S3: el bucket que quedó público sin querer
La fuga de datos más común en la nube no es un hackeo: es un bucket mal configurado. Acá ves las cuatro capas que deciden si un objeto es público y cómo verificarlo antes de que lo haga un escáner ajeno.
Antes de empezar necesitás
- Idea básica de qué es S3 y un bucket
- Haber leído una policy de IAM (lab: IAM, Deny gana)
Al terminar vas a poder
- Entender las capas que deciden el acceso: Block Public Access, policy, ACL y permisos de IAM
- Leer una bucket policy y detectar el Principal '*'
- Verificar si un bucket es público sin adivinar
- Aplicar el default seguro: Block Public Access activado
La filtración de datos más repetida de la última década no fue un exploit ingenioso: fue un bucket de S3 que quedó público. Nadie “entró”; estaba abierto y un escáner lo encontró. La buena noticia es que decidir si un objeto es público depende de capas concretas que podés leer y cerrar.
Las capas, de afuera hacia adentro
1. Block Public Access interruptor maestro. Si está ON, gana: nada es público.
2. Bucket policy JSON a nivel bucket. Un Principal "*" lo abre al mundo.
3. ACL del objeto permisos viejos por objeto (AllUsers = público).
4. IAM del que pide qué puede hacer esa identidad concreta.
La policy que abre el bucket
Esta es la que aparece en buckets filtrados. Leela despacio, fijate en el Principal:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::reportes-prod/*"
}
]
}
Verificar, no suponer
Antes de creer que está cerrado, confirmalo:
# ¿El Block Public Access está activado? Querés ver los cuatro flags en true.
aws s3api get-public-access-block --bucket reportes-prod
# ¿Hay una bucket policy? ¿tiene Principal "*"?
aws s3api get-bucket-policy --bucket reportes-prod \
--query Policy --output text | jq '.Statement[] | {Effect, Principal, Action}' Un BPA sano se ve así:
{
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}
El fix: cerrar y dejar el cinturón puesto
Primero sacá el Principal "*" de la policy (si el bucket sirve un sitio, eso se hace con CloudFront + OAC, no abriendo S3). Después prendé BPA para que ninguna policy futura lo vuelva a abrir:
aws s3api put-public-access-block --bucket reportes-prod \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true La policy privada típica no nombra Principal "*" en absoluto: el acceso lo dan los roles de IAM de tus servicios, cada uno con lo justo (mirá el lab de IAM y mínimo privilegio).
El criterio
1. ¿Block Public Access está ON a nivel cuenta? → cinturón maestro
2. ¿Alguna bucket policy tiene Principal "*"? → la puerta abierta clásica
3. ¿Hay ACLs públicas viejas (AllUsers)? → legado peligroso
4. ¿El acceso real lo dan roles de IAM acotados? → así debería ser
Lo que practicás en este lab
Llevátelo a tu repo si querés, pero no es obligatorio: es tu aprendizaje.
- El antes/después de una bucket policy: de pública a privada
- El comando con el que verificaste el estado de Block Public Access
- Writeup de 2 líneas: qué capa estaba dejando el bucket abierto
Reto
Tomá la policy 'abierta' de abajo y volvela privada. Después escribí en dos líneas qué chequeo correrías para confirmar, desde afuera, que ya nadie anónimo puede leer los objetos.
Resolvelo y escribí dos líneas explicando qué pasó. Con eso lo fijás.