XUT_ / COURSES / PENETRATION TESTER

HTTP-2 Request Tunneling - Leaking Internal Headers

Leakear Headers Internos

La forma más simple de abusar el request tunneling es conseguir información de cómo se ven las peticiones del backend. En algunos casos, los proxies del frontend pueden añadir headers a las peticiones antes de mandarlas al backend. Si queremos contrabandear una petición específica al backend, puede que necesitemos añadir dichos headers a la petición.

Para filtrar dichos headers, podemos abusar cualquier funcionalidad en la aplicación backend que refleje un parámetro de la petición a la respuesta. En nuestro caso, la aplicación refleja lo que sea que se le mande a /hello mediante el parámetro POST q. Aquí está cómo se vería la petición:

HTTP-2 Request Tunneling - Leaking Internal Headers

Fíjate en la existencia del header content-length a pesar de ser ignorada por HTTP/2. La mayoría de los navegadores añaden este header a todas las peticiones HTTP/2 para que el backend siga recibiendo un header Content-Length válido si ocurre un HTTP downgrade. En el backend, la petición sería convertida a HTTP/1.1. Este proxy en particular insertará el header Host: después de los headers mandados por el cliente. Si se necesita, el proxy podría también añadir cualquier header adicional (representados como X-Internal en la imagen). La petición final del backend se vería así:

HTTP-2 Request Tunneling - Leaking Internal Headers

Nos aprovecharemos de la vulnerabilidad en HAProxy que nos permite inyectar CRLFs vía headers para leakear los headers del backend exitosamente. Añadiremos un header personalizado Foo y mandaremos nuestro payload a través de él. Así se verá nuestra petición:

HTTP-2 Request Tunneling - Leaking Internal Headers

Hay bastante que desglosar aquí:

  • Esto será la petición normal para el frontend ya que a HTTP/2 no le importa la información binaria del header.
  • El header Content-Lenth: 0 inyectado a través del header Foo hará al backend pensar que la primera petición POST no tiene body. Lo que venga después será interceptado como una segunda petición.
  • Como el header Host y cualquier otro header interno es insertado por el proxy después de Foo, la primera petición POST no tendrá header Host a no ser que se la proporcionemos. Por eso hemos inyectado este header en la primera petición. Es requerido porque HTTP/1.1 lo necesita.
  • La segunda petición POST disparará una búsqueda en la web. Fíjate cómo los headers internos ahora son parte del parámetro q en el body. Esto causará que la web refleje los headers de vuelta a nosotros.
  • La segunda petición POST que hemos inyectado tiene Content-Length: 300. Este número es sólo un valor adivinado inicial de cuánto espacio requeriremos para los headers internos. Tendrás que jugar un poco hasta que des con la respuesta correcta. Si se pone demasiado alto, la petición se colgará ya que el backend espera a que lleguen esos bytes. Si lo pones muy corto sólo recibirás una parte de los headers.

Ahora trataremos de mandar esto usando BurpSuite. Primero captura la petición que es mandada por la web al realizar una búsqueda. Deberías ser capaz de identificar una petición POST siendo mandada a /hello. Mándala al Repeater:

HTTP-2 Request Tunneling - Leaking Internal Headers

CAUTION

Asegúrate de que la petición es HTTP/2 y no HTTP/1.1 ya que a veces el navegador manda una petición HTTP/1.1 la primera vez que accede a un recurso.

Una vez que la petición está en el repetidor, le haremos unas modificaciones:

  1. Borramos el contenido del body.
  2. Configuramos Conten-Length: 0. Haremos esto por la misma razón que antes, queremos la primera petición POST sin body. Recuerda deshabilitar Update Content-Length.

HTTP-2 Request Tunneling - Leaking Internal Headers

Si Burp te lo pone difícil, aquí está una versión simplificada de la misma petición modificada que puedes copiar y pegar:

shell-session
POST /hello HTTP/2
Host: 10.114.188.96:8100
User-Agent: Mozilla/5.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

Añadiremos nuestro header personalizado Foo con contenido inicial bar. Como estamos añadiendo CRLFs a la petición, editar la petición como texto no será posible. En su lugar, usaremos el panel "Inspector" a la derecha ya que nos permite una edición de peticiones mucho más precisa.

HTTP-2 Request Tunneling - Leaking Internal Headers

Hacemos click en la flecha al lado del header foo en el Inspector y la editamos a lo que queramos.

NOTE

Para insertar un CRLF en el header necesitarás presionar SHIFT+ENTER.

La petición final se verá así:

HTTP-2 Request Tunneling - Leaking Internal Headers

Una vez que le des a Apply changes, el panel de la petición se mostrará en blanco y te mostrará un mensaje indicando que la petición está "kettled". Esto significa que no hay forma de representar la petición en texto puro debido a caracteres especiales (los CRLFs en nuestro caso). Desde ahora, todas las modificaciones necesarias podrán hacerse sólo en el Inspector.

Cuando la petición esté lista, puedes presionar el botón Send como de costumbre para mandarlo. Recuerda que nuestra petición HTTP/2 será partida en dos en el backend, por lo que la primera vez que la mandes, sólo obtendrás la respuesta de la primera petición, que está vacía. Para obtener el valor de los headers internos escondidos necesitarás mandar la misma petición dos veces sucesivamente. Si todo va bien, la web te devolverá reflejados los headers internos.

HTTP-2 Request Tunneling - Leaking Internal Headers