SSRF - Server-Side Request Forgery (Labs & Técnicas)
🔍 ¿Qué es SSRF?
Server-Side Request Forgery (SSRF) es una vulnerabilidad de seguridad web que permite a un atacante engañar a una aplicación del lado del servidor para que realice solicitudes HTTP (u otros protocolos) hacia destinos no previstos o controlados por el atacante.
🧨 En un ataque SSRF, el servidor puede ser manipulado para acceder a:
-
Servicios internos que normalmente no son accesibles desde el exterior (por ejemplo,
localhosto direcciones privadas como192.168.x.x). -
Sistemas externos arbitrarios, lo que puede derivar en filtraciones de información sensible como credenciales o tokens de autorización.
⚠️ Impacto de los ataques SSRF
Un ataque SSRF exitoso puede tener consecuencias graves, tales como:
-
Acceso no autorizado a datos sensibles.
-
Realización de acciones dentro de la aplicación o en sistemas internos conectados.
-
En ciertos casos, ejecución remota de comandos.
🔁 Ejemplo común de ataque SSRF

Imagina una aplicación de compras donde el usuario puede consultar el stock de un producto en diferentes tiendas. El frontend envía una URL al servidor para consultar la API de stock:
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
stockApi=http://stock.weliketoshop.net:8080/product/stock/check?productId=6&storeId=1
Sin embargo, un atacante puede modificar esta petición para forzar al servidor a acceder a una ruta interna protegida:
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
stockApi=http://localhost/admin:8080
✅ Esto hace que el servidor mismo acceda a http://localhost/admin:8080, una ruta normalmente protegida y accesible solo desde dentro.
🔓 Desde el navegador del atacante, esta URL estaría bloqueada. Pero al hacer que el propio servidor realice la petición, se bypassean los controles de acceso, ya que parece una solicitud legítima desde el entorno interno.
Así, el atacante logra acceder a información o funciones a las que no debería tener acceso, aprovechando la confianza que tiene la aplicación en sí misma.
🧪 Laboratorios prácticos
Ahora que ya entiendes qué es un ataque SSRF, ¡es momento de ponerlo en práctica!
Vamos a explorar algunos laboratorios interactivos de la academia de seguridad web de Burp Suite.
🔗 Accede aquí a los laboratorios de SSRF de PortSwigger:
**Accede aquí a los laboratorios de SSRF de PortSwigger
💡 Necesitarás crear una cuenta gratuita en PortSwigger para acceder a los labs.
Basic SSRF against the local server
📜 Enunciado del laboratorio:
This lab has a stock check feature which fetches data from an internal system.
To solve the lab, change the stock check URL to access the admin interface at `http://localhost/admin` and delete the user `carlos`.
En este laboratorio estamos ante una tienda en línea simulada, con un catálogo de productos ficticios:

📦 Al hacer clic en un producto, tenemos la opción de consultar el stock disponible en distintas ciudades.
Esto desencadena una consulta que el navegador envía al servidor.

Cuando interceptamos la solicitud con Burp Suite, observamos que el parámetro stockApi contiene la URL que el servidor utilizará para consultar la API de stock:
stockApi=http%3A%2F%2Fstock.weliketoshop.net%3A8080%2Fproduct%2Fstock%2Fcheck%3FproductId%3D1%26storeId%3D1
🔎 Si hacemos Ctrl + Shift + U en Burp Suite, podemos decodificar esta URL y ver el valor real:
http://stock.weliketoshop.net:8080/product/stock/check?productId=1&storeId=1
Según el enunciado del laboratorio, el objetivo es hacer que el servidor acceda a su propia interfaz interna de administración, ubicada en` http://localhost/admin
➡️ Simplemente modificamos la solicitud interceptada en Burp Suite así:
stockApi=http://localhost/admin
Y pum ya estamos en el panel de administrador

Ahora nos falta eliminar el usuario carlos. Para eso tenemos que hacer
stockApi=http://localhost/admin/admin/delete?username=carlos

Basic SSRF against another back-end system
📜 Enunciado del laboratorio:
This lab has a stock check feature which fetches data from an internal system.
To solve the lab, use the stock check functionality to scan the internal `192.168.0.X` range for an admin interface on port `8080`, then use it to delete the user `carlos`.
-
Identificar cuál dirección IP dentro del rango
192.168.0.1-192.168.0.254contiene una interfaz administrativa accesible en el puerto8080. -
Acceder a esa interfaz.
-
Eliminar al usuario
carlos.

Al igual que en el laboratorio anterior, entramos en cualquier producto y capturamos la solicitud enviada al consultar el stock.
El parámetro clave es stockApi, que contiene una URL codificada. 🔓 Decodificamos con Ctrl + Shift + U en Burp Suite.
📌 Usamos Ctrl + I para enviar esta solicitud a Intruder, y configuramos el ataque de la siguiente forma:
stockApi=http://192.168.0.$1$:8080/admin
Seleccionamos el número 1 con doble clic y pulsamos "Add $" para marcarlo como un payload dinámico.
Vamos a la pestaña Payloads, y elegimos:
-
Payload type: Numbers
-
From: 1
-
To: 254
-
Step: 1
Esto generará una IP por cada intento:
192.168.0.1, 192.168.0.2, ..., 192.168.0.254
📊 Esto simula un escaneo de red interna.

Al ordenar la columna Status Code en Burp Intruder de menor a mayor, detectamos que la IP: http://192.168.0.15:8080/admin Respondió con **Status Code 200**, lo que indica una conexión **exitosa** al panel de administración interno. 🟢  👉 Una vez identificada la IP interna (192.168.0.15), enviamos la petición a **Repeater** (Ctrl + R), modificamos el valor del parámetro stockApiporhttp://192.168.0.15:8080/admin/delete?username=carlos` y presionamos Send. ¡El laboratorio está completado con éxito! ✅

SSRF with blacklist-based input filter
📜 Enunciado del laboratorio:
This lab has a stock check feature which fetches data from an internal system.
To solve the lab, change the stock check URL to access the admin interface at `http://localhost/admin` and delete the user `carlos`.
The developer has deployed two weak anti-SSRF defenses that you will need to bypass.
En este caso, la URL http://localhost/admin no funciona debido a una lista negra de entrada que bloquea el acceso directo a localhost. Para evadir esta protección, intentamos varias combinaciones de cómo representar 127.0.0.1, incluyendo variaciones como 127.1. Observamos que 127.1 es aceptado, pero al agregar /admin en la URL, también es bloqueado. Esto indica que el sistema detecta y bloquea direcciones que comienzan con 127.0.0.1 y que tenga /admin.
Para superar esta restricción, aplicamos doble codificación en la ruta /admin. Esta técnica permitió eludir el filtro y acceder finalmente a la URL protegida. Así, la URL modificada para eliminar al usuario carlos se convierte en:
stockApi=http://127.1/%25%36%31%25%36%34%25%36%64%25%36%39%25%36%65/delete?username=carlos
Para encodear el admin en tipo URL:


SSRF with whitelist-based input filter
📜 Enunciado del laboratorio:
This lab has a stock check feature which fetches data from an internal system.
To solve the lab, change the stock check URL to access the admin interface at `http://192.168.0.12:8080/admin` and delete the user `carlos`.
The stock checker has been restricted to only access the local application, so you will need to find an open redirect affecting the application first.
Veamos como lo que bloquae poniendo stockApi=http://127.1/admin. No s pone "External stock check host must be stock.weliketoshop.net"

La redirección abierta es una vulnerabilidad que permite a un atacante redirigir a un usuario a un sitio web arbitrario. Esta vulnerabilidad ocurre cuando una aplicación permite que un parámetro de URL contenga una dirección URL externa no validada, permitiendo que se redirija a cualquier sitio
En este caso, hemos identificado una vulnerabilidad de redirección abierta en el sitio. Al hacer clic en el botón "Next product" en la página, observamos que se produce una redirección a otra URL basada en los parámetros pasados. Comprobamos esto al cambiar el parámetro path para redirigir a un sitio externo, como https://www.marca.com/, lo que efectivamente nos llevó a esa página.
/product/nextProduct?currentProductId=1&path=/product?productId=2
/product/nextProduct?currentProductId=1&path=https://www.marca.com/

Al explotar esta vulnerabilidad, podemos manipular el parámetro path para que en lugar de redirigirnos a una página externa legítima, redirijamos a un sistema interno del servidor. Modificamos la URL de la siguiente manera:
stockApi=/product/nextProduct?currentProductId=1&path=http://192.168.0.12:8080/admin

Esto nos llevará a la página de administración del servidor interno. Luego, para eliminar al usuario carlos, modificamos la URL de la siguiente manera:
stockApi=/product/nextProduct?currentProductId=1&path=http://192.168.0.12:8080/admin/delete?username=carlos
SSRF with whitelist-based input filter
📜 Enunciado del laboratorio:
This lab has a stock check feature which fetches data from an internal system.
To solve the lab, change the stock check URL to access the admin interface at `http://localhost/admin` and delete the user `carlos`.
The developer has deployed an anti-SSRF defense you will need to bypass.
Paso inicial:
-
Modifica el parámetro
stockApiahttp://127.0.0.1/.Resultado:
✅ Esto confirma que el servidor está usando una lista blanca (whitelist), que solo permite URLs que apunten al dominiostock.weliketoshop.net.Comportamiento:
El desarrollador implementó una protección que verifica que el host de la URL sea exactamentestock.weliketoshop.net. Si no coincide, bloquea la solicitud. Este tipo de defensa es común, pero puede ser engañada si el análisis de la URL no está bien implementado.

¿Cómo podemos evadir esta protección?
1. Ingresando credenciales embebidas en la URL:
Prueba con la siguiente URL:
stockApi=http://localhost@stock.weliketoshop.net/
-
🔍 Qué hace el validador: El validador superficial solo ve
stock.weliketoshop.net→ ✅ Pasa. -
🔁 Qué hace el servidor: El servidor se conecta a
localhost(puerto 80), lo que nos da acceso a un servicio interno.

Introducción del # (fragmento de la URL):
Prueba añadiendo el fragmento #:
stockApi=http://localhost#@stock.weliketoshop.net/
¿Qué hace el símbolo # en una URL?
Fragmento de URL (hash):
-
En las URLs, el símbolo
#introduce un fragmento (o fragment identifier). Todo lo que viene después de#no se envía al servidor en una solicitud HTTP. -
El fragmento es solo interpretado por el navegador para saltar a una sección específica de un documento HTML, como un
<div id="seccion">.
Ejemplo clásico de un fragmento:
https://example.com/page#section1
🔁 El navegador solo envía:
GET /page HTTP/1.1
El navegador ignora completamente #section1. Este fragmento nunca se envía al servidor.
Doble codificación del #
Para evitar que el filtro detecte el fragmento, aplicamos doble codificación al #:
stockApi=http://localhost%2523@stock.weliketoshop.net/
¿Qué hace este payload?
-
El servidor se conecta a
localhost(puerto 80). -
El validador superficialmente sigue viendo
stock.weliketoshop.netcomo host válido, y no detecta ellocalhost. -
El
%2523es la doble codificación del#, que engaña al parser del servidor.
Payload final para eliminar el usuario carlos
Una vez que hemos logrado evadir la validación, para acceder a la interfaz de administración y eliminar al usuario carlos, utilizamos este payload:
stockApi=http://localhost%2523@stock.weliketoshop.net/