一、漏洞本质:HTTP协议解析的”双刃剑”
HTTP协议通过CRLF(回车符\r+换行符\n,即%0d%0a)分隔响应头与响应体,这种设计本意是提升可读性,却成为攻击者的突破口。当Web应用未对用户输入进行严格过滤时,攻击者可构造包含CRLF的恶意输入,使服务器将单一响应拆分为多个独立响应。
典型攻击流程:
- 用户提交包含
CRLF的参数(如header=X-Test:%0d%0aSet-Cookie:evil=1) - 服务器直接将该参数写入响应头,解析为:
X-Test:Set-Cookie: evil=1
- 攻击者成功注入新头部字段,后续响应内容完全可控
二、攻击面扩展:从头部注入到协议劫持
该漏洞的危害远超简单的头部注入,攻击者可实现多种高级攻击:
1. 跨用户会话篡改
通过注入Set-Cookie字段覆盖合法会话ID,例如:
GET /vulnerable?param=test%0d%0aSet-Cookie:%20sessionid=attacker
导致后续所有用户请求携带攻击者控制的会话ID。
2. Web缓存投毒
在CDN或反向代理场景下,攻击者可构造恶意响应:
HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nX-Cache-Inject: <script>alert(1)</script>\r\n\r\n<html>...
使缓存服务器存储并分发被污染的响应,影响所有访问该资源的用户。
3. 协议混淆攻击
结合HTTP/2协议特性,攻击者可构造畸形帧序列,导致代理服务器崩溃或状态混乱。某主流云服务商的负载均衡器曾因此漏洞出现服务中断。
三、防御技术矩阵:多层级防护策略
1. 输入验证与净化
核心原则:禁止所有非预期的CRLF字符进入响应流。
-
白名单过滤:仅允许字母、数字及特定符号(如
-_.)import redef sanitize_input(user_input):return re.sub(r'[\r\n]', '', user_input)
-
URL编码转换:将
%0d%0a等编码形式转换为安全字符String safeInput = URLEncoder.encode(rawInput, "UTF-8").replaceAll("\\+", "%20").replaceAll("%0D|%0A", "");
2. 框架级防护
主流Web框架均提供安全配置选项:
-
Spring Security:通过
HttpHeaderSecurity过滤器自动处理@Beanpublic FilterRegistrationBean<HttpHeaderSecurity> httpHeaderSecurityFilter() {return new HttpHeaderSecurity().headers().xssProtection().and().frameOptions().and().hstsStrict(true);}
-
Django:启用
SECURE_BROWSER_XSS_FILTER和SECURE_CONTENT_TYPE_NOSNIFF
3. 协议层加固
- HTTP/1.1严格模式:禁用
Transfer-Encoding: chunked与Connection: keep-alive的组合使用 - HTTP/2优先:强制使用二进制帧传输,天然免疫CRLF注入
- TLS 1.3强制:通过加密通道减少中间人攻击风险
4. 运行时防护
-
WAF规则配置:检测响应头中的非法换行符
SecRule RESPONSE_HEADERS "[\r\n]" "id:950100,phase:4,block,t:none,msg:'HTTP Response Splitting Attempt'"
-
RASP技术:在应用运行时动态检测异常响应构造
// 示例:Node.js RASP钩子app.use((req, res, next) => {const originalWrite = res.write;res.write = function(chunk) {if (chunk.toString().includes('\r\n')) {console.warn('Potential CRLF injection detected');return;}return originalWrite.apply(res, arguments);};next();});
四、典型漏洞案例分析
CVE-2022-37436:某开源代理软件的mod_proxy模块漏洞
- 根本原因:未对后端返回的
Location头进行CRLF过滤 - 攻击向量:
GET /proxy?url=http://attacker.com%0d%0aSet-Cookie:%20sid=evil
- 修复方案:升级至2.4.55+版本,或手动应用补丁:
// 补丁核心逻辑if (strstr(header_value, "\r\n")) {ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,"Illegal CRLF sequence in proxy header");return HTTP_BAD_REQUEST;}
五、安全开发最佳实践
- 最小权限原则:代理服务器应限制可修改的响应头字段
- 防御性编程:所有动态生成的HTTP头必须经过净化
- 安全测试:
- 使用
Burp Suite的Intruder模块进行模糊测试 - 编写自动化检测脚本:
# 示例:curl检测脚本curl -s -I "http://target.com/vuln?param=test%0d%0aX-Test:1" | grep "X-Test"
- 使用
- 日志监控:记录所有包含换行符的响应头尝试
结语
HTTP响应拆分漏洞的本质是协议设计与实现的安全权衡问题。开发者需建立”纵深防御”意识:在输入验证、框架配置、协议选择、运行时检测等多个层面构建防护体系。随着云原生架构的普及,结合容器安全、服务网格等技术,可进一步提升Web应用的整体安全性。建议定期使用自动化工具(如OWASP ZAP)进行安全扫描,并关注CWE-113等通用漏洞列表的更新动态。