HTTP Request Smuggling / HTTP Desync Attack
Last updated
Last updated
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)
Esta vulnerabilidad ocurre cuando una desincronización entre los proxies de front-end y el servidor back-end permite a un atacante enviar una solicitud HTTP que será interpretada como una solicitud única por los proxies de front-end (balanceador de carga/proxy inverso) y como 2 solicitudes por el servidor back-end. Esto permite a un usuario modificar la siguiente solicitud que llega al servidor back-end después de la suya.
Si se recibe un mensaje con un campo de encabezado Transfer-Encoding y un campo de encabezado Content-Length, este último DEBE ser ignorado.
Content-Length
El encabezado de entidad Content-Length indica el tamaño del cuerpo de la entidad, en bytes, enviado al destinatario.
Transfer-Encoding: chunked
El encabezado Transfer-Encoding especifica la forma de codificación utilizada para transferir de manera segura el cuerpo de la carga útil al usuario. Chunked significa que los datos grandes se envían en una serie de fragmentos.
El Front-End (un balanceador de carga / Proxy Inverso) procesa el encabezado content-length o el transfer-encoding y el servidor Back-end procesa el otro provocando una desincronización entre los 2 sistemas. Esto podría ser muy crítico ya que un atacante podrá enviar una solicitud al proxy inverso que será interpretada por el servidor back-end como 2 solicitudes diferentes. El peligro de esta técnica reside en el hecho de que el servidor back-end interpretará la 2ª solicitud inyectada como si viniera del siguiente cliente y la solicitud real de ese cliente será parte de la solicitud inyectada.
Recuerda que en HTTP un carácter de nueva línea está compuesto por 2 bytes:
Content-Length: Este encabezado utiliza un número decimal para indicar el número de bytes del cuerpo de la solicitud. Se espera que el cuerpo termine en el último carácter, no se necesita una nueva línea al final de la solicitud.
Transfer-Encoding: Este encabezado utiliza en el cuerpo un número hexadecimal para indicar el número de bytes del siguiente fragmento. El fragmento debe terminar con una nueva línea pero esta nueva línea no se cuenta en el indicador de longitud. Este método de transferencia debe terminar con un fragmento 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 solicitud del HTTP Request Smuggling.
Al intentar explotar esto con Burp Suite desactiva Update Content-Length
y Normalize HTTP/1 line endings
en el repetidor porque algunos gadgets abusan de nuevas líneas, retornos de carro y content-lengths malformados.
Los ataques de HTTP request smuggling se elaboran enviando solicitudes ambiguas que explotan discrepancias en cómo los servidores de front-end y back-end interpretan los encabezados Content-Length
(CL) y Transfer-Encoding
(TE). Estos ataques pueden manifestarse en diferentes formas, principalmente como CL.TE, TE.CL y TE.TE. Cada tipo representa una combinación única de cómo los servidores de front-end y back-end priorizan estos encabezados. Las vulnerabilidades surgen de que los servidores procesan la misma solicitud de diferentes maneras, lo que lleva a resultados inesperados y potencialmente maliciosos.
A la tabla anterior deberías agregar la técnica TE.0, como la técnica CL.0 pero usando Transfer Encoding.
Front-End (CL): Procesa la solicitud basada en el encabezado Content-Length
.
Back-End (TE): Procesa la solicitud basada en el encabezado Transfer-Encoding
.
Escenario de Ataque:
El atacante envía una solicitud donde el valor del encabezado Content-Length
no coincide con la longitud real del contenido.
El servidor de front-end reenvía toda la solicitud al back-end, basado en el valor de Content-Length
.
El servidor back-end procesa la solicitud como fragmentada debido al encabezado Transfer-Encoding: chunked
, interpretando los datos restantes como una solicitud separada y subsiguiente.
Ejemplo:
Front-End (TE): Procesa la solicitud basada en el encabezado Transfer-Encoding
.
Back-End (CL): Procesa la solicitud basada en el encabezado Content-Length
.
Escenario de Ataque:
El atacante envía una solicitud fragmentada donde el tamaño del fragmento (7b
) y la longitud real del contenido (Content-Length: 4
) no se alinean.
El servidor de front-end, respetando Transfer-Encoding
, reenvía toda la solicitud al back-end.
El servidor back-end, respetando Content-Length
, procesa solo la parte inicial de la solicitud (7b
bytes), dejando el resto como parte de una solicitud subsiguiente no intencionada.
Ejemplo:
Servidores: Ambos soportan Transfer-Encoding
, pero uno puede ser engañado para ignorarlo a través de ofuscación.
Escenario de Ataque:
El atacante envía una solicitud con encabezados Transfer-Encoding
ofuscados.
Dependiendo de qué servidor (front-end o back-end) no reconozca la ofuscación, se puede explotar una vulnerabilidad CL.TE o TE.CL.
La parte no procesada de la solicitud, tal como la ve uno de los servidores, se convierte en parte de una solicitud subsiguiente, llevando al smuggling.
Ejemplo:
Ambos servidores procesan la solicitud basándose únicamente en el encabezado 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 solicitud.
Ejemplo:
Se refiere a escenarios donde el encabezado Content-Length
está presente y tiene un valor diferente de cero, indicando que el cuerpo de la solicitud tiene contenido. El back-end ignora el encabezado Content-Length
(que se trata como 0), pero el front-end lo analiza.
Es crucial para entender y elaborar ataques de smuggling, ya que influye en cómo los servidores determinan el final de una solicitud.
Ejemplo:
Similar al anterior pero usando TE.
Técnica reportada aquí
Ejemplo:
Esta técnica también es útil en escenarios donde es posible romper un servidor web mientras se lee los datos HTTP iniciales pero sin cerrar la conexión. De esta manera, el cuerpo de la solicitud HTTP será considerado la siguiente solicitud HTTP.
Por ejemplo, como se explica en este artículo, en Werkzeug era posible enviar algunos caracteres Unicode y esto haría que el servidor se rompiera. Sin embargo, si la conexión HTTP se creó con el encabezado Connection: keep-alive
, el cuerpo de la solicitud no será leído y la conexión seguirá abierta, por lo que el cuerpo de la solicitud será tratado como la siguiente solicitud HTTP.
Abusando de los encabezados hop-by-hop, podrías indicar al proxy que elimine el encabezado Content-Length o Transfer-Encoding para que un HTTP request smuggling sea posible de abusar.
Para más información sobre los encabezados hop-by-hop visita:
hop-by-hop headersIdentificar vulnerabilidades de HTTP request smuggling a menudo se puede lograr utilizando técnicas de temporización, que se basan en observar cuánto tiempo 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, hay otras estrategias y herramientas que se pueden utilizar para encontrar tales vulnerabilidades:
Método:
Envía una solicitud que, si la aplicación es vulnerable, hará que el servidor de back-end espere datos adicionales.
Ejemplo:
Observación:
El servidor de front-end procesa la solicitud en función de Content-Length
y corta el mensaje prematuramente.
El servidor de back-end, esperando un mensaje en trozos, espera el siguiente trozo que nunca llega, causando un retraso.
Indicadores:
Timeouts o largos retrasos en la respuesta.
Recibir un error 400 Bad Request del servidor de back-end, a veces con información detallada del servidor.
Método:
Envía una solicitud que, si la aplicación es vulnerable, hará que el servidor de back-end espere datos adicionales.
Ejemplo:
Observación:
El servidor de front-end procesa la solicitud en función de Transfer-Encoding
y reenvía todo el mensaje.
El servidor de back-end, esperando un mensaje basado en Content-Length
, espera datos adicionales que nunca llegan, causando un retraso.
Análisis de Respuesta Diferencial:
Envía versiones ligeramente variadas de una solicitud y observa si las respuestas del servidor difieren de manera inesperada, indicando una discrepancia de análisis.
Uso de Herramientas Automatizadas:
Herramientas como la extensión 'HTTP Request Smuggler' de Burp Suite pueden probar automáticamente estas vulnerabilidades enviando varias formas de solicitudes ambiguas y analizando las respuestas.
Pruebas de Variación de Content-Length:
Envía solicitudes con valores de Content-Length
variables que no están alineados con la longitud real del contenido y observa cómo maneja el servidor tales desajustes.
Pruebas de Variación de Transfer-Encoding:
Envía solicitudes con encabezados de Transfer-Encoding
ofuscados o malformados y monitorea cómo responden de manera diferente los servidores de front-end y back-end a tales manipulaciones.
Después de confirmar la efectividad de las técnicas de temporización, es crucial verificar si se pueden manipular las solicitudes del cliente. Un método sencillo es intentar envenenar tus solicitudes, por ejemplo, haciendo que una solicitud a /
produzca una respuesta 404. Los ejemplos de CL.TE
y TE.CL
discutidos anteriormente en Ejemplos Básicos demuestran cómo envenenar la solicitud de un cliente para provocar una respuesta 404, a pesar de que el cliente intenta acceder a un recurso diferente.
Consideraciones Clave
Al probar vulnerabilidades de request smuggling interfiriendo con otras solicitudes, ten en cuenta:
Conexiones de Red Distintas: Las solicitudes "atacantes" y "normales" deben enviarse a través de conexiones de red separadas. Utilizar 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 dirigen las solicitudes a servidores de back-end específicos según la URL y los parámetros. Hacer coincidir estos aumenta la probabilidad de que ambas solicitudes sean procesadas por el mismo servidor, un requisito previo para un ataque exitoso.
Condiciones de Temporización y Carrera: La solicitud "normal", destinada a detectar interferencias de la solicitud "atacante", compite contra otras solicitudes concurrentes de la aplicación. Por lo tanto, envía la solicitud "normal" inmediatamente después de la solicitud "atacante". Las aplicaciones ocupadas pueden requerir múltiples intentos para una confirmación concluyente de vulnerabilidad.
Desafíos de Balanceo de Carga: Los servidores de front-end que actúan como balanceadores de carga pueden distribuir solicitudes entre varios sistemas de back-end. Si las solicitudes "atacantes" y "normales" terminan en diferentes sistemas, el ataque no tendrá éxito. Este aspecto de balanceo de carga puede requerir varios intentos para confirmar una vulnerabilidad.
Impacto No Intencionado en el Usuario: Si tu ataque impacta inadvertidamente la solicitud de otro usuario (no la solicitud "normal" que enviaste para la detección), esto indica que tu ataque influyó en otro usuario de la aplicación. Las pruebas continuas podrían interrumpir a otros usuarios, lo que requiere un enfoque cauteloso.
A veces, los proxies de front-end imponen medidas de seguridad, examinando las solicitudes entrantes. Sin embargo, estas medidas pueden ser eludidas al explotar HTTP Request Smuggling, permitiendo el acceso no autorizado a puntos finales restringidos. Por ejemplo, acceder a /admin
podría estar prohibido externamente, con el proxy de front-end bloqueando activamente tales intentos. No obstante, este proxy puede descuidar inspeccionar las solicitudes incrustadas dentro de una solicitud HTTP contrabandeada, dejando un vacío para eludir estas restricciones.
Considera los siguientes ejemplos que ilustran cómo HTTP Request Smuggling puede ser utilizado para eludir los controles de seguridad del front-end, específicamente apuntando a la ruta /admin
que generalmente está protegida por el proxy de front-end:
Ejemplo CL.TE
En el ataque CL.TE, se aprovecha el encabezado Content-Length
para la solicitud inicial, mientras que la solicitud embebida subsiguiente utiliza el encabezado Transfer-Encoding: chunked
. El proxy de front-end procesa la solicitud POST
inicial pero no inspecciona la solicitud embebida GET /admin
, lo que permite el acceso no autorizado a la ruta /admin
.
Ejemplo TE.CL
Por el contrario, en el ataque TE.CL, la solicitud POST
inicial utiliza Transfer-Encoding: chunked
, y la solicitud embebida subsiguiente se procesa en función del encabezado Content-Length
. Similar al ataque CL.TE, el proxy de front-end pasa por alto la solicitud GET /admin
contrabandeada, otorgando inadvertidamente acceso a la ruta restringida /admin
.
Las aplicaciones a menudo emplean un servidor de front-end para modificar las solicitudes entrantes antes de pasarlas al servidor de back-end. Una modificación típica implica agregar encabezados, como X-Forwarded-For: <IP del cliente>
, para transmitir la IP del cliente al back-end. Comprender estas modificaciones puede ser crucial, ya que podría revelar formas de eludir protecciones o descubrir información o puntos finales ocultos.
Para investigar cómo un proxy altera una solicitud, localiza un parámetro POST que el back-end ecoe en la respuesta. Luego, elabora una solicitud, utilizando este parámetro al final, similar a lo siguiente:
En esta estructura, los componentes de la solicitud subsiguiente se añaden 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. Se aconseja comenzar con un valor pequeño e incrementar gradualmente, ya que un valor demasiado bajo truncará los datos reflejados, mientras que un valor demasiado alto puede causar que la solicitud falle.
Esta técnica también es aplicable en el contexto de una vulnerabilidad TE.CL, pero la solicitud debe terminar con search=\r\n0
. Independientemente de los caracteres de nueva línea, los valores se añadirán al parámetro de búsqueda.
Este método sirve principalmente para entender las modificaciones de la solicitud realizadas por el proxy del front-end, realizando esencialmente una investigación autodirigida.
Es factible capturar las solicitudes del siguiente usuario añadiendo una solicitud específica como el valor de un parámetro durante una operación POST. Aquí se explica cómo se puede lograr:
Al añadir la siguiente solicitud como el valor de un parámetro, puedes almacenar la solicitud del cliente subsiguiente:
En este escenario, el parámetro de comentario 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 subsiguiente aparecerá como un comentario.
Sin embargo, esta técnica tiene limitaciones. Generalmente, captura datos solo hasta el delimitador de parámetro utilizado en la solicitud contrabandeada. Para envíos de formularios codificados en URL, 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 de la cadena de consulta.
Además, vale la pena señalar que este enfoque también es viable con una vulnerabilidad TE.CL. En tales casos, la solicitud debe concluir con search=\r\n0
. Independientemente de los caracteres de nueva línea, los valores se agregarán al parámetro de búsqueda.
El contrabando de solicitudes HTTP se puede aprovechar para explotar páginas web vulnerables a XSS Reflejado, 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 los encabezados de solicitudes HTTP.
En escenarios donde un sitio web es susceptible a XSS Reflejado a través del encabezado User-Agent, la siguiente carga útil demuestra cómo explotar esta vulnerabilidad:
Este payload está estructurado para explotar la vulnerabilidad mediante:
Iniciando una solicitud POST
, aparentemente típica, con un encabezado Transfer-Encoding: chunked
para indicar el inicio del smuggling.
Siguiendo con un 0
, marcando el final del cuerpo del mensaje en chunks.
Luego, se introduce una solicitud GET
smuggled, donde el encabezado User-Agent
se inyecta con un script, <script>alert(1)</script>
, activando el XSS cuando el servidor procesa esta solicitud subsiguiente.
Al manipular el User-Agent
a través del smuggling, el payload elude las restricciones normales de la solicitud, explotando así la vulnerabilidad de XSS Reflejado de una manera no estándar pero efectiva.
En caso de que el contenido del usuario se refleje en una respuesta con un Content-type
como text/plain
, impidiendo la ejecución del XSS. ¡Si el servidor soporta HTTP/0.9 podría ser posible eludir esto!
La versión HTTP/0.9 fue anterior a la 1.0 y solo utiliza verbos GET y no responde con encabezados, solo el cuerpo.
En este writeup, esto fue abusado con un smuggling de solicitudes y un punto final vulnerable que responderá con la entrada del usuario para smuggling una solicitud con HTTP/0.9. El parámetro que se reflejará en la respuesta contenía una respuesta HTTP/1.1 falsa (con encabezados y cuerpo), por lo que la respuesta contendrá código JS ejecutable válido con un Content-Type
de text/html
.
Las aplicaciones a menudo redirigen de una URL a otra utilizando el nombre de host del encabezado Host
en la URL de redirección. Esto es común en servidores web como Apache e IIS. Por ejemplo, solicitar una carpeta sin una barra diagonal al final resulta en una redirección para incluir la barra:
Resultados en:
Aunque aparentemente inofensivo, este comportamiento puede ser manipulado utilizando HTTP request smuggling para redirigir a los usuarios a un sitio externo. Por ejemplo:
Esta solicitud encubierta podría hacer que la siguiente solicitud de usuario procesada sea redirigida a un sitio web controlado por un atacante:
Resultados en:
En este escenario, se secuestra la solicitud de un usuario para un archivo JavaScript. El atacante puede comprometer potencialmente al usuario sirviendo JavaScript malicioso en respuesta.
La contaminación de caché web puede ejecutarse si cualquier componente de la infraestructura de front-end almacena contenido en caché, típicamente para mejorar el rendimiento. Al manipular la respuesta del servidor, es posible contaminar la caché.
Anteriormente, observamos cómo se podían alterar las respuestas del servidor para devolver un error 404 (consulte Ejemplos Básicos). De manera similar, es factible engañar al servidor para que entregue 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é con el de /index.html
, haciendo que /static/include.js
sea inaccesible para los usuarios, lo que potencialmente puede llevar a una Denegación de Servicio (DoS).
Esta técnica se vuelve particularmente potente si se descubre una vulnerabilidad de Redirección Abierta o si hay una redirección en el sitio a una redirección abierta. Tales vulnerabilidades pueden ser explotadas para reemplazar el contenido en caché de /static/include.js
con un script bajo el control del atacante, habilitando esencialmente un ataque de Cross-Site Scripting (XSS) generalizado contra todos los clientes que soliciten el /static/include.js
actualizado.
A continuación se muestra una ilustración de la explotación de contaminación de caché combinada con una redirección en el sitio a una redirección abierta. El objetivo es alterar el contenido de la caché de /static/include.js
para servir código JavaScript controlado por el atacante:
Note el request incrustado que apunta a /post/next?postId=3
. Este request será redirigido a /post?postId=4
, utilizando el valor del encabezado Host para determinar el dominio. Al alterar el encabezado Host, el atacante puede redirigir el request a su dominio (redirección en el sitio a redirección abierta).
Después de un exitoso envenenamiento de socket, se debe iniciar un request GET para /static/include.js
. Este request será contaminado por el anterior request de redirección en el sitio a redirección abierta y obtendrá el contenido del script controlado por el atacante.
Posteriormente, cualquier request para /static/include.js
servirá el contenido en caché del script del atacante, lanzando efectivamente un amplio ataque XSS.
¿Cuál es la diferencia entre el envenenamiento de caché web y el engaño de caché web?
En el envenenamiento de caché web, el atacante provoca que la aplicación almacene contenido malicioso en la caché, y este contenido se sirve desde la caché a otros usuarios de la aplicación.
En el engaño de caché web, el atacante provoca que la aplicación almacene contenido sensible perteneciente a otro usuario en la caché, y luego el atacante recupera este contenido de la caché.
El atacante elabora un request smuggled que obtiene contenido sensible específico del usuario. Considere el siguiente ejemplo:
Si esta solicitud contrabandeada envenena una entrada de caché destinada a contenido estático (por ejemplo, /someimage.png
), los datos sensibles de la víctima de /private/messages
podrían ser almacenados en caché bajo la entrada de caché del contenido estático. En consecuencia, el atacante podría potencialmente recuperar estos datos sensibles almacenados en caché.
En esta publicación se sugiere que si el servidor tiene habilitado el método TRACE, podría ser posible abusar de él con un HTTP Request Smuggling. Esto se debe a que este método reflejará cualquier encabezado enviado al servidor como parte del cuerpo de la respuesta. Por ejemplo:
Enviaré una respuesta como:
Un ejemplo de cómo abusar de este comportamiento sería contrabandear primero una solicitud HEAD. Esta solicitud será respondida solo con los encabezados de una solicitud GET (Content-Type
entre ellos). Y contrabandear inmediatamente después de la HEAD una solicitud TRACE, que estará reflejando los datos enviados.
Como la respuesta HEAD contendrá un encabezado Content-Length
, la respuesta de la solicitud TRACE será tratada como el cuerpo de la respuesta HEAD, reflejando así datos arbitrarios en la respuesta.
Esta respuesta se enviará a la siguiente solicitud a través de la conexión, por lo que esto podría ser utilizado en un archivo JS en caché, por ejemplo, para inyectar código JS arbitrario.
Continuar siguiendo esta publicación se sugiere como otra forma de abusar del método TRACE. Como se comentó, contrabandear una solicitud HEAD y una solicitud TRACE es posible controlar algunos datos reflejados en la respuesta a la solicitud HEAD. La longitud del cuerpo de la solicitud HEAD está básicamente indicada en el encabezado Content-Length y se forma por la respuesta a la solicitud TRACE.
Por lo tanto, la nueva idea sería que, sabiendo este Content-Length y los datos dados en la respuesta TRACE, es posible hacer que la respuesta TRACE contenga una respuesta HTTP válida después del último byte del Content-Length, permitiendo a un atacante controlar completamente la solicitud a la siguiente respuesta (que podría ser utilizada para realizar un envenenamiento de caché).
Ejemplo:
Generará estas respuestas (note cómo la respuesta HEAD tiene un Content-Length que hace que la respuesta TRACE sea parte del cuerpo de HEAD y una vez que termina el Content-Length de HEAD, se infiltra una respuesta HTTP válida):
¿Has encontrado alguna vulnerabilidad de HTTP Request Smuggling y no sabes cómo explotarla? Prueba este otro método de explotación:
HTTP Response Smuggling / DesyncHTTP Request Smuggling en el Navegador (Lado del Cliente)
Request Smuggling en Downgrades de HTTP/2
Desde https://hipotermia.pw/bb/http-desync-idor
De: https://hipotermia.pw/bb/http-desync-account-takeover
https://github.com/bahruzjabiyev/t-reqs-http-fuzzer: Esta herramienta es un Fuzzer HTTP basado en gramática útil para encontrar discrepancias extrañas en el request smuggling.
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)