构建模块化调用图以实现NodeJS应用的安全扫描

VSole2022-06-29 06:39:48
原文标题:Modular Call Graph Construction for Security Scanning of Node.js Applications
原文作者:Benjamin Barslev Nielsen, Martin Toldam Torp, Anders Møller
原文链接:https://cs.au.dk/~amoeller/papers/jam/paper.pdf
原文来源:ISSTA'21
笔记作者:NING@SecQuan
笔记小编:cherry@SecQuan

1 背景介绍

现如今大多数的 Node.js 应用都会采用大量的第三方库来帮助实现其功能,据调查显示,一个典型的 Node.js 应用 90% 的代码都来自第三方库。而这些第三方库的来源是当下最大的软件库 NPM ,其拥有超过 100 万个 JavaScript 包,但不幸的是在这些包直接存在着严重的依赖关系,高达 40% 的 npm 包依赖的代码至少包含一个公开漏洞,因此如何解决 Node.js 应用的安全性检测是一个十分重要的问题。

我们期望的安全检测是当程序依赖于包含已知安全漏洞的库时能够给出警告。当下安全检测工具主要有 Dependabot, npm audit, Snyk 等,但这些工具有一个共同的特性,就是只从 package.json 中寻找包依赖,不看程序源代码,无法判断程序是否真的使用了库中有漏洞的部分,导致出现很多 false-positive(假阳性),因此本文的作者便提出了构建调用图的方法来做更加准确的安全检测。

2 论文主要贡献

作者该篇文章主要做出了以下贡献:

  • 提出了一种分析工具 JAM ,可以有效地将 JavaScript 项目构建相应的模块化调用图
  • 提出了一种概念验证的工具,能够根据调用图进行安全扫描
  • 对比 npm audit ,在 12 个 Node.js 应用的扫描当中,该工具能够减少 81% 的假阳性,并且在重用调用图的基础上,分析时间也大大减小
  • 对比当前 SOTA 模型 js-callgraph ,该方法在精度、准度和分析时间都有很大提升

3 动机及挑战

针对一个 npm 应用 writex 1.0.4,作者首先使用 npm audit 工具进行了安全扫描并获取了 5 个不同的安全建议,但是在作者手动进行源码验证时,发现其中只有一个安全建议是有效的,因此发现该工具存在极大的假阳性。而之所以会存在上述情况,以下述代码为例:

图3-1 示例代码

该代码片段首先 lib.js 模块执行了一个 filter 函数,而该函数以 iteratee 函数作为参数,并返回另一个函数。这个函数通过接收 arr 作为参数,并遍历其中元素分别传递给 iteratee 函数,最终返回一个经过 iteratee 函数处理过的数组。

通过该片段可以发现,JS 代码极为灵活,存在着多种的调用方式,因此直接静态分析是比较困难的,主要概括为:

  • 模块公共接口是通过 module.exports 对象来写入属性,以完成动态构造
  • 存在高阶函数的使用,即函数作为参数或者返回值
  • 构造函数的直接使用

4 方法

整个方法共分为三个阶段。这里可能不能很好的讲解清楚,具体可以详细看一下论文。这里一些专有名词的翻译如下:

  • module summary:模块概要
  • call edges:调用边
  • VersionRange:版本范围
  • Scanner:扫描器
  • API-pattern:API 模式
  • Access Path:可达路径

4.1 模块概要构建

1.构建概要

为每个模块(file f)构造一个概要 ,而不考虑模块之间的调用关系, 包含:

其中:Loc = ,Prop:属性名,Var:变量名/参数,Exp:表达式

图4-1 AccessPath

2.表达式分析

对文件中每个表达式进行如下操作:别名分析、可达路径分析、概要构建。

4.2 调用图构建

1. 合并概要

合并 Node.js 应用所有模块的模块概要,例如:

2. 调用图定义 

其中 V:各函数定义的Loc,E:调用边, :标注函数调用的访问路径,用于解析对高阶函数的参数调用等。

3. 调用图生成

提出一些约束规则,通过迭代地求解规则生成的约束来求解调用图。

4.3 安全检测

1. 建立 npm 漏洞库中已知安全漏洞的模式

图4- API模式

2. 如果待分析应用依赖于版本范围内某个包

图4- findNodes算法

findNodes:根据 API 模式和模块概要查找存在漏洞的函数在 f 中的位置。

3. 扫描器从入口点检查这些函数是否在应用程序的调用图中可达

如果可达,系统给出警告信息和调用路径。

5 评估实验及分析

实验选择了 12 个 Node.js 应用,这些应用使用 npm audit 工具检测往往存在 1 个及以上的警告,下面通过回答三个问题来证实其工具的有效性。

RQ1: 与安全检测工具 npm audit 对比怎么样呢?

图5-1 安全检测结果对比

  • precision: 从 24% 提升到 61%
  • recall: 实现 100%
  • FP: 下降了 81%

RQ2&RQ3: 与调用图构建工具 js-callgraph 对比怎么样呢?

图5-2 调用图构建结果对比

这里的 precision 指的是只有唯一被调用者的调用点所占的百分比。

  • precision: 从 58.64% 提升到 84.35%
  • recall: 从 48.16% 提升到 98.62%
  • analysis time:大幅缩减至 0.1 秒级

6 总结与展望

作者针对其方法所带来的贡献进行了简要概括但未提及相关的不足,而针对未来针对调用图可能的研究目标包括:

  • 代码变化的影响分析
  • IDE工具中的代码导航和重构

个人认为从实验数据来看,本文所使用的图构建方法相比现有技术有着很大的提升,在召回率、精度、时间方法都取得了巨大的进步,是值得我们学习思考的;此外在 FP 上面的提升也能够帮助我们更好的解决一些问题,整体方法具有极好的效果,但实验个人认为还不够丰富,并且其中一些小问题可能还需要继续说明一些。

函数调用node
本作品采用《CC 协议》,转载必须注明作者和本文链接
由此可以推测,之前找到的main.node,可能就是解密模块。此时找到了AES的算法常量,前两个是重复的,可能是插件问题。只能去问度娘了,搜索一下AES加密解密原理与 C 实现代码。
高达40%的npm包依赖的代码至少包含一个公开漏洞,因此如何解决 Node.js 应用的安全性检测是一个十分重要的问题。
NPM上发布了170多万个Node.js库,以促进软件开发。正如对比安全所揭示的,第三方库出现在当今软件的大多数(79%)中。然而,任何事物都有两面性。虽然使用库可以减少开发成本和时间,但这些集成库在实践中对软件生态系统构成了新的安全威胁,这些库中的漏洞可能会使依赖它们的软件不断面临安全风险。之前的工作已经调查了整个NPM生态系统的脆弱性影响,而他们的方法要么只是静态地考虑直接依赖性,或者基于依赖
漏洞信息CVE-2021-26411 该漏洞存在于iexplore.exe mshtml.dll模块,在JS9引擎处理dom对象时,由于未对nodevalue对象的有效性做判断,所导致的UAF漏洞,该漏洞可实现RCE。
最近遇到webpack类型的网站越来越多,所以在B站学习了一下,今天来实战一波。
target_func: sark.Function 类型,表示要查找交叉引用关系的目标函数对象。max_depth: int 类型,表示查找引用关系的最大深度。② 然后根据 include_data_xref 的设置,获取该函数中所有的引用 refes。③ 遍历函数的所有引用 ref,如果该引用 ref 指向目标函数,则在有向图 G 中通过 add_edge 函数添加一条从当前函数到目标函数的边,并返回 True。④ 如果引用指向另一个函数,则递归调用 find_cross_refs 函数查找两个函数之间的交叉引用关系。⑤ 如果所有引用遍历完,仍然没有找到交叉引用,则返回 False。
本篇针对该JS中的字符串混淆进行还原。字符串是如何混淆的解密方式想要对字符串反混淆就要先分析该样本是如何对字符串进行混淆的。而处于全局作用域的_0x1f1a68实际上也是对另一个函数的调用。
目前的检测器以JavaScript为唯一的目标语言,然而忽略了WebAssembly可能带来的攻击。论文提出了第一个通过将计算的部分移动到WebAssembly中来逃避静态JavaScript恶意软件检测的技术。技术的核心是将JavaScript中实现恶意行为的片段翻译为WebAssembly。通过实验评估,该方法可以有效逃逸最先进的基于学习的静态恶意软件检测。
字符串是 JavaScript 中的重要数据类型
企业安全规划建设过程中,往往会涉及到开发的代码安全,而更多可以实现落地的是源代码安全审计中,使用自动化工具代替人工漏洞挖掘,并且可以交付给研发人员直接进行安全自查,同时也更符合SDL的原则,此外可以显著提高审计工作的效率。
VSole
网络安全专家