Skip to content
CyberXplore - Xplore the Unseen

De la SSRF a la toma total de una cuenta en la nube: atacando el servicio de metadatos

cyberxplorePor cyberxplore13 min de lectura

Un solo fallo SSRF en un recuperador de URL puede alcanzar el punto de acceso de metadatos de la nube, robar las credenciales de rol IAM y terminar en la toma total de la cuenta. Aquí tienes la cadena de ataque – y cómo romperla.

De la SSRF a la toma total de una cuenta en la nube: atacando el servicio de metadatos

Entréguennos una aplicación web que recupere una URL que usted controla – un importador de avatares, un probador de webhooks, un botón del estilo “genera un PDF a partir de este enlace” – y lo primero que probamos es un sondeo SSRF contra los metadatos de la nube. La dirección de destino apenas cambia de un objetivo a otro: la dirección link-local 169.254.169.254, donde AWS (y, por rutas ligeramente distintas, GCP y Azure) ejecuta un servicio de metadatos de instancia que entrega credenciales IAM temporales a la carga de trabajo.

Esa única petición es todo el juego. Un hallazgo que se lee como “el servidor hizo una llamada saliente que no debía” se convierte discretamente en “el servidor nos entregó su identidad en la nube”. Hemos visto cómo un proxy de imágenes de solo lectura se convirtió en un punto de apoyo que leía buckets de S3 y enumeraba otros roles. La server-side request forgery es la CWE-918, y en un host en la nube casi nunca es una mera nota informativa en el informe.

Este recorrido sigue la cadena completa: cómo una función corriente se convierte en SSRF, cómo la petición aterriza en el punto de acceso de metadatos, por qué IMDSv1 frente a IMDSv2 decide si el ataque funciona, y cómo unas credenciales robadas escalan hacia la toma de la cuenta. Luego, las defensas que de verdad aguantan bajo prueba.

Conclusiones clave

  • La SSRF (CWE-918) hace que un servidor envíe peticiones HTTP a destinos que elige el atacante, incluidas direcciones internas que la aplicación puede alcanzar pero la internet pública no.
  • El premio en un host en la nube es el punto de acceso de metadatos en 169.254.169.254. En AWS EC2 con IMDSv1 devuelve credenciales de rol IAM temporales por HTTP en claro y sin autenticación alguna.
  • Esas credenciales se enchufan directamente en la AWS CLI o en un SDK. Si el rol de la instancia tiene permisos de más, el fallo escala a robo de datos, movimiento lateral y toma de la cuenta.
  • IMDSv2 exige un token de sesión emitido por PUT e impone un límite de saltos, lo que rompe la mayoría de los intentos ingenuos de SSRF hacia los metadatos. Imponerlo – es decir, deshabilitar IMDSv1 – es la única corrección de mayor impacto.
  • Superponga el resto: allowlists de egress, bloqueo de los rangos link-local y RFC 1918, volver a resolver las URL tras cada redirección y roles de instancia de mínimo privilegio.

¿Qué es la SSRF y por qué la nube la empeora?

La SSRF es un defecto en el que una aplicación acepta como entrada una URL o un nombre de host y realiza una petición del lado del servidor hacia él, lo que permite a un atacante dirigir esa petición a donde nunca debió ir. El navegador queda fuera de juego. Es el servidor vulnerable el que hace la llamada en su lugar, desde dentro de la frontera de confianza, más allá del cortafuegos perimetral, con el acceso a la red interna que tenga el host.

En una máquina normal ya es grave: paneles de administración internos, una instancia de Redis o Elasticsearch sin autenticar, un barrido rápido de la subred interna. La nube sube la apuesta por una razón muy concreta. Todo gran proveedor ejecuta un servicio de metadatos en la misma dirección link-local mágica, 169.254.169.254, alcanzable solo desde la propia instancia, y su único cometido es entregar secretos al código que se ejecuta allí. Engañe a la aplicación para que lo consulte y el atacante hereda la identidad de la instancia.

¿Cómo se convierte una función normal en SSRF?

La función vulnerable suele ser una que el equipo de producto lanzó con cierto orgullo. Los sospechosos habituales que probamos:

  • Recuperadores de URL e “importar desde un enlace”: foto de perfil por URL, “importa tus datos desde esta URL”, importadores de RSS y de sitemap. El servidor desreferencia todo lo que usted pegue.
  • Webhooks y probadores de callback: “enviaremos tus eventos por POST a tu punto de acceso, pulsa Probar.” Ese botón de prueba dispara una petición del lado del servidor hacia un host que usted elige.
  • Renderizadores de PDF e imágenes: los motores de HTML a PDF y los capturadores de pantalla con Headless-Chrome siguen referencias <img>, <iframe> y CSS url(). Apunte uno al punto de acceso de metadatos y la salida renderizada puede filtrarle la respuesta de vuelta.
  • Procesadores de documentos y de SVG: los parseadores de XML y los renderizadores de SVG pueden ser inducidos a recuperar recursos externos – ahí es donde una XXE se convierte discretamente en SSRF.

La señal reveladora es cualquier parámetro que acaba convirtiéndose en una petición saliente. Confirmamos ese comportamiento primero con un payload fuera de banda, normalmente Burp Collaborator o un interactsh autoalojado, antes de tocar nada interno:

POST /api/avatar/import HTTP/1.1
Host: example.com
Content-Type: application/json

{"image_url":"http://abcd1234.oastify.com/ping"}

Si el listener registra un impacto, el servidor está recuperando URL por nosotros. Fíjese en si fue solo una resolución DNS o una devolución de llamada HTTP completa, porque un impacto solo de DNS a veces apunta a una tubería de renderizado que resuelve pero no muestra el cuerpo. En cualquier caso, ahora lo apuntamos hacia algo interesante.

¿Cómo se alcanza el punto de acceso de metadatos en 169.254.169.254?

Una vez confirmadas las peticiones salientes, cambiamos el host externo por la dirección link-local de metadatos. En una instancia EC2 con IMDSv1, el primer paso pregunta qué rol está adjunto:

GET /latest/meta-data/iam/security-credentials/ HTTP/1.1
Host: 169.254.169.254

Entregado a través del parámetro vulnerable, eso no es más que:

{"image_url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/"}

La respuesta es el nombre del rol. Añádalo a la ruta y el punto de acceso devuelve credenciales vivas:

GET /latest/meta-data/iam/security-credentials/example-app-role HTTP/1.1
Host: 169.254.169.254
{
  "Code": "Success",
  "AccessKeyId": "ASIAEXAMPLEKEY",
  "SecretAccessKey": "EXAMPLEsecret...",
  "Token": "IQoJb3JpZ2luX2VjE...",
  "Expiration": "2026-07-02T18:00:00Z"
}

Cuando un desarrollador ha atornillado una blocklist ingenua, salen a la luz los clásicos bypasses. En decimal, la misma IP es http://2852039166/; en octal, http://0251.0376.0251.0376/; y en una forma IPv6 mapeada a IPv4, http://[::ffff:169.254.169.254]/. Un nombre DNS que resuelva a la dirección link-local también funciona. Nuestro favorito en la práctica es un open redirect en un dominio permitido: la aplicación valida obedientemente que la URL apunta a un host de confianza, sigue el 302 y aterriza igualmente en el punto de acceso de metadatos. Por eso exactamente validar la cadena de URL inicial, por sí sola, no basta.

¿Cuál es la diferencia entre IMDSv1 e IMDSv2?

Esta es la diferencia entre un medio y un crítico. IMDSv1 es un simple servicio de petición-respuesta: cualquier proceso capaz de enviar un GET a 169.254.169.254 obtiene respuesta. Sin token, sin sesión, sin autenticación. Es exactamente la forma de una SSRF básica – por eso los dos son una pareja tan peligrosa.

IMDSv2 vuelve el flujo con estado. El cliente envía primero un PUT para obtener un token y luego incluye ese token como cabecera en cada GET posterior:

PUT /latest/api/token HTTP/1.1
Host: 169.254.169.254
X-aws-ec2-metadata-token-ttl-seconds: 21600
GET /latest/meta-data/iam/security-credentials/ HTTP/1.1
Host: 169.254.169.254
X-aws-ec2-metadata-token: <token-from-put>

Dos propiedades derrotan aquí a la mayoría de las SSRF. Primero, hace falta un PUT, y muchas primitivas de SSRF solo emiten GET y no pueden controlar el método. Segundo, hace falta una cabecera de petición personalizada que el recuperador vulnerable no añadirá por usted. IMDSv2 fija además un límite de saltos de respuesta predeterminado de 1, así que si la petición se ha reenviado aunque sea por un salto de red adicional, el servicio de metadatos la descarta en silencio. Lo que queremos ver impuesto es IMDSv1 deshabilitado, no meramente IMDSv2 disponible.

Que IMDSv2 esté disponible no cambia nada por sí solo. Si IMDSv1 se sigue aceptando, un atacante simplemente usa la vía antigua, sin token. El ajuste que importa es HttpTokens = required.

¿Cómo se convierte el acceso a credenciales robadas en toma de la cuenta?

Las credenciales del servicio de metadatos son claves temporales STS corrientes: una clave de acceso, un secreto y un token de sesión. Exportamos las tres y manejamos la CLI con la identidad del rol de la instancia:

export AWS_ACCESS_KEY_ID=ASIAEXAMPLEKEY
export AWS_SECRET_ACCESS_KEY=EXAMPLEsecret...
export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjE...
aws sts get-caller-identity

A partir de aquí, el radio de impacto es una función directa de lo que ese rol tiene permitido hacer. El primer movimiento es una enumeración discreta: qué buckets, qué secretos, qué otros roles. Si el rol puede leer Secrets Manager o SSM Parameter Store, sacamos rutinariamente contraseñas de bases de datos y claves de API que abren mucho más que la única instancia. Si porta amplios derechos IAM – el antipatrón que vemos demasiado a menudo -, el camino a la toma es corto: adjuntar una política de admin, acuñar una clave de acceso nueva en un usuario privilegiado o asumir un rol más fuerte. Del lado del atacante, esto encaja con MITRE ATT&CK Unsecured Credentials (T1552) y con la reutilización de material de autenticación alternativo.

La lección de años de estos trabajos es rotunda. La gravedad de una SSRF la fija el rol de la instancia, no el fallo web en sí. Un rol de alcance ajustado convierte un hallazgo de aspecto aterrador en uno contenido. Un rol permisivo convierte un único parámetro de URL en un incidente de alcance en toda la nube.

¿Cómo se previenen los ataques de SSRF hacia los metadatos?

No hay un interruptor único, así que recomendamos superponer los controles de abajo. Cualquiera por separado puede eludirse. Apilados juntos, hacen que la cadena sea genuinamente difícil de completar.

  • Imponer IMDSv2 y deshabilitar IMDSv1. Ponga HttpTokens en required en cada instancia e incorpórelo a las launch templates y a las AMIs para que los hosts nuevos lo hereden por defecto. Donde una carga de trabajo nunca necesite los metadatos de instancia, apague el punto de acceso por completo.
  • Bloquear los rangos link-local y privados. La aplicación – o un proxy de reenvío por el que deba pasar obligatoriamente – debería rechazar conexiones a 169.254.0.0/16, a los rangos RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) y al loopback. Hágalo en la capa de red, no solo en el código de la aplicación.
  • Filtrado de egress con allowlists. El tráfico saliente de los hosts de aplicación solo debería alcanzar los destinos que una función necesita legítimamente. Un recuperador de URL que solo tira de una única API de un socio no tiene nada que hacer en una IP interna.
  • Validar y volver a resolver las URL. Analice la URL, rechace los esquemas que no sean HTTP y los puertos raros, resuelva el nombre de host a una IP y compruebe esa IP contra su denylist antes de conectar. Vuelva a comprobar tras cada redirección para que un 302 no pueda colarle en el servicio de metadatos. Esto también mitiga el DNS rebinding.
  • Roles de instancia de mínimo privilegio. Ajuste cada rol a lo que su carga de trabajo usa realmente y a nada más. Es el control que pone tope al daño cuando los demás fallan.

Una advertencia del terreno: las blocklists de cadenas que casan “169.254.169.254” y se dan por satisfechas fallan constantemente frente a las formas decimal, octal e IPv6. Resuelva a una IP numérica y compare contra rangos, nunca contra el texto literal.

Cómo ayuda CyberXplore

La SSRF hacia los metadatos es una de las vías estándar que nuestros pentesters persiguen durante un trabajo de pruebas de penetración en la nube. Ejercitamos la función que hace peticiones salientes, intentamos la cadena completa hasta el servicio de metadatos y luego trazamos hasta dónde llegarían realmente las credenciales de rol robadas en toda su cuenta – para que obtenga el impacto de negocio real en lugar de una casilla marcada. Si quiere ejecutar esto contra su propio entorno, solicite un presupuesto y definiremos el alcance junto a usted.

FAQ

¿Sigue siendo la SSRF un riesgo real si opero en la nube con un cortafuegos?

Sí. Un cortafuegos perimetral no hace nada aquí, porque la petición maliciosa se origina dentro de su propia instancia, justo donde el servicio de metadatos es alcanzable. La SSRF convierte su servidor de confianza en el proxy del atacante, de modo que cualquier control que solo inspeccione el tráfico entrante queda eludido. Necesita controles de egress e IMDSv2 impuesto, no solo un cortafuegos de entrada.

¿Detiene IMDSv2 por completo que la SSRF robe credenciales?

Detiene la gran mayoría de los casos del mundo real, pero no es absoluto. IMDSv2 derrota la SSRF limitada a GET y cualquier petición que cruce un salto adicional, lo que cubre la mayoría de los fallos que encontramos. Una SSRF muy flexible, capaz de emitir un PUT e inyectar la cabecera personalizada requerida, aún podría pasar – por eso IMDSv2 va junto a los roles de mínimo privilegio y al filtrado de egress, en vez de tratarse como el único control.

¿Qué es la dirección 169.254.169.254 y por qué no deja de aparecer?

Es la IP link-local que los proveedores de nube usan para exponer su servicio de metadatos de instancia, alcanzable solo desde la propia instancia. En AWS sirve los metadatos de EC2 y, sobre todo, las credenciales de rol IAM temporales. GCP y Azure exponen servicios similares en esa dirección o mediante nombres de host de metadatos – lo que la convierte en el primer objetivo universal en cuanto un atacante confirma una SSRF en un host en la nube.

¿Cómo sé si una función es vulnerable antes de que lo haga un atacante?

Busque cualquier entrada que se convierta en una petición saliente del lado del servidor: importadores de URL, webhooks, renderizadores de PDF o de imágenes, parseadores de documentos. Pruebe cada una con un listener fuera de banda como Burp Collaborator o interactsh. Si el servidor alcanza su listener, compruebe si también alcanza direcciones internas y link-local y si sigue las redirecciones hacia ellas. Ese es el comportamiento que sondeamos en una prueba de penetración.

¿Qué CWE y qué estándares cubren este problema?

La server-side request forgery es la CWE-918, y tiene su propia categoría, la A10, en el OWASP Top 10 (2021). Del lado del atacante, cosechar credenciales de instancia y usarlas se corresponde con MITRE ATT&CK en torno a las unsecured credentials (T1552) y al uso de material de autenticación alternativo. Citarlos en un informe ayuda a los equipos a priorizar y a encaminar la corrección correctamente.

¿Cuál es la corrección más importante por sí sola?

Imponga IMDSv2 con IMDSv1 deshabilitado en cada instancia y luego ajuste sus roles de instancia al mínimo privilegio. El primer cambio rompe de plano la técnica común de SSRF hacia los metadatos. El segundo garantiza que incluso un robo de credenciales exitoso quede contenido en un conjunto pequeño y bien entendido de permisos en lugar de en toda su cuenta.

Trabaja con CyberXplore

Pruebas de Penetración en la Nube

Ves este riesgo en tus propios sistemas? Nuestros testers senior encuentran y demuestran exactamente estos fallos y te dan un camino claro para corregirlos.

Artículos relacionados

Convierte estos análisis en un proyecto

Obtén una prueba de penetración dirigida por expertos senior y adaptada a tu stack - resultados accionables, no una checklist.

  • Retest gratuito de cada corrección
  • Alcance y presupuesto en 24 horas
  • Solo evaluadores sénior
  • ISO 27001
  • ISO 9001
  • OSCP
  • CRTP
  • CREST
Solicitar presupuesto