AWS - S3 Unauthenticated Enum
Reading time: 9 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
S3 Public Buckets
Um bucket é considerado “público” se qualquer usuário puder listar o conteúdo do bucket, e “privado” se o conteúdo do bucket só puder ser listado ou escrito por determinados usuários.
Empresas podem ter permissões de buckets mal configuradas, dando acesso tanto a tudo quanto a qualquer pessoa autenticada na AWS em qualquer conta (portanto a qualquer um). Observe que, mesmo com tais más configurações, algumas ações podem não ser possíveis, pois os buckets podem ter suas próprias access control lists (ACLs).
Aprenda sobre misconfiguração do AWS-S3 aqui: http://flaws.cloud e http://flaws2.cloud/
Finding AWS Buckets
Diferentes métodos para descobrir quando uma página web está usando AWS para armazenar alguns recursos:
Enumeration & OSINT:
- Usando o plugin de navegador wappalyzer
- Usando burp (spidering a web) ou navegando manualmente pela página — todos os resources loaded serão salvos no History.
- Verifique por resources em domínios como:
http://s3.amazonaws.com/[bucket_name]/
http://[bucket_name].s3.amazonaws.com/
- Verifique por CNAMES já que
resources.domain.compode ter o CNAMEbucket.s3.amazonaws.com - s3dns – Um servidor DNS leve que identifica passivamente cloud storage buckets (S3, GCP, Azure) analisando o tráfego DNS. Detecta CNAMEs, segue cadeias de resolução e casa padrões de bucket, oferecendo uma alternativa silenciosa ao brute-force ou à descoberta via API. Perfeito para fluxos de trabalho de recon e OSINT.
- Verifique https://buckets.grayhatwarfare.com, um site com buckets abertos já descobertos.
- O bucket name e o bucket domain name precisam ser os mesmos.
- flaws.cloud está no IP 52.92.181.107 e se você for lá ele redireciona para https://aws.amazon.com/s3/. Além disso,
dig -x 52.92.181.107retornas3-website-us-west-2.amazonaws.com. - Para verificar que é um bucket você também pode visitar https://flaws.cloud.s3.amazonaws.com/.
Brute-Force
Você pode encontrar buckets fazendo brute-force nos nomes relacionados à empresa que você está pentesting:
- https://github.com/sa7mon/S3Scanner
- https://github.com/clario-tech/s3-inspector
- https://github.com/jordanpotti/AWSBucketDump (Contains a list with potential bucket names)
- 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 abertos, BucketLoot pode automaticamente buscar informações interessantes.
Find the Region
Você pode encontrar todas as regiões suportadas pela AWS em https://docs.aws.amazon.com/general/latest/gr/s3.html
By DNS
Você pode obter a região de um bucket com dig e nslookup fazendo uma requisição DNS do IP descoberto:
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.
Verifique se o domínio resolvido contém a palavra "website".
Você pode acessar o site estático indo para: flaws.cloud.s3-website-us-west-2.amazonaws.com
ou você pode acessar o bucket visitando: flaws.cloud.s3-us-west-2.amazonaws.com
Ao Tentar
Se você tentar acessar um bucket, mas no nome de domínio você especificar outra região (por exemplo o bucket está em bucket.s3.amazonaws.com mas você tenta acessar bucket.s3-website-us-west-2.amazonaws.com), então você será indicado para a localização correta:
.png)
Enumerando o bucket
Para testar a abertura do bucket, um usuário pode simplesmente inserir a URL no navegador. Um bucket privado responderá com "Access Denied". Um bucket público listará os primeiros 1.000 objetos que foram armazenados.
Aberto a todos:
.png)
Privado:
.png)
Você também pode verificar isso com o 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]
Se o bucket não tiver um nome de domínio, ao tentar enumerá-lo, coloque apenas o nome do bucket e não todo o domínio AWSs3. Exemplo: s3://<BUCKETNAME>
Modelo de URL pública
https://{user_provided}.s3.amazonaws.com
Obter Account ID de um Bucket público
É possível determinar uma conta AWS aproveitando a nova S3:ResourceAccount Policy Condition Key. Esta condição restringe o acesso com base no S3 bucket em que uma conta está (outras policies baseadas em conta restringem com base na conta em que o principal solicitante está).
E, porque a policy pode conter wildcards, é possível descobrir o número da conta apenas um dígito por vez.
Esta ferramenta automatiza o processo:
# 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 também funciona com API Gateway URLs, Lambda URLs, Data Exchange data sets e até para obter o valor de tags (se você souber a chave da tag). Você pode encontrar mais informações na original research e na ferramenta conditional-love para automatizar essa exploração.
Confirmando que um bucket pertence a uma conta AWS
Como explicado em this blog post, se você tiver permissões para listar um bucket é possível confirmar o accountID ao qual o bucket pertence enviando uma requisição 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>
Se o erro for “Access Denied”, isso significa que o account ID estava errado.
Emails usados para enumeração de contas root
Como explicado em this blog post, é possível verificar se um endereço de email está relacionado a alguma conta AWS ao tentar conceder permissões a um email sobre um bucket S3 via ACLs. Se isso não gerar um erro, significa que o email é um usuário root de alguma conta 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'
}
}
)
References
- https://www.youtube.com/watch?v=8ZXRw4Ry3mQ
- https://cloudar.be/awsblog/finding-the-account-id-of-any-public-s3-bucket/
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
HackTricks Cloud