Server-Side Request Forgery#
Una vulnerabilidad SSRF se da cuando un atacante manipula una aplicación para realizar solicitudes a URLs arbitrarias.
Por ejemplo, si un servidor debe solicitar datos de otros servidores en función del input de un usuario, un atacante puede hacer que las solicitudes se hagan a sitios o recursos en los que el desarrollador no había pensado en un primer momento.
Ejemplo#
En su forma más simple, una vulnerabilidad SSRF puede ser así:
En este caso, se va a registrar un usuario nuevo, y para comprobar la disponibilidad del nombre, vemos que nuestro navegador manda lo siguiente al servidor en el que nos estamos registrando:
| |
Si cambiamos el campo unameserver a, p.ej, nuestra IP:
| |
Podemos ver que recibimos la solicitud, confirmando la vulnerabilidad:
| |
Comprobar visibilidad output SSRF#
Para ver si, aunque haya SSRF en un host, el output del SSRF se nos muestra, podemos hacer que el campo de la URL apunte hacia el propio objetivo (ya sea su propia IP pública, dominio o localhost)
| |
Si nos devuelve el mismo index.html que nos devuelve el servidor cuando nos conectamos a él nosotros mismos, y podemos verlo, significa que el SSRF es visible.
Enumeración de servicios interna#
Gracias al hecho de poder conectarnos a cualquier URL, podemos enumerar los servicios internos del servidor redirigiendo la URL hacia localhost y el puerto a enumerar.
De forma automatizada:
| |
Output:
| |
Local File Inclusion#
Podemos usar otros protocolos que no sean http a la hora de hacer la solicitud, por ejemplo file://, que nos permite ver archivos locales:
| |
Protocolo gopher#
Aunque podemos usar SSRF para acceder a recursos protegidos, estamos limitados a solicitudes GET, pues no hay forma de mandar datos POST únicamente desde la URL.
El protocolo gopher nos permite mandar bytes “en crudo” a sockets TCP, lo que nos permite a su vez mandar solicitudes POST o de cualquier otro tipo (o protocolo) a los puertos que necesitemos.
P.ej, para mandar:
| |
Lo encodeamos en formato URL y añadimos el prefijo de gopher (_) antes del payload
- Protocolo y host:
gopher://internal.server.com:80/ - Prefijo gopher:
_ - Solicitud encodeada:
POST%20%2Fadmin.php%20HTTP%2F1.1%0AHost%3A%20internal.server.com%0AContent-Length%3A%2014%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0A%0Apassword%3Dhello
Esto deja la URL como: gopher://internal.server.com:80/_POST%20%2Fadmin.php%20HTTP%2F1.1%0AHost%3A%20internal.server.com%0AContent-Length%3A%2014%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0A%0Apassword%3Dhello.
De nuevo, como esta URL la vamos a poner en un campo en otra solicitud HTTP, p.ej:
| |
Vamos a necesitar encodear de nuevo toda la URL, lo que deja la solicitud final así:
| |
Podemos usar Gopherus como herramienta que automatiza la creación de payloads de gopher.
Blind SSRF#
Si el output de nuestra solicitud realizada no es visible (p.ej, si se devolviese únicamente un mensaje usuario disponible o usuario no disponible al hacer la solicitud mediante SSRF), en función del comportamiento del servidor seguiríamos pudiendo enumerar ciertas cosas.
Si, por ejemplo, el servidor devuelve usuario disponible cuando un archivo existe y usuario no disponible cuando no (o cuando se devuelve un error), podríamos seguir enumerando la existencia de archivos en el servidor o los puertos abiertos en el mismo.

