cve20113192漏洞利用
CVE-2011-3192 漏洞利用
Apache HTTP Server 的洞利 ByteRange 过滤器在处理 Range 请求头时,没有对请求的洞利 range 数量做上限限制。攻击者只要发送一个包含大量 range 声明的洞利 HTTP 请求,就能让服务端为每个 range 分配内存并生成对应的洞利 multipart 响应体。一个请求,洞利几百个 range,洞利内存瞬间被吃光。洞利这就是洞利 CVE-2011-3192 的底层逻辑——不是代码执行,是洞利拒绝服务,而且粗暴到令人发指。洞利
我第一次在实验环境里复现这个漏洞时,洞利用的洞利是 Apache 2.2.17。写了个 Python 脚本,洞利构造 1300 个 range,洞利每个 range 请求 1 字节,洞利指向同一个大文件。发出去不到两秒,httpd 进程的 RSS 从 20MB 飙到 1.8GB。机器开始 swap,SSH 卡得敲一个字符要等三秒。那种感觉就像你明明只是轻轻推了一下门,整栋楼却塌了。
Range 头是怎么变成武器的
HTTP/1.1 允许客户端用 Range: bytes=0-0,1-1,2-2,... 这种形式请求文件的多个片段。服务端收到后,会返回 206 Partial Content,响应体是 multipart/byteranges 格式。每个 range 对应一个独立的 part,每个 part 都有自己的头部。问题出在 Apache 的实现上:它会把所有 range 先解析、排序、合并,然后逐个生成响应。内存占用与 range 数量成正比,而请求体本身可能只有几 KB。
一个典型的攻击请求长这样:
GET /bigfile.iso HTTP/1.1 Host: victim.com Range: bytes=0-0,1-1,2-2,...,1299-1299 Connection: close 1300 个 range,每个只请求 1 字节。服务端却要为每个 range 准备响应头、计算偏移、分配缓冲区。更致命的是,Apache 默认不会拒绝这种请求。它老老实实地处理,直到内存耗尽。
为什么这个漏洞特别讨厌
它不需要认证。不需要上传文件。不需要任何特殊权限。一个普通的 GET 请求就能打瘫服务器。2011 年 8 月漏洞公开后,大量共享主机和 VPS 遭殃。我认识的一个运维当时管着几十台 Apache,补丁还没打,攻击脚本已经在 GitHub 上满天飞。他凌晨三点被监控告警吵醒,发现所有机器都在疯狂 swap,日志里全是同一个 IP 发来的畸形 Range 请求。
更麻烦的是,Apache 的 mod_deflate 有时候会加剧问题。如果启用了压缩,multipart 响应体在压缩前就已经在内存里膨胀了一轮。等于说,攻击者用几 KB 的请求,换来了服务端几百 MB 甚至 GB 级的内存分配。放大倍数高得离谱。
利用代码其实很简单
用 Python 写个 PoC 不超过二十行。核心就是拼 Range 头:
import socket ranges = ",".join([f"{ i}-{ i}" for i in range(1300)]) req = f"GET /largefile HTTP/1.1\r\nHost: target\r\nRange: bytes={ ranges}\r\nConnection: close\r\n\r\n" s = socket.socket() s.connect(("target", 80)) s.send(req.encode()) s.close() 就这么点东西。没有 shellcode,没有绕过 ASLR,没有堆喷射。纯粹的资源耗尽。你甚至可以用 curl 配合 -r 参数循环生成,但那样太慢。直接拼字符串发原始 socket 最快。
我试过在局域网里用单台笔记本打一台 Apache 2.2.19,并发 50 个这样的请求,目标机器 30 秒内失去响应。如果带宽再大点,并发再高点,效果更明显。这不是什么精妙的漏洞利用,就是蛮力,但偏偏有效。
修复方式和遗留问题
Apache 在 2.2.20 和 2.3.15 里加了 MaxRanges 指令,默认限制 range 数量为 200。超过就返回 200 完整响应或者 416。补丁本身不复杂,但部署是个问题。2011 年那会儿,很多发行版的更新包滞后了好几周。有些老系统干脆没得升,只能靠前端反向代理过滤 Range 头。
我后来在几个客户环境里见过更野的缓解措施:有人用 mod_rewrite 直接拒绝所有带逗号的 Range 请求。简单粗暴,但确实能挡住大部分自动化攻击。代价是正常的断点续传和多段下载也废了。安全跟功能之间的取舍,有时候就是这么难看。
这个漏洞现在看已经过时了,Apache 新版本早就默认限制了 range 数量。但它是个很好的教材——一个看似无害的协议特性,实现时少加了一个边界检查,就能变成远程 DoS 的入口。写代码的人当时大概觉得,谁会发几千个 range 啊?攻击者会。
```








