El 7 de octubre de 2019, el Director de Investigaci贸n de PortSwigger (fabricante de BurpSuite) public贸 un estudio sobre nuevos enfoques para el contrabando de solicitudes HTTP. Con su ayuda, gan贸 alrededor de $ 70,000 en bugbounty. En este art铆culo, descubrimos brevemente la esencia del ataque, las herramientas y tambi茅n los m茅todos de investigaci贸n de servidores web que son vulnerables a esta vulnerabilidad.
驴Qu茅 es el contrabando de solicitudes HTTP?
Contrabando de solicitudes HTTP: un ataque destinado a desincronizar el frontend del servidor web y el back-end del servidor web, como resultado de lo cual el atacante podr铆a pasar de contrabando una solicitud HTTP m谩s all谩 del servidor frontend. La imagen del art铆culo original sirve como una buena demostraci贸n:

Tal ataque puede llevar a una variedad de consecuencias: la introducci贸n de XSS en la sesi贸n de otros usuarios, redirigiendo a los usuarios a recursos de terceros, envenenando la cach茅 del servidor, similitud con SSRF y muchos otros.
En la Encarnaci贸n de contrabando de 2019 de 2019, James Kettle explot贸 el procesamiento incorrecto del encabezado del servidor web
Transfer-Encoding: chunked
indicando que el cuerpo del mensaje se transmitir谩 en partes ( RFC ). Debido al hecho de que algunos servidores web no son compatibles con la transmisi贸n fragmentada, o manejan el encabezado de manera diferente, el frontend "ver谩" solo una solicitud, y el backend la reconocer谩 como dos. Puede encontrar m谩s detalles sobre los detalles del ataque en el art铆culo original , tambi茅n hay una tarea pr谩ctica en la que puede practicar para encontrar la vulnerabilidad manualmente.
Para una b煤squeda r谩pida, James desarroll贸 un complemento para BurpSuit, que recibe una solicitud de entrada y crea una nota sobre la vulnerabilidad del servicio (si existe) en la salida.
Ejemplos de servidores web vulnerables
Debo decir que el problema del contrabando y otras vulnerabilidades relacionadas con el funcionamiento de los servidores web ha sido tratado por otro investigador bajo el apodo regilero . En los 煤ltimos tres a帽os, ha publicado tres art铆culos que describen las vulnerabilidades que encontr贸 en los servidores web populares, la mayor铆a de los cuales tienen asignados CVE de cr铆tica media y alta. Entre los servidores vulnerables se encuentran Apache Traffic Server, Jetty, Apsis.
A ra铆z del inter茅s en el problema, otro investigador, Nathan Davison, descubri贸 una vulnerabilidad en HAProxy, que ignor贸 un encabezado formado incorrectamente.
Transfer-Encoding:[\x0b]chunked
y lo convirti贸 a la siguiente forma:
Transfer-Encoding: chunked
Pero el servidor de fondo: gunicorn, que representa la aplicaci贸n en Flask, ley贸 el encabezado, lo que provoc贸 la vulnerabilidad.
Un poco m谩s tarde, varios otros investigadores descubrieron una vulnerabilidad (asignada CVE-2019-16276) en la implementaci贸n del servidor http golang: el servidor normalizaba el encabezado si hab铆a un espacio antes del prelet.
Solicitud:

Despu茅s de procesar por el servidor:

La vulnerabilidad podr铆a explotarse si el servidor frontend ignora el encabezado con un espacio y usa Content-Length para calcular el tama帽o de la solicitud.
El servidor web Caddy escrito en Go tambi茅n era vulnerable porque usaba la misma biblioteca net / http. Los desarrolladores confirmaron que despu茅s de actualizar GO y reconstruir el paquete, el problema desaparece.
El autor de este art铆culo encontr贸 un problema similar en el servidor lighthttpd (no se asign贸 CVE). La captura de pantalla muestra que el servidor acepta y procesa el encabezado que contiene un espacio:

Los desarrolladores no est谩n del todo de acuerdo con RFC 7230 (y el autor tambi茅n), y creen que la responsabilidad del procesamiento incorrecto de los encabezados recae en los proxies que env铆an las solicitudes sin normalizarlas y verificarlas. Sin embargo, el error se solucionar谩 en la nueva versi贸n:
De forma predeterminada, lighttpd analiza (y normaliza) las solicitudes antes de enviarlas por proxy a los backends. Hacerlo frustra los ataques mencionados en https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn a los servidores aguas arriba de lighttpd.
Sin embargo, como mencion贸 anteriormente stbuehler, los servidores proxy posteriores a lighttpd podr铆an pasar cualquier cosa a lighttpd.
El cambio que se realizar谩 en la pr贸xima versi贸n de lighttpd ser谩 rechazar las solicitudes con espacio o tabulaci贸n despu茅s del nombre del campo y antes de los dos puntos, pero solo cuando lighttpd est茅 configurado en el modo (predeterminado) del an谩lisis estricto del encabezado http.
Se encontr贸 el mismo error en el servidor web cheroot utilizado por el framework cherrypy. Este mini-framework se encuentra en startups, a menudo se usa para escribir API. El informe de error se cuelga en el estado abierto.
Condiciones necesarias y suficientes para la vulnerabilidad.
Entonces, 驴cu谩les son las condiciones necesarias para verificar y explotar la vulnerabilidad?
- Solicitud POST. Aunque el RFC no proh铆be expl铆citamente el uso de encabezados Content-Length y Transfer-Encoding para solicitudes GET, de hecho, solo se usan en solicitudes POST.
- La presencia de servidores frontend y backend: si no hay ninguno, no habr谩 nada que sincronizar.
- Los servidores web deben analizar el encabezado Transfer-Encoding de manera diferente, es decir, uno debe "leerlo" y el segundo debe ignorarse.
Pruebas de laboratorio
Para una mejor comprensi贸n y resoluci贸n de problemas en servidores web y servidores proxy existentes, es aconsejable implementar un entorno de prueba localmente con Docker.
Un ejemplo de un diagrama de entorno de prueba:

C贸digo de aplicaci贸n:
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def main(): # the next line is required for Transfer-Encoding support in the request request.environ['wsgi.input_terminated'] = True headers = {} for header in request.headers: headers[header[0]] = header[1] print (request.data) print (headers) return jsonify(body=str(request.data), headers=headers)
Archivo con configuraciones frontend, por ejemplo, caddy:
localhost:80 log ../access.log proxy / host.docker.internal:8888
Entonces todo es simple, ejecuta la aplicaci贸n:
gunicorn --keep-alive 10 -k gevent --bind 0.0.0.0:8888 -w 4 backend:app
Y contenedor:
docker run -d -t --name caddy -p 80:80 -p 443:443 -v /Users/sun/work/caddyfile:/etc/Caddyfile abiosoft/caddy:latest
Desde la tienda Burp, instalamos HTTP Request Smuggler y Logger ++ para facilitar la depuraci贸n. A continuaci贸n en Repeater formamos una solicitud simple, por ejemplo esto:
POST / HTTP/1.1 Host: localhost Content-Length: 8 Connection: close body=123
Y env铆elo para verificar que todo est茅 configurado correctamente:
HTTP/1.1 200 OK Content-Length: 202 Content-Type: application/json Date: Mon, 07 Oct 2019 13:17:18 GMT Server: Caddy Server: gunicorn/19.9.0 Connection: close {"body":"b'body=123'","headers":{"Accept-Encoding":"gzip","Connection":"close","Content-Length":"8","Host":"host.docker.internal:8888","User-Agent":"Go-http-client/1.1","X-Forwarded-For":"172.17.0.1"}}
Ahora inicie Launch Smuggle Probe y mire las respuestas.

Lo m谩s interesante comienza en este momento. Es necesario analizar las solicitudes y respuestas para comprender si los servicios son vulnerables o no. Esta parte se deja para el lector curioso.