介绍Snyk和CISPA为更大的利益进行合作

262 阅读4分钟

当学术界和软件业合作时,会发生伟大的事情!今天,我们想分享一个关于我们最近与CISPA亥姆霍兹信息安全中心(德国的一个大科学机构)合作的故事。

早在一月份,Cris Staicu博士(CISPA终身教职),就他对NodeJS和JavaScript的研究与我们联系。Staicu和他的团队进行的研究集中在JavaScript和NodeJS环境中有趣的安全问题,如原型污染漏洞、JS沙盒逃逸和NodeJS本地扩展中的低级C/C++漏洞。

与CISPA一起,我们能够确认一些不那么直接的漏洞,将它们报告给维护者进行修复,并指定CVE和发布顾问。

在这篇文章中,我们将带领大家了解我们在CISPA中发现的几个漏洞,同时也呼吁其他学术机构与我们合作,使开源世界对每个人都更安全。

NodeJS沙盒逃逸小工具

我们研究的第一个漏洞是沙盒逃逸漏洞。

对于那些不熟悉 "沙盒 "一词的人来说,它指的是一个环境、进程或机器,在那里我们可以执行一些东西而不用担心安全影响。例如,当我们在处理未经消毒的客户提供的代码或文件时。

在这种情况下,Cris的团队发现了一个具有可绕过沙箱的JS库。所报告的库,notevil 及其衍生物argencoders-notevil ,允许Cris的团队通过滥用原型污染漏洞绕过沙箱。

这个问题的PoC看起来是这样的。

var notevil = require('notevil')

notevil(`  
Object.defineProperty(({})[["__proto__"]][["__proto__"]], 'polluted', {
  value: 'success'
});`);

console.log(polluted); // prints "success"

虽然这个PoC乍看之下并无害处,但同一库中的一个类似的漏洞以前曾被报道过,在NodeJS环境中可能导致RCE,在浏览器环境中可能导致XSS。

由于该库已经被废弃(但仍有很多人在使用),Cris的团队需要我们帮助发布CVE并通知维护者。如果你不知道,Snyk是一个官方的CNA,允许我们在需要时发布CVE.因此,我们发布了CVE-2021-23771,让未来的开发者意识到这个漏洞。

本地NodeJS扩展中的类型混淆

由于CISPA的重点是NodeJS应用程序和NodeJS引擎的C扩展之间的类型混淆漏洞,我们在这个主题上进行了合作。CISPA的大多数类型混淆实验都导致了V8引擎的崩溃,所以双方都想深入研究并更好地了解这个问题。

作为一个例子,让我们使用libxmljs 库。如果你不熟悉,libxmljs 是用于XML解析的,并在幕后采用了本地的libxml 二进制。

下面是该库的一个基本使用例子的片段,是从其README中复制的。

// As copied from libxmljs readme
var libxmljs = require("libxmljs");
var xml =  '<?xml version="1.0" encoding="UTF-8"?>' +
           '<root>' +
               '<child foo="bar">' +
                   '<grandchild baz="fizbuzz">grandchild content</grandchild>' +
               '</child>' +
               '<sibling>with content!</sibling>' +
           '</root>';

var xmlDoc = libxmljs.parseXml(xml); // you can now query the document

然而,我们能够通过下面的PoC使整个应用程序崩溃。

let libxmljs = require("libxmljs");
let xml = {toString: 23};
try { 
    libxmljs.parseXml(xml);
} catch(e) {
    // never executed because of the hard crash
}

尽管有try/catch块的存在,但由于应用程序可以通过用户输入而崩溃,我们面临着一个DoS入口点。

运行前一个块的代码将产生以下堆栈跟踪。

FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal.
 1: 0xb23a90 node::Abort() [node]
 2: 0xa3823c node::FatalError(char const*, char const*) [node]
 3: 0xd13ffa v8::Utils::ReportApiFailure(char const*, char const*) [node]
 4: 0x7fa0bc5eec9b libxmljs::XmlDocument::FromXml(Nan::FunctionCallbackInfo<v8::Value> const&) [/opt/node_modules/libxmljs/build/Release/xmljs.node]
 5: 0x7fa0bc5ea208  [/opt/node_modules/libxmljs/build/Release/xmljs.node]
 6: 0xd7019e  [node]
 7: 0xd715bf v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [node]
 8: 0x16138f9  [node]
Aborted

用GDB的进一步调试帮助我们了解到,底层引擎期望得到一个String类型的参数,但是--正如我们所发现的--当传递一个对象时,它将尝试对其进行字符串化。

在上面的例子中,toString 方法是不可调用的(因为它只是一个数字)。V8无法处理这个问题,并引发了一个异常。然而,由于这个异常是在V8中,所以try/catch块是无效的--导致整个应用程序崩溃。

我们与CISPA一起接触了维护者,并负责任地披露了该漏洞,将其作为CVE-2022-21144进行跟踪。

呼吁合作

我们希望与更多像CISPA这样的学术机构合作,与Snyk合作有几个有益的优势。发现漏洞是一回事,但披露漏洞是另一回事--特别是当漏洞在开源库中时。我们专门的分析员和研究人员团队将帮助你验证和了解特定漏洞的全部影响,而且我们的程序保证漏洞将被负责任地、谨慎地和专业地披露。而且,由于Snyk是CNA,我们有一个特殊的跟踪系统,可以同步到报告人和维护者,使双方随时了解情况。