Saltar al contenido

Request smuggling y desincronización HTTP: cuando el proxy y el servidor no se ponen de acuerdo

    Request smuggling y desincronización HTTP:

    cuando el proxy y el servidor no se ponen de acuerdo

    Seguridad de aplicaciones web  |  unfantasmaenelsistema.com

    Casi ninguna aplicación web habla directamente con el navegador. Entre medias hay uno o varios intermediarios: un balanceador, un CDN, un proxy inverso, un WAF, una pasarela de API. El navegador manda una petición al primero de la cadena (el front-end), este la reenvía al siguiente y así hasta el servidor de aplicación (el back-end), que es quien realmente la procesa. Para ahorrar recursos, esos saltos suelen reutilizar una misma conexión TCP para muchas peticiones seguidas, una detrás de otra.

    El request smuggling —o desincronización HTTP— aparece cuando el front-end y el back-end no interpretan igual dónde termina una petición y dónde empieza la siguiente dentro de ese flujo compartido. Basta esa discrepancia para que un atacante logre que parte de lo que él envía quede «pegado» al principio de la petición de otra persona. Este artículo explica el mecanismo, qué permite, cómo se detecta y cómo se elimina; sin recetas para atacar servicios ajenos.

    Que aprenderas en este articulo

    Como el mismo mensaje HTTP puede parecer ‘una peticion’ para el front-end y ‘dos peticiones’ para el back-end · Las familias clasicas: CL.TE, TE.CL y TE.TE, y por que HTTP/1.1 las hace posibles · Las variantes modernas: downgrade de HTTP/2 a HTTP/1.1, request splitting y H2.CL / H2.TE · Que consigue un atacante: envenenar la cola de respuestas, saltarse controles del front y capturar peticiones ajenas · Deteccion (anomalias de longitud y de temporizacion) y defensa definitiva (rechazar lo ambiguo, HTTP/2 extremo a extremo)

    Encuadre legal y de pruebas

    Prueba estas tecnicas unicamente contra laboratorios propios o deliberadamente vulnerables (los labs de HTTP request smuggling de PortSwigger Web Security Academy, una cadena front-end/back-end que montes tu mismo en el rango 192.168.56.x de la serie) o con autorizacion escrita del titular · Enviar peticiones manipuladas contra una infraestructura ajena para desincronizar su cola de peticiones puede constituir acceso ilicito a sistemas de informacion, interceptacion de datos y danos informaticos (arts. 197 bis, 197 ter y 264 del Codigo Penal espanol) · El request smuggling afecta a peticiones de otros usuarios reales: incluso una prueba ‘inocente’ en produccion ajena puede degradar el servicio o exponer datos de terceros. Si encuentras un caso, no lo explotes: documenta lo minimo y usa el canal de divulgacion responsable del proveedor o el INCIBE-CERT

    1. El origen: dos formas de decir dónde acaba una petición

    En HTTP/1.1 el cuerpo de una petición puede delimitarse de dos maneras distintas. La cabecera Content-Length indica en bytes cuánto ocupa el cuerpo. La cabecera Transfer-Encoding: chunked dice que el cuerpo llega en trozos, cada uno precedido por su tamaño en hexadecimal, y que termina con un trozo de tamaño cero. Ambos mecanismos son válidos, pero el estándar prohíbe usar los dos a la vez en la misma petición precisamente porque son ambiguos juntos.

    El problema es qué hace cada servidor cuando llega una petición que, por descuido o por malicia, incluye las dos cabeceras o una versión rara de una de ellas. Si el front-end decide fiarse de Content-Length y el back-end de Transfer-Encoding (o al revés), cada uno leerá un número diferente de bytes como «la primera petición». Lo que uno considera final del mensaje, el otro lo considera principio del siguiente. A partir de ahí la conexión reutilizada queda desincronizada: todas las peticiones posteriores de esa conexión se interpretan corridas una posición.

    FamiliaFront-end usaBack-end usaEfecto
    CL.TEContent-LengthTransfer-Encoding: chunkedEl back-end cierra el cuerpo antes; los bytes sobrantes quedan como inicio de la siguiente peticion
    TE.CLTransfer-Encoding: chunkedContent-LengthEl front-end reenvia mas de lo que el back-end considera cuerpo; el resto se procesa como peticion nueva
    TE.TETransfer-Encoding (ofuscado)Transfer-Encoding (ofuscado)Ambos soportan chunked pero uno ignora una version malformada de la cabecera y cae a Content-Length

    Por que ‘chunked’ es el ingrediente habitual

    Un front-end que normaliza todo a Content-Length y reenvia, combinado con un back-end que sigue honrando Transfer-Encoding, es la receta de la mayoria de casos CL.TE · Las variantes TE.TE se consiguen escribiendo la cabecera de forma no estandar (espacios raros, mayusculas/minusculas mezcladas, un caracter de mas) para que solo uno de los dos servidores la reconozca · La defensa no es ‘detectar la ofuscacion concreta’: es que un unico componente decida y que cualquier peticion ambigua se rechace de plano

    2. Qué se consigue con la desincronización

    La desincronización en sí no roba nada; lo que importa es qué se puede hacer con ese hueco al principio de la petición de la víctima. Las consecuencias habituales, descritas a alto nivel:

    • Saltarse controles del front-end. Si el front-end aplica autenticacion, listas de acceso o reglas de WAF y el back-end confia en que ya vienen filtradas, un fragmento ‘contrabandeado’ llega al back-end sin pasar por esos controles y alcanza rutas internas que deberian estar vetadas.
    • Envenenar la cola de respuestas (response queue poisoning). El atacante consigue que las respuestas se desplacen: la victima recibe la respuesta destinada a otra peticion, y viceversa. En el peor caso se sirve a un usuario contenido de la sesion de otro.
    • Capturar peticiones de otros usuarios. El prefijo contrabandeado hace que la peticion completa de la victima (con sus cookies, cabeceras de sesion o tokens) quede almacenada como si fuera un dato enviado por el atacante, que luego la recupera.
    • Envenenamiento de cache. Combinado con una cache intermedia, una respuesta manipulada se almacena y se sirve a todo el que pida esa URL despues.
    • Amplificar otras debilidades. Un XSS que requeria interaccion se vuelve explotable ‘a ciegas’ contra quien pase por ahi; un endpoint interno de administracion queda expuesto.

    El rasgo que hace peligroso al request smuggling es que no ataca al atacante: ataca a los usuarios legítimos que comparten esa conexión aguas arriba. Por eso ni siquiera está justificado «probar un poco» contra un sistema de terceros.

    3. HTTP/2 no lo soluciona solo: el problema del downgrade

    HTTP/2 define la longitud de cada mensaje con un mecanismo propio (frames con longitud explícita), así que la ambigüedad Content-Length vs Transfer-Encoding no existe entre dos extremos que hablen HTTP/2 puro. El problema aparece cuando el front-end acepta HTTP/2 del cliente pero lo traduce a HTTP/1.1 para hablar con el back-end, algo muy común.

    En esa traducción, el front-end tiene que reconstruir una petición HTTP/1.1 a partir de la de HTTP/2. Si no valida bien el contenido de las pseudo-cabeceras y las cabeceras del mensaje HTTP/2, un atacante puede colar saltos de línea o cabeceras de longitud dentro de un valor, y el texto HTTP/1.1 resultante contiene una segunda petición incrustada. Es el mismo efecto que CL.TE/TE.CL pero introducido en el momento de la conversión.

    VarianteSituacionIdea general
    H2.CLHTTP/2 -> HTTP/1.1 con Content-Length inyectadaEl atacante declara un Content-Length en HTTP/2 que el back-end HTTP/1.1 honra y usa para recortar el cuerpo
    H2.TEHTTP/2 -> HTTP/1.1 con Transfer-Encoding inyectadaSe cuela Transfer-Encoding: chunked al bajar de version y el back-end la aplica
    Request splitting por CRLFValores de cabecera HTTP/2 sin sanearUn salto de linea CR LF dentro de un valor parte el mensaje HTTP/1.1 en dos al serializarlo
    HTTP/2 puro extremo a extremoFront-end y back-end hablan HTTP/2 sin downgradeNo hay ambiguedad de longitud: es la configuracion recomendada

    La regla practica sobre HTTP/2

    HTTP/2 solo cierra el problema si se mantiene de extremo a extremo, sin bajar a HTTP/1.1 en ningun salto interno · Si hay downgrade, el front-end DEBE rechazar toda cabecera y pseudo-cabecera HTTP/2 con caracteres de control (CR, LF, NUL) y no permitir que el cliente fije Content-Length ni Transfer-Encoding · Muchos casos reales de 2019-2023 fueron precisamente downgrades mal validados en CDNs y balanceadores

    4. Cómo se detecta

    4.1 Desde fuera, con pruebas controladas

    En un pentest autorizado o en tu propio laboratorio, la detección se apoya en dos señales observables sin necesidad de ver el interior de la infraestructura:

    • Diferencia de temporizacion. Se envia una peticion construida para que, SI existe desincronizacion, el back-end se quede esperando bytes que nunca llegan. Un retardo claro y reproducible frente a una peticion normal es el primer indicio (tecnica de deteccion por tiempo).
    • Respuestas anomalas a la peticion siguiente. Tras la peticion sospechosa se manda otra normal por la misma conexion; si vuelve un codigo de estado o un cuerpo que no corresponde (un 404 donde deberia haber 200, una respuesta partida, cabeceras duplicadas), la cola esta desincronizada.
    • Herramientas de test propio. La extension HTTP Request Smuggler de Burp Suite y el modo de estudio de la Web Security Academy automatizan estas sondas contra objetivos que controlas. Ejecutarlas contra terceros sin permiso es lo que convierte la prueba en delito.

    4.2 Desde dentro, en los logs y la telemetría

    El defensor tiene ventaja: ve los dos lados de la conversación. Señales que un SIEM o una revisión de logs pueden recoger (enlaza con los artículos de Sigma y Wazuh de la serie):

    • Peticiones con Content-Length y Transfer-Encoding a la vez, o con Transfer-Encoding escrita de forma no estandar, en los logs del front-end o del WAF.
    • Desajuste entre el numero de peticiones que registra el front-end y las que registra el back-end para una misma conexion o en una misma ventana de tiempo.
    • Respuestas del back-end cuyo tamano o codigo no casa con ninguna peticion registrada; lineas de log de aplicacion con metodos o rutas ‘raras’ pegadas al final del cuerpo de otra peticion.
    • Acceso a rutas internas o de administracion desde la IP del front-end pero sin la traza de autenticacion que ese front-end deberia haber anadido.
    • Picos de errores 400/408/502 concentrados, tipicos de sondas de smuggling que dejan la conexion a medias.
    # Lectura/auditoria: localizar peticiones con doble delimitador de longitud
    # en un log de acceso que registre cabeceras (formato propio del proxy).
    grep -iE 'transfer-encoding' access.log | grep -iE 'content-length'
     
    # Transfer-Encoding con espacios o mayusculas sospechosas antes del valor
    grep -iE 'transfer-encoding[^:]*:[^c]*chunked' access.log
     
    # Nginx: exigir que se rechace la peticion ambigua (comportamiento por defecto
    # en versiones actuales; verificar tras cada actualizacion).
    #   Directiva relevante:  ignore_invalid_headers on;  (valor por defecto)
     
    # Revisar que el back-end NO reutiliza una conexion tras una peticion malformada:
    #   Apache httpd:   comprobar 'HttpProtocolOptions Strict'  (por defecto desde 2.4.24)

    5. Defensa: eliminar la ambigüedad

    El request smuggling no se «mitiga» con parches parciales: se elimina cuando toda la cadena interpreta cada petición de la misma forma. Las medidas, de más a menos determinante:

    MedidaQue consigueNota
    Rechazar toda peticion ambiguaSi llegan Content-Length y Transfer-Encoding juntas, o una cabecera de longitud malformada, se responde 400 y se cierra la conexionEs la defensa central; la mayoria de servidores modernos ya lo hacen por defecto, hay que confirmarlo
    HTTP/2 de extremo a extremoElimina la ambiguedad de longitud en todos los saltos internosRequiere que el back-end y los proxies internos hablen HTTP/2; si no, validar el downgrade a fondo
    Normalizar en un unico puntoUn solo componente decide la forma canonica de la peticion y todos los demas la respetanEvita que front-end y back-end ‘negocien’ cada uno por su lado
    No reutilizar la conexion aguas arribaSin conexion compartida no hay cola que desincronizar (una conexion por peticion al back-end)Cuesta rendimiento; util como medida temporal mientras se corrige la cadena
    Mismo software y misma config en la cadenaDos servidores identicos no discrepan sobre donde acaba una peticionNo siempre es posible (CDN + origen), pero reduce la superficie
    Mantener actualizados proxy, WAF y servidorLa mayoria de variantes conocidas se corrigieron en versiones concretasVerificar el comportamiento tras cada actualizacion, no darlo por hecho
    WAF con reglas anti-smugglingFiltra cabeceras duplicadas y Transfer-Encoding ofuscadaCapa extra, no sustituto: el WAF tambien puede ser el componente que discrepa

    Checklist rápida para una cadena front-end / back-end

    Confirma que el front-end rechaza (no ‘normaliza y reenvia’) cualquier peticion con doble delimitador de longitud · Comprueba que el back-end no acepta Transfer-Encoding de una fuente que no deberia usarla y que no reutiliza conexiones tras un error de protocolo · Si hay downgrade de HTTP/2 a HTTP/1.1, revisa que se saneen CR/LF/NUL en cabeceras y pseudo-cabeceras y que el cliente no pueda fijar Content-Length ni Transfer-Encoding · Ejecuta las sondas de deteccion contra tu propio entorno de preproduccion tras cada cambio de infraestructura

    6. Practicar en laboratorio

    Para entender el mecanismo de primera mano hace falta una cadena con al menos dos servidores que discrepen. La forma más limpia de estudiarlo sin tocar nada ajeno:

    • Los laboratorios de ‘HTTP request smuggling’ de la PortSwigger Web Security Academy: son gratuitos, estan pensados para esto y cubren CL.TE, TE.CL, TE.TE, las variantes de HTTP/2 y los escenarios de explotacion (bypass de controles, captura de peticiones, envenenamiento de cache).
    • Un montaje propio en el rango 192.168.56.x de la serie: por ejemplo un proxy inverso delante de un servidor de aplicacion sencillo, deliberadamente con versiones o configuraciones que discrepen, solo para observar la desincronizacion en los logs de ambos.
    • Del lado defensivo: reproduce las sondas y escribe la regla de deteccion (Sigma) que las cazaria en el log del front-end; comprueba que una configuracion endurecida devuelve 400 y cierra la conexion.
    • No uses estas pruebas contra servicios en produccion, tuyos o ajenos: afectan a la cola de peticiones real y pueden alcanzar a usuarios que no son tu.

    Conclusión

    El request smuggling es un fallo de acuerdo, no de código de aplicación: dos piezas de infraestructura que leen el mismo mensaje y cuentan un número distinto de bytes. Esa grieta minúscula basta para que lo que envía un atacante se adhiera a la petición de otra persona, con consecuencias que van desde saltarse el WAF hasta servir la sesión de un usuario a otro.

    La buena noticia es que la solución es conceptualmente simple y definitiva: que un único componente decida la forma canónica de cada petición, que cualquier mensaje ambiguo se rechace en lugar de «arreglarse», y que HTTP/2 se mantenga de extremo a extremo siempre que se pueda. Con la cadena alineada, no queda desincronización que explotar.

    Referencias y recursos

    PortSwigger – ‘HTTP request smuggling’ (articulo de investigacion de James Kettle) y laboratorios de la Web Security Academy · PortSwigger – ‘HTTP/2: The Sequel is Always Worse’ (downgrade, H2.CL, H2.TE, request splitting) · OWASP – HTTP Request Smuggling y OWASP Testing Guide (WSTG-INPV-15) · CWE-444: Inconsistent Interpretation of HTTP Requests (‘HTTP Request/Response Smuggling’) · RFC 9112 (HTTP/1.1) – seccion sobre message body length y el conflicto Content-Length / Transfer-Encoding · Documentacion de tu proxy (nginx, HAProxy, Apache httpd, Envoy) – opciones de ‘strict’ parsing de HTTP

    unfantasmaenelsistema.com | Seguridad, sistemas y todo lo que no debería funcionar (pero funciona)

    Resumen de privacidad

    Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.