Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
HTTP3ONSTEROIDS — HTTP3ONSTEROIDS - A research on CVE-2023-25950 where HAProxy's HTTP/3 implementation fails to block a malformed HTTP header field name. | Kitploit
Ferramentas/GitHubGitHub/dhmosfunk/http3onsteroids
Vulnerability AnalysisWeb Application ExploitationLearning & EducationLabs & Practice
GitHubdhmosfunk/http3onsteroids

HTTP3ONSTEROIDS

HTTP3ONSTEROIDS - A research on CVE-2023-25950 where HAProxy's HTTP/3 implementation fails to block a malformed HTTP header field name.

Ver Repositório
112há 1 anoAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

Índice

  • Descrição da Vulnerabilidade
    • Revisão do Código Fonte
  • Configuração do Laboratório
    • Identificando o problema
  • Referências

Descrição da Vulnerabilidade

A implementação HTTP/3 do HAProxy falha em bloquear um nome de campo de cabeçalho HTTP malformado, e quando implantado na frente de um servidor que processa incorretamente este cabeçalho malformado, pode ser usado para conduzir um ataque de contrabando de requisição/resposta HTTP. Um atacante remoto pode alterar a requisição de um usuário legítimo. Como resultado, o atacante pode obter informações sensíveis ou causar uma condição de negação de serviço (DoS).

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

Revisão do Código Fonte

Uma abordagem muito boa antes de iniciar qualquer pesquisa sobre CVEs é começar lendo a descrição da vulnerabilidade e depois verificar se o(s) commit(s) de correção estão disponíveis.
No meu caso, o commit estava disponível, e é evidente que os desenvolvedores do HAProxy esqueceram de incluir as verificações do RFC 9114 4.1.2. Malformed Requests and Responses durante a análise dos cabeçalhos padrão na implementação HTTP3.

Consulte o commit do patch abaixo.

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;

Repositories - haproxy-2.7.git/commit

Abaixo, você pode encontrar o código que demonstra a ausência de sanitização de nomes de cabeçalho na implementação do tratamento de cabeçalhos padrão no 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;
}

Abaixo, você pode encontrar o código usado para verificar se o nome do cabeçalho é válido.

O código começa com um loop for que itera por cada caractere de um nome de campo de cabeçalho. O loop é executado de i = 0 até i < list[hdr_idx0.n.len], onde list é um array ou estrutura contendo informações do cabeçalho, e hdr_idx é um índice representando o cabeçalho específico sendo verificado.
Dentro do loop, o código extrai o caractere atual c do nome do campo do cabeçalho. list[hdr_idx].n.ptr[i] acessa o caractere na posição i do nome do campo do cabeçalho.
A próxima parte do código contém uma instrução if. Ela verifica se o caractere atual c satisfaz uma de duas condições:

  • (uint8_t)(c - 'A') < 'Z' - 'A': Isso verifica se o caractere é uma letra maiúscula (A a Z) subtraindo 'A' de c e convertendo o resultado para uint8_t. Se o resultado for menor que a diferença entre 'Z' e 'A', então o caractere é uma letra maiúscula.
  • !HTTP_IS_TOKEN(c): Esta condição verifica se o caractere é um caractere de token HTTP válido. O HTTP_IS_TOKEN funciona primeiro verificando se o nome do cabeçalho contém algum token. Um token é uma sequência de caracteres que não é um caractere reservado no protocolo HTTP. Caracteres reservados são caracteres que têm significado especial no protocolo HTTP, por exemplo, :, /, ? e #.
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;
    }
}

Configuração do Laboratório

Todo o laboratório está sendo executado no Docker. Você pode executar o laboratório com os seguintes comandos:

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

Observe que a construção do Docker levará 15-20 minutos para terminar.
No entanto, antes de executar o laboratório, você precisa fazer algumas alterações de configuração:

/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
Você pode escolher entre a versão vulnerável e a versão corrigida alterando o valor do argumento para 'vuln' ou 'patched' para realizar seu teste nela.

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

e finalmente importe o certificado minica.crt no seu navegador.

⚠️ Por favor, execute o laboratório em um ambiente Linux.

Identificando o problema

Enviando a seguinte requisição curl:

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

Resposta da versão vulnerável:

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 <-- Cabeçalho malformado

Resposta da versão corrigida:

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

Com base nas descobertas acima, as respostas correspondentes indicam que a versão vulnerável do HAProxy permitiu que o prefixo \r\n passasse para o servidor backend, enquanto a versão corrigida descartou a conexão entre o cliente e o HAProxy.


Um atacante pode conduzir um ataque de Contrabando de Requisições HTTP com base no comportamento do backend e em como o servidor backend tratará o cabeçalho malformado. Na minha opinião, a preocupação mais significativa é que um atacante poderia explorar o CVE mencionado para realizar um ataque de Negação de Serviço (DoS).

Referências:

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

Baixar ferramenta