Prototype Pollution to RCE
可能受到影响的代码
想象一个真实的JS使用以下代码:
const { execSync, fork } = require('child_process');
function isObject(obj) {
console.log(typeof obj);
return typeof obj === 'function' || typeof obj === 'object';
}
// Function vulnerable to prototype pollution
function merge(target, source) {
for (let key in source) {
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}
function clone(target) {
return merge({}, target);
}
// Run prototype pollution with user input
// Check in the next sections what payload put here to execute arbitrary code
clone(USERINPUT);
// Spawn process, this will call the gadget that poputales env variables
// Create an a_file.js file in the current dir: `echo a=2 > a_file.js`
var proc = fork('a_file.js');通过环境变量实现PP2RCE
PP2RCE 意味着 原型污染到远程代码执行(Remote Code Execution)。
根据这个解说,当使用 child_process 中的某个方法(如 fork 或 spawn 或其他方法)生成一个 进程 时,它会调用方法 normalizeSpawnArguments,这个方法利用 原型污染小工具来创建新的环境变量:
污染 __proto__
__proto__请注意,由于node的child_process库中的normalizeSpawnArguments函数的工作方式,当调用某些内容以为进程设置新的环境变量时,你只需要污染任何内容。
例如,如果你执行__proto__.avar="valuevar",进程将被生成一个名为avar,值为valuevar的变量。
然而,为了使环境变量成为第一个变量,你需要污染.env属性,并且(仅在某些方法中)该变量将成为第一个变量(从而允许攻击)。
这就是为什么在以下攻击中**NODE_OPTIONS**不在.env中的原因。
DNS 交互
使用以下有效载荷,可以滥用我们之前讨论过的 NODE_OPTIONS 环境变量,并通过 DNS 交互检测是否起作用:
或者,为了避免WAF要求域名:
PP2RCE漏洞child_process函数
在这一部分中,我们将分析child_process中的每个函数,以执行代码并查看是否可以使用任何技术来强制该函数执行代码:
强制执行Spawn
在之前的示例中,您看到了如何触发一个功能,该功能需要调用spawn(用于执行某些操作的child_process的所有方法都会调用它)。在之前的示例中,这是代码的一部分,但如果代码没有调用它呢。
控制require文件路径
在这个其他解释中,用户可以控制文件路径,其中将执行require。在这种情况下,攻击者只需要找到系统中将在导入时执行spawn方法的.js文件。
一些常见文件导入时调用spawn函数的示例包括:
/path/to/npm/scripts/changelog.js
/opt/yarn-v1.22.19/preinstall.js
查找下面的更多文件
以下简单脚本将搜索来自child_process的调用,而不带任何填充(以避免显示在函数内部的调用):
相对路径加载 - 1
如果加载的是相对路径而不是绝对路径,您可以让节点加载不同的路径:
相对路径 require - 2
```javascript const { fork } = require('child_process'); console.log("Hellooo from malicious"); fork('/path/to/anything'); ``` #### 相对路径 require - 3
类似于前一个示例,这个漏洞在这篇文章中被发现。
VM Gadgets
在论文https://arxiv.org/pdf/2207.11171.pdf中还指出,可以利用**vm库的某些方法中的contextExtensions的控制作为一个gadget。
然而,就像之前的child_process方法一样,在最新版本中已经被修复**。
Fixes & Unexpected protections
请注意,如果正在访问的对象的属性是undefined,则原型污染会起作用。如果在代码中为该属性设置了一个值,则无法覆盖它。
在2022年6月,从此提交中,变量options不再是{},而是**kEmptyObject。这样可以防止原型污染影响options的属性以获取RCE。
至少从v18.4.0开始,这种保护已经实施**,因此影响这些方法的spawn和spawnSync利用(如果未使用options)不再起作用!
在此提交中,还在某种程度上修复了vm库中**contextExtensions的原型污染**,将选项设置为**kEmptyObject而不是{}**。
其他 Gadgets
References
最后更新于