En esta habitación vamos a aprender sobre la vulnerabilidad SSRF (server-side request forgery) y el impacto que puede tener, junto con ejemplos de ataques.

¿Qué es el SSRF?

Es una vulnerabilidad que permite a un atacante hacer una petición HTTP adicional o editada, a fin de obtener un recurso al que no debería poder acceder.

Tipos de SSRF

Hay dos clases principales:

  • SSRF normal: en cuyo caso, los datos son visualizados en pantalla por el atacante.
  • SSRF ciego: la vulnerabilidad está y el SSRF sucede, pero el resultado no aparece en pantalla.

Impacto del SSRF

Este ataque puede dar lugar a:

  • Accesos a áreas no autorizadas.
  • Accesos a datos de clientes / organizacionales.
  • La habilidad de escalar a redes internas.
  • Revelar credenciales o tokens de autenticación.

¿Qué significa SSRF?

Server-side request forgery

¿Cuál es el tipo de SSRF que no es el «normal»?

Blind

Ejemplos de SSRF

La habitación ofrece varios ejemplos de SSRF habituales y cómo explotarlos. Del mismo modo, hay una bandera que nos pedirá.

En la pista nos dice que el payload debe terminar en &x= para que ignore el resto de la URL que pide.

La petición inicial que hacemos en la barra del navegador y a partir de la que vamos a trabajar es la siguiente:

https://website.thm/item/2?server=api

Lo que queremos conseguir es que nos devuelva la bandera que hay en esta dirección, pidiendo la siguiente página concreta.

https://server.website.thm/flag?id=9

La habitación nos da pistas de la petición final que se construye con lo que pongamos en la barra del navegador.

Por ejemplo, cuando ponemos la petición inicial en la barra del navegador sin modificar, esto es lo que se manda finalmente al servidor, ojo a la estructura.

https://api.website.thm/api/item?id=2

Vemos que dándole un valor api tras la parte de la expresión server= se construye una petición donde api es el subdominio que pide. Lo que queremos es llegar hasta:

https://server.website.thm/flag?id=9

Así que en vez de api hemos de alimentar server= con el valor de esa dirección completa de la bandera.

Una vez conseguida, queremos que se pare y no siga construyendo con los datos de item etc, de modo que la construcción final de la petición que hacemos en el navegador tiene que ser:

https://website.thm/item/9?server=server.website.thm/flag?id=9&x=

Eso hace que se vaya a la dirección que queremos y luego detenga el resto de cosas y no las añada (como los elementos item o 9), al finalizar el payload con &x=

De este modo, la bandera que nos da es:

THM{SSRF_MASTER}

Encontrando un SSRF

Las vulnerabilidades SSRF pueden ser avistadas en las aplicaciones web de muy diferentes maneras. He aquí un ejemplo de cuatro lugares comunes en los que encontrarlas.

1. Cuando una URL completa se usa como parámetro en la barra de direcciones

URl completa en barra de direcciones SSRF

2. Un campo oculto en un formulario

SSRF de campo oculto en un formulario

3. Una URL parcial, como por ejemplo, solo el nombre del servidor (host)

SSRF de URL parcial con nombre del servidor

4. Solamente la ruta de la URL, sin host

SSRF de ruta de URL sin host

Algunos de estos ejemplos son más fáciles de explotar que otros y aquí entra mucho ensayo y error para encontrar un payload que funcione.

Cuando trabajemos con SSRF ciego, necesitaremos usar una herramienta externa de registro de logs HTTP para monitorizar peticiones. Por ejemplo requestbin.com, tu propio servidor http (como el que creas con php o python) o el cliente Collaborator de Burp Suite.

¿Qué sitio web podemos usar para recoger peticiones HTTP de un servidor?

requestbin.com

Eliminando defensas habituales contra el SSRF

Los desarrolladores implementan chequeos en sus aplicaciones para asegurarse de que las peticiones siguen reglas específicas. Normalmente, hay dos enfoques, una lista de denegación (negra) o una lista de admisión (blanca).

Lista de denegación

Todas las peticiones son aceptadas excepto las que estén en una lista de las que coincidan con un patrón concreto.

Una aplicación web puede emplear una lista de denegación para proteger endpoints sensibles, direcciones IP o dominios y que no se accedan por el público, mientras que otros sí.

Así, dominios como localhost o direcciones como 127.0.0.1 pueden usarse en una lista de denegación.

Un atacante la puede burlar usando referencias alternativas a localhost, como:

 0, 0.0.0.0, 0000, 127.1, 127.*.*.*, 2130706433, 017700000001

O bien subdominios que tiene un registro DNS que resuelve a la dirección 127.0.0.1, como 127.0.0.1.nip.io.

Igualmente, en un entorno de nube, suele ser útil bloquear la IP 169.254.169.254, que contiene metadatos del servidor cloud desplegado, incluyendo la posibilidad de información sensible.

Un atacante puede evadir esto registrando un subdominio de su propio dominio con un registro DNS que apunte a la dirección IP 169.254.169.254.

Lista de admisión

Toda petición es denegada a menos que coincida con alguna de las que hay en la lista blanca de admisión. Por ejemplo, con la regla de una URL usada en un parámetro debe empezar con https://website.thm.

Un atacante puede evadir esta regla creando un subdominio en el nombre de dominio atacante, como https://website.thm.attackers-domain.thm. La lógica de la aplicación permitiría este input y dejará que el atacante controle la petición HTTP interna.

Redirección abierta

Si las evasiones anteriores no funciona, hay un truco más en la manga. Una redirección abierta es un endpoint en el servidor donde el visitante de la web queda redirigido automáticamente a otra web.

Por ejemplo, el enlace: https://website.thm/link?url=https://tryhackme.com.

Este endpoint fue creado para registrar el número de visitantes que han hecho clic en ese enlace, a fin de que marketing tenga datos. Pero imagina una SSRF con una regla que solo permita URL’s que comiencen con https://website.thm/.

Un atacante podría utilizar la característica de arriba para redirigir la petición HTTP interna a un dominio a elección del atacante.

¿Qué método puede usarse para evadir reglas estrictas?

Open redirect

¿Qué dirección IP puede contener datos sensibles en un entorno cloud?

169.254.169.254

¿Qué tipo de lista se usa para permitir solamente cierto input?

Allow list

¿Qué tipo de lista se usar para denegar cierto input?

Deny list

SSRF en la práctica

Vamos a practicar lo visto con una máquina vulnerable que activamos.

En este escenario, hemos encontrado dos endpoints en la web de Acme IT Support.

  • El primero es /private, que nos da un error explicando que los contenidos no pueden verse desde nuestra IP.
  • El segundo es una nueva versión de la página de cuenta de clientes en /customers/new-account-page.

Visitamos la web y seguimos las instrucciones para obtener la bandera.

Primero, creamos una cuenta de cliente para identificarnos. Una vez lo hemos hecho, visitamos la página /customers/new-account-page.

Allí veremos la prestación de elegir un nuevo avatar. Si miramos el código fuente de la página, veremos que el valor del campo de formulario avatar contiene la ruta a la imagen.

Campo formulario con URL a la imagen

Si elegimos uno de los avatares y hacemos clic en «Update avatar», veremos que el formulario cambia y nos muestra el avatar que hemos seleccionado. Si vemos la fuente de la página, nos mostrará ese avatar usando el esquema de datos URI, y el contenido de la imagen en codificación Base64.

Campo formulario con URL a la imagen

Ahora vamos a intentar realizar una petición, pero cambiando el valor de avatar a private, con la esperanza de que el servidor accederá al recurso y pasará el bloqueo de IP. Para hacerlo, primero realizamos clic derecho en uno de los botones de radio en el formulario de avatar y seleccionamos inspeccionar.

Inspeccionando

Y ahora editamos el valor a private:

Cambiando el valor a private

Y ahora, hacemos clic en «Update avatar». Por desgracia, parece que la aplicación tiene una lista de denegación y ha bloqueado el acceso al endpoint /private.

Bloqueo por lista de denegación

Como vemos en el mensaje de error, la ruta no puede empezar por /private, pero no pasa nada.

Podemos usar un directory traversal o viaje por directorios. Este truco funciona porque el servidor web recibe la petición para x/../private, sabe que ../ significa moverse un directorio hacia arriba y traduce la petición como /private.

Viendo la fuente de la página del formulario de avatar, veremos que el set de avatares contiene lo que hay en el directorio /private, aunque codificado en base64.

Decodificando revela la bandera que buscamos.

Así que inspeccionamos un botón de radio, cambiamos el valor de la URL de la imagen a x/../private y examinamos la fuente de la página.

Resultado de SSRF

Decodificamos:

echo "VEhNe1lPVV9XT1JLRURfT1VUX1RIRV9TU1JGfQ==" | base64 -d

Y obtenemos la bandera.

THM{YOU_WORKED_OUT_THE_SSRF}