Apache HTTP Server混淆攻击:挖掘隐藏语义歧义的安全漏洞
故事是如何开始的?
今年年初,我开始寻找下一个研究目标。作为总是希望挑战影响整个互联网大目标的研究员,我开始研究一些看似复杂的主题或有趣的开源项目,如Nginx、PHP等。在仔细阅读这些代码时,我回忆起去年年中曾短暂看过Apache HTTP Server源代码的经历!尽管当时由于工作安排没有深入阅读代码,但已经从它的编码风格上"闻"到了一些不太好的味道。
为什么Apache HTTP Server闻起来有问题?
Apache HTTP Server是一个由"模块们"构建起来的世界。整个Httpd服务需要由数百个小模块共同合作才能完成客户端的HTTP请求,官方列出的136个模块中约有一半是默认启用或经常被使用的模块!
更令人惊讶的是,这么多模块在处理HTTP请求时,要共同维护一个巨大的request_rec结构。这个结构包含处理HTTP时用到的所有元素,所有模块都依赖这个结构进行同步、沟通和数据交换。这个内部结构会在所有模块间传递,每个模块都可以随意修改这个结构上的任意值!
新的攻击面:混淆攻击
基于前面的思考,我们开始专注于研究这些模块间的"关系"和"交互作用"。如果有一个模块不小心修改了它觉得不重要但对另一个模块至关重要的结构字段,就可能影响该模块的判断。甚至更进一步,如果Apache HTTP Server对这些结构的定义不够精确,导致不同模块对同一个字段的理解存在根本性不一致,都可能产生安全风险!
从这个出发点我们发展出了三种不同的攻击,由于这些攻击都与模块对结构字段的误用有关,因此将这个攻击面命名为"混淆攻击":
1. 文件名混淆
基本手法1-1:截断
- 路径截断:通过问号截断RewriteRule后面的路径
- 误导RewriteFlag分配:利用截断行为将RewriteFlag设置到不属于它们的请求上
基本手法1-2:ACL绕过
通过mod_proxy与其他模块对r->filename理解的不一致,绕过基于文件系统的访问控制模块。
2. 文档根目录混淆
对于任意的RewriteRule,Httpd总是会尝试开启带有DocumentRoot的路径和不带的路径!这使得我们能够"故意"访问Web Root以外的路径。
基本手法2-1:服务器端源代码泄露
- 泄露CGI源代码
- 泄露PHP源代码
基本手法2-2:本地小工具操纵
- 信息泄露
- XSS攻击
- 本地文件包含
- 服务器端请求伪造
- 远程代码执行
基本手法2-3:从本地小工具越狱
- 利用符号链接跳出限制目录
- 通过Redmine实现RCE
3. 处理程序混淆
利用Apache HTTP Server从上古时期架构遗留的技术债,特别是AddType和AddHandler之间的混淆。
基本手法3-1:覆盖处理程序
- 覆盖处理程序泄露PHP源代码
- 其他高级利用(暂未完全披露)
基本手法3-2:调用任意处理程序
- 信息泄露
- 脚本误解释
- 完整SSRF
- 访问本地Unix Domain Socket
- 远程代码执行
发现的漏洞
通过混淆攻击面,我们发现了9个新漏洞:
- CVE-2024-38472:基于Windows UNC的SSRF
- CVE-2024-39573:基于RewriteRule前缀可完全控制的SSRF
- CVE-2024-38477:通过恶意请求导致拒绝服务
- CVE-2024-38476:使用可利用的后端应用输出运行本地处理程序
- 等其他5个CVE
实际影响
这些漏洞都通过官方安全信箱回报,并由Apache HTTP Server团队在2024-07-01发布安全性通报以及2.4.60更新。由于这是针对Httpd架构及其内部机制的新攻击面,很多修复由于其历史架构无法向下兼容,对于运行许久的正式服务器来说修复并不容易。
结论
维护一个开源项目确实很困难,特别是在让用户方便的同时兼顾旧版本的兼容性。Apache HTTP Server开发过程必须小心翼翼地踩在一堆遗留代码和技术债上。这项研究展示了即使是最成熟和广泛使用的软件也可能存在深层的架构问题,需要持续的安全审计和改进。