在渗透测试与漏洞赏金(Bug Bounty)实战中,Nginx 的配置往往是攻击面的重要来源。不当的 proxy_pass 和 alias 指令配置,可能导致路径穿越漏洞,使得攻击者能够绕过预期的访问控制,读取到内部文件或访问非授权的后端服务。本文将通过一个完整的实战环境搭建,带你深入理解这两种常见的 Nginx 配置风险,并学习如何对其进行安全测试。
环境搭建
首先,你需要一个基础的 Nginx 环境。我们假设你已在 Ubuntu 系统上安装并启动了 Nginx。
接下来,修改 Nginx 配置文件(通常为 /etc/nginx/sites-available/default 或类似路径),在 server 块中追加以下配置:
# 漏洞测试1:alias指令(静态文件遍历)
location /static {
alias /var/www/html/static_files/; # 注意:alias目录与location名称不同
}
# 漏洞测试2:proxy_pass指令(反向代理穿透)
location /api {
proxy_pass http://localhost:8080/v1/; # 转发到本地8080端口的/v1/路径
}
保存配置后,执行以下命令使配置生效:
sudo nginx -t # 检查配置语法
sudo systemctl reload nginx # 热重载配置
准备测试文件
我们创建漏洞复现所需的文件和目录。
-
为 alias 指令创建测试文件:
创建 alias 指令指向的目录,并在其上级目录放置一个“敏感”文件。
# 创建alias指令的测试目录和文件
sudo mkdir -p /var/www/html/static_files/secret
echo "public info" | sudo tee /var/www/html/static_files/public.txt
echo "info secret 666!" | sudo tee /var/www/html/secret/db_pass.txt
-
为 proxy_pass 指令创建后端服务:
创建一个内部 API 服务目录和文件,并用 Python 启动一个简易 HTTP 服务器。
# 创建proxy_pass指令的后端测试文件
mkdir -p ~/internal-api/v1
echo '{"status": "public API"}' > ~/internal-api/v1/data.json
echo '{"admin": "internal API"}' > ~/internal-api/admin.json
# 启动后端服务(端口8080)
cd ~/internal-api && python3 -m http.server 8080 &

环境准备就绪,下面开始进行漏洞测试。
漏洞测试与复现
1. 测试 alias 指令漏洞(静态文件遍历)
按照正常逻辑,访问 /static/public.txt 应该能读取到公开文件。但让我们看看是否存在路径穿越的可能。
# 正常请求
curl http://127.0.0.1/static/public.txt
# 恶意请求(路径穿越到上级目录)
curl http://127.0.0.1/static../secret/db_pass.txt


预期结果:
- 正常请求成功返回公开文件内容 “public info”。
- 恶意请求成功返回敏感文件内容 “info secret 666!”,这证明了
alias 配置存在目录遍历风险。
2. 测试 proxy_pass 指令漏洞(反向代理穿透)
proxy_pass 指令常用于构建反向代理。接下来我们测试其配置缺陷。
# 正常请求(预期返回public API)
curl http://127.0.0.1/api/data.json
# 恶意请求(路径穿越到上级目录)
curl http://127.0.0.1/api../admin.json


结果分析:第二个请求成功访问到了本应只在内部网络(http://localhost:8080/admin.json)才能访问的 admin.json 文件。这证明了漏洞的存在。
漏洞原理分析
让我们从日志层面深入理解漏洞的发生过程。
查看 Nginx 访问日志:

日志显示,Nginx 接收到的请求路径是 /api../admin.json,它忠实地将这个路径处理后转发给了后端。
查看后端 Python 服务日志:

请注意上图红框中的日志行。后端服务收到的请求路径是 /v1/../admin.json。这是因为我们的配置 proxy_pass http://localhost:8080/v1/; 在转发时,会将 location /api 匹配的部分(即 /api)替换为 http://localhost:8080/v1/。
所以,攻击者请求的 /api../admin.json 被处理为:
- Nginx 移除
/api,剩下 ../admin.json。
- 与
proxy_pass 的目标 URL 拼接:http://localhost:8080/v1/ + ../admin.json = http://localhost:8080/v1/../admin.json。
- 路径规范化后,
/v1/../admin.json 等价于 /admin.json,从而访问到了后端服务的上级目录文件。
问题的关键在于 location 匹配与 proxy_pass 路径拼接的规则。当 proxy_pass 指令的 URL 以斜杠 / 结尾时,情况尤为特殊。回顾一下我们的问题配置(为清晰起见,修改了后端地址):
location /api {
proxy_pass http://apiserver/v1/; # 注意结尾有斜杠
}
预期行为:所有以 /api 开头的请求(如 /api/user)应转发到后端服务器 http://apiserver/v1/user。
实际风险:由于 /api 这个 location 末尾没有斜杠,而 proxy_pass 的路径有斜杠,在处理包含 ../ 的恶意路径时,会产生非预期的拼接结果。
漏洞修复与安全配置
修复的关键在于规范 location 的匹配规则。对比漏洞配置与安全配置:
存在风险的配置 (漏洞来源):

修复后的安全配置:

主要改动是将 location /static 和 location /api 修改为 location /static/ 和 location /api/,即在 location 指令后也添加了尾随斜杠 /。
重启 Nginx 服务:
sudo systemctl restart nginx
再次尝试访问之前的敏感路径:


可以看到,两个恶意请求现在都返回了 404 错误,漏洞已被修复。这是因为 location /static/ 只会匹配以 /static/ 开头的路径,/static../ 无法匹配该规则,Nginx 会将其交给其他 location(如 location /)处理,通常会导致 404。
如何检测此类漏洞
在安全审计和渗透测试中,如何快速识别此类潜在风险呢?这里提供一个简单的检测思路。
假设目标 Nginx 配置存在以下有问题的模式:
location /api {
proxy_pass http://apiserver/v1/;
}
检测方法:比较以下两个请求的响应是否相同。
http://target.com/api/user (正常请求)
http://target.com/apiuser (恶意构造,去掉了 /api 后的斜杠视觉分隔)
为什么可以这样检测?
对于第一个请求,Nginx 移除 /api,剩余 /user,拼接后转发为:http://apiserver/v1//user(双斜杠会被服务器合并为单斜杠)。
对于第二个请求,路径 /apiuser 无法匹配 location /api(因为它不是以 /api 开头),因此不会被该 location 处理,可能由默认 location / 处理,转发到完全不同的路径,例如 http://apiserver/apiuser。
如果两者返回相同结果,则强烈暗示可能存在路径标准化或拼接问题,攻击者可以通过构造 ../ 进行路径穿越。例如,请求 http://target.com/api../admin 可能被转发到 http://apiserver/v1/../admin,即 http://apiserver/admin,从而访问到非授权接口。
在日常的安全测试中,应当密切关注 Web 路径中出现的诸如 /api、/proxy、/static 等关键词,它们往往是反向代理或资源映射的入口点,也是挖掘此类高价值漏洞的“黄金地标”。
深入理解这些中间件的配置细节,是提升安全研究能力的关键一步。希望本文的实战演练能帮助你更好地把握Nginx的安全配置要点。如果你对这类网络与系统安全话题感兴趣,欢迎在云栈社区与更多开发者交流探讨。