AWS - S3 Unauthenticated Enum
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
S3 Buckets públicos
Un bucket se considera “público” si cualquier usuario puede listar el contenido del bucket, y “privado” si el contenido del bucket solo puede ser listado o escrito por ciertos usuarios.
Las empresas pueden tener permisos de buckets mal configurados que dan acceso ya sea a todo o a cualquier persona autenticada en AWS en cualquier cuenta (es decir, a cualquiera). Ten en cuenta que incluso con tales malas configuraciones algunas acciones podrían no poder ejecutarse ya que los buckets pueden tener sus propias listas de control de acceso (ACLs).
Aprende sobre misconfiguraciones de AWS-S3 aquí: http://flaws.cloud y http://flaws2.cloud/
Encontrar Buckets de AWS
Diferentes métodos para encontrar cuando una página web está usando AWS para almacenar algunos recursos:
Enumeration & OSINT:
- Usando la extensión del navegador wappalyzer
- Usando burp (spidering la web) o navegando manualmente por la página, todos los resources loaded se guardarán en el Historial.
- Revisa recursos en dominios como:
http://s3.amazonaws.com/[bucket_name]/
http://[bucket_name].s3.amazonaws.com/
- Comprueba CNAMES ya que
resources.domain.compodría tener el CNAMEbucket.s3.amazonaws.com - s3dns – Un servidor DNS ligero que identifica pasivamente cloud storage buckets (S3, GCP, Azure) analizando el tráfico DNS. Detecta CNAMEs, sigue cadenas de resolución y encuentra patrones de buckets, ofreciendo una alternativa silenciosa al descubrimiento por fuerza bruta o mediante API. Perfecto para recon y flujos de trabajo OSINT.
- Revisa https://buckets.grayhatwarfare.com, un sitio con buckets abiertos ya descubiertos.
- El bucket name y el bucket domain name necesitan ser el mismo.
- flaws.cloud está en la IP 52.92.181.107 y si vas allí te redirige a https://aws.amazon.com/s3/. Además,
dig -x 52.92.181.107devuelves3-website-us-west-2.amazonaws.com. - Para comprobar que es un bucket también puedes visitar https://flaws.cloud.s3.amazonaws.com/.
Brute-Force
Puedes encontrar buckets haciendo brute-forcing de nombres relacionados con la compañía que estás pentesting:
- https://github.com/sa7mon/S3Scanner
- https://github.com/clario-tech/s3-inspector
- https://github.com/jordanpotti/AWSBucketDump (Contiene una lista con posibles nombres de buckets)
- https://github.com/fellchase/flumberboozle/tree/master/flumberbuckets
- https://github.com/smaranchand/bucky
- https://github.com/tomdev/teh_s3_bucketeers
- https://github.com/RhinoSecurityLabs/Security-Research/tree/master/tools/aws-pentest-tools/s3
- https://github.com/Eilonh/s3crets_scanner
- https://github.com/belane/CloudHunter
# Generate a wordlist to create permutations
curl -s https://raw.githubusercontent.com/cujanovic/goaltdns/master/words.txt > /tmp/words-s3.txt.temp
curl -s https://raw.githubusercontent.com/jordanpotti/AWSBucketDump/master/BucketNames.txt >>/tmp/words-s3.txt.temp
cat /tmp/words-s3.txt.temp | sort -u > /tmp/words-s3.txt
# Generate a wordlist based on the domains and subdomains to test
## Write those domains and subdomains in subdomains.txt
cat subdomains.txt > /tmp/words-hosts-s3.txt
cat subdomains.txt | tr "." "-" >> /tmp/words-hosts-s3.txt
cat subdomains.txt | tr "." "\n" | sort -u >> /tmp/words-hosts-s3.txt
# Create permutations based in a list with the domains and subdomains to attack
goaltdns -l /tmp/words-hosts-s3.txt -w /tmp/words-s3.txt -o /tmp/final-words-s3.txt.temp
## The previous tool is specialized increating permutations for subdomains, lets filter that list
### Remove lines ending with "."
cat /tmp/final-words-s3.txt.temp | grep -Ev "\.$" > /tmp/final-words-s3.txt.temp2
### Create list without TLD
cat /tmp/final-words-s3.txt.temp2 | sed -E 's/\.[a-zA-Z0-9]+$//' > /tmp/final-words-s3.txt.temp3
### Create list without dots
cat /tmp/final-words-s3.txt.temp3 | tr -d "." > /tmp/final-words-s3.txt.temp4http://phantom.s3.amazonaws.com/
### Create list without hyphens
cat /tmp/final-words-s3.txt.temp3 | tr "." "-" > /tmp/final-words-s3.txt.temp5
## Generate the final wordlist
cat /tmp/final-words-s3.txt.temp2 /tmp/final-words-s3.txt.temp3 /tmp/final-words-s3.txt.temp4 /tmp/final-words-s3.txt.temp5 | grep -v -- "-\." | awk '{print tolower($0)}' | sort -u > /tmp/final-words-s3.txt
## Call s3scanner
s3scanner --threads 100 scan --buckets-file /tmp/final-words-s3.txt | grep bucket_exists
Loot S3 Buckets
Dado buckets S3 abiertos, BucketLoot puede automáticamente buscar información interesante.
Encontrar la región
Puedes encontrar todas las regiones soportadas por AWS en https://docs.aws.amazon.com/general/latest/gr/s3.html
Por DNS
Puedes obtener la región de un bucket con un dig y nslookup realizando una consulta DNS sobre la IP descubierta:
dig flaws.cloud
;; ANSWER SECTION:
flaws.cloud. 5 IN A 52.218.192.11
nslookup 52.218.192.11
Non-authoritative answer:
11.192.218.52.in-addr.arpa name = s3-website-us-west-2.amazonaws.com.
Comprueba que el dominio resuelto tenga la palabra “website”.
Puedes acceder al sitio web estático yendo a: flaws.cloud.s3-website-us-west-2.amazonaws.com
o puedes acceder al bucket visitando: flaws.cloud.s3-us-west-2.amazonaws.com
Al intentar
Si intentas acceder a un bucket, pero en el nombre de dominio especificas otra región (por ejemplo el bucket está en bucket.s3.amazonaws.com pero intentas acceder a bucket.s3-website-us-west-2.amazonaws.com), entonces se te indicará la ubicación correcta:
.png)
Enumerando el bucket
Para comprobar la apertura del bucket un usuario puede simplemente ingresar la URL en su navegador web. Un bucket privado responderá con “Access Denied”. Un bucket público listará los primeros 1,000 objetos que se hayan almacenado.
Accesible para todos:
.png)
Privado:
.png)
También puedes comprobar esto con el cli:
#Use --no-sign-request for check Everyones permissions
#Use --profile <PROFILE_NAME> to indicate the AWS profile(keys) that youwant to use: Check for "Any Authenticated AWS User" permissions
#--recursive if you want list recursivelyls
#Opcionally you can select the region if you now it
aws s3 ls s3://flaws.cloud/ [--no-sign-request] [--profile <PROFILE_NAME>] [ --recursive] [--region us-west-2]
Si el bucket no tiene un nombre de dominio, al intentar enumerate el bucket, solo coloca el bucket name y no todo el dominio AWSs3. Ejemplo: s3://<BUCKETNAME>
Plantilla de URL pública
https://{user_provided}.s3.amazonaws.com
Obtener el ID de la cuenta desde un Bucket público
Es posible determinar una cuenta de AWS aprovechando la nueva S3:ResourceAccount Policy Condition Key. Esta condición restringe el acceso en función del bucket S3 en el que está una cuenta (otras políticas basadas en la cuenta restringen en función de la cuenta en la que se encuentra el principal que realiza la solicitud).
Y debido a que la política puede contener comodines es posible encontrar el número de cuenta un número a la vez.
Esta herramienta automatiza el proceso:
# Installation
pipx install s3-account-search
pip install s3-account-search
# With a bucket
s3-account-search arn:aws:iam::123456789012:role/s3_read s3://my-bucket
# With an object
s3-account-search arn:aws:iam::123456789012:role/s3_read s3://my-bucket/path/to/object.ext
Esta técnica también funciona con API Gateway URLs, Lambda URLs, Data Exchange data sets e incluso para obtener el valor de las etiquetas (si conoces la clave de la etiqueta). Puedes encontrar más información en el original research y la herramienta conditional-love para automatizar esta explotación.
Confirmar que un bucket pertenece a una cuenta de AWS
Como se explica en this blog post, si tienes permisos para listar un bucket es posible confirmar el accountID al que pertenece el bucket enviando una solicitud como:
curl -X GET "[bucketname].amazonaws.com/" \
-H "x-amz-expected-bucket-owner: [correct-account-id]"
<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">...</ListBucketResult>
Si el error es “Access Denied” significa que el account ID era incorrecto.
Correos usados como root account enumeration
Como se explica en this blog post, es posible comprobar si una dirección de correo electrónico está relacionada con alguna cuenta AWS intentando conceder permisos a un correo sobre un bucket S3 vía ACLs. Si esto no provoca un error, significa que el correo es un root user de alguna cuenta AWS:
s3_client.put_bucket_acl(
Bucket=bucket_name,
AccessControlPolicy={
'Grants': [
{
'Grantee': {
'EmailAddress': 'some@emailtotest.com',
'Type': 'AmazonCustomerByEmail',
},
'Permission': 'READ'
},
],
'Owner': {
'DisplayName': 'Whatever',
'ID': 'c3d78ab5093a9ab8a5184de715d409c2ab5a0e2da66f08c2f6cc5c0bdeadbeef'
}
}
)
Referencias
- https://www.youtube.com/watch?v=8ZXRw4Ry3mQ
- https://cloudar.be/awsblog/finding-the-account-id-of-any-public-s3-bucket/
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
HackTricks Cloud

