¿ Que es un SSRF ?
El Server-Side Request Forgery ( SSRF ) es una vulnerabilidad de seguridad en la que un atacante pueda forzar a un servidor web para que realice solicitudes HTTP en su nombre.
En un ataque de SSRF, el atacante utiliza una entrada del usuario, como una URL o un campo de formulario, para enviar una solicitud HTTP a un servidor web. El atacante manipula la solicitud para que se dirija a un servidor vulnerable o a una red interna a la que el servidor web tiene acceso.
El ataque se SSRF puede permitir al atacante acceder a información confidencial, como contraseñas, claves de API y otros datos sensibles, y también puede llegar a permitir al atacante (en función del escenario) ejecutar comandos en el servidor web o en otros servidores en la red interna.
Una de las diferencias clave entre el SSRF y el CSRF - (Cross-Side Request Forgery) es que el SSRF se ejecuta en el servidor web en lugar del navegador del usuario. El atacante no necesita engañar a un usuario legítimo para hacer click en un enlace malicioso, ya que puede enviar la solicitud HTTP directamente al servidor web desde una fuente externa.
Para explotar un SSRF, primero hay que entender los diversos escenarios que podrian haber, en este caso vamos a hacer de manera local dos escenarios diferentes.
En este caso contamos con un entorno en docker, el cual contiene una máquina ubuntu la cual hostea un servicio web por el puerto 80, su ip es la 172.0.0.2 y contiene un servicio en el puerto 4343 unicamente disponible para el localhost, es decir, que este servicio no esta publico para nadie que no sea la máquina 172.0.0.2.
Ahora bien, esta servicio por el puerto 80 tiene un login.html asi como un recurso de utility.php, siendo este un recurso el cual permite en un punto ingresar un parametro denominado "?url=" en la URL para apuntar a una determinada url ingresada y volcar su contenido. Es en este punto cuando podemos empezar a pensar en un SSRF, ya que si existieran reistricciones en esta maquina las cuales bloquearan determinados puertos para el público, pero de manera interna se permite ver dichos puertos, abusando de alguna utilidad como la de utility.php podriamos realizar FUZZING (Explicado en Fase de Reconocimiento) para intentar enumerar diversos puertos internos que pudiesen llegar a existir los cuales por alguna configuración no esten abiertos al puerots pero si para la maquina en si.
En este caso, supongamos que la maquina ejecuta el comando python3 -m http.server 4343 --bind 127.0.0.1, de esta manera la máquina victima (172.17.0.2) cuenta con el puerto :80 corriendo disponibles para todos y el puerto :4343 abierto tambien pero solo disponible para su localhost. Aca es donde podemos abusar del archivo utility.php el cual permite apuntar a recursos externos, solo que en este caso, haremos que apunte a todos sus puertos para ver la respuesta que sea distinta para asi determinar que otros puertos contiene abiertos.
wfuzz -c -t 200 --hw=8 -z range,1-65535 "http://172.17.0.2/utility.php?url=http://127.0.0.1:FUZZ" jugando con wfuzz, podriamos determinar aquellos puertos internos que esten abiertos, dando como resultado asi, que el puerto 80 y 4343 estan abiertos.
De esta manera, tendriamos una vía potencial para enumerar puertos abiertos los cuales no deberiamos ver, ya sea que hostean aplicaciones en producción, recursos privilegiados, archivos de configuraciónes, etc. por lo que estariamos explotando un SSRF.
En este caso contamos con un entorno el cual, una vez más tenemos un contenedor de docker que tiene una maquina que hostea un servicio web por el puerto 80, su ip es, una vez más, la 172.17.0.2, con la diferencia de que esta vez no tiene ningun servicio configurado el cual no tengamos accesible, simplemente forma parte de una red interna en donde tiene la ip asignada de 10.10.0.2 y en esta red, existe otra máquina con la ip 10.10.0.3 la cual si hostea un servicio por el puerto 4343.
Si quisieramos crear este escenario deberiamos en primer lugar, crear una sub red con el comando docker network create --dirver=bridge {name} --subnet={ip}/{cidr}, luego crear 3 máquinas, una atacante, una producción y otra pre producción. (La máquina de PRO, la creamos como siempre y la agregamos a la red creada con docker network connect {network_name} {machine_name}, la máquna de PRE solo deberia estar en la network creada por lo que la creamos con
docker run -dit --name PRE network={network_name} ubuntu y la máquina de atacante solo en nuestra red, de esta manera, la máquina atacante esta en la misma red que la de PRO, la PRO en una con PRE y PRE solo en una con PRO. )
En este caso el concepto es el mismo pero con un leve Pivoting, en donde podriamos realizar un SSRF abusando del archivo utility.php (En este ejemplo támbien lo tiene), donde podriamos, luego de realizar cierto reconocmiento, ingresar la url maliciosa para escanear puertos de una máquina en una subred de la máquina principal: http://172.17.0.2/utility.php?url=http://10.10.0.3:464
Algo que se puede intentar hacer a la hora de tener SSRF es enumerar con gopher:// base de datos en caso de que tengamos la certeza (O creencia) de que existe un usuario a nivel base de datos el cual no esta protegido por contraseña.
Gopher es un servicio de Internet consistente en el acceso a la información a través de menús. La información se organiza en forma de árbol: solo los nodos contienen menús de acceso a otros menús o a hojas, mientras que las hojas contienen simplemente información textual.
Jugando con la herramienta gopherus que se encarga de generar payloads para listar base de datos haciendo uso de gopher.
Una vez generado el payload, al pegarlo en el input vulnerable a SSRF - (Server-Side Request Forgery) se podría ejecutar la accion solicitada, como listar información de la base de datos, intentar alterar datos, etc.