AWS - S3 Unauthenticated Enum

Support HackTricks

S3 Public Buckets

Um bucket é considerado “público” se qualquer usuário pode listar o conteúdo do bucket, e “privado” se o conteúdo do bucket pode ser listado ou escrito apenas por certos usuários.

As empresas podem ter permissões de buckets mal configuradas, dando acesso a tudo ou a todos autenticados na AWS em qualquer conta (ou seja, a qualquer pessoa). Note que, mesmo com tais configurações incorretas, algumas ações podem não ser possíveis, pois os buckets podem ter suas próprias listas de controle de acesso (ACLs).

Saiba mais sobre a configuração incorreta do AWS-S3 aqui: http://flaws.cloud e http://flaws2.cloud/

Encontrando Buckets AWS

Diferentes métodos para encontrar quando uma página está usando AWS para armazenar alguns recursos:

Enumeração & OSINT:

  • Usando o plugin de navegador wappalyzer

  • Usando burp (spidering a web) ou navegando manualmente pela página, todos os recursos carregados serão salvos no Histórico.

  • Verifique recursos em domínios como:

http://s3.amazonaws.com/[bucket_name]/
http://[bucket_name].s3.amazonaws.com/
  • Verifique CNAMES como resources.domain.com pode ter o CNAME bucket.s3.amazonaws.com

  • Verifique https://buckets.grayhatwarfare.com, um site com buckets abertos já descobertos.

  • O nome do bucket e o nome do domínio do bucket precisam ser os mesmos.

  • flaws.cloud está no IP 52.92.181.107 e se você for lá, será redirecionado para https://aws.amazon.com/s3/. Além disso, dig -x 52.92.181.107 retorna s3-website-us-west-2.amazonaws.com.

  • Para verificar se é um bucket, você também pode visitar https://flaws.cloud.s3.amazonaws.com/.

Força Bruta

Você pode encontrar buckets por força bruta de nomes relacionados à empresa que você está pentestando:

# Gerar uma wordlist para criar permutações
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

# Gerar uma wordlist baseada nos domínios e subdomínios para testar
## Escreva esses domínios e subdomínios em 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

# Criar permutações baseadas em uma lista com os domínios e subdomínios para atacar
goaltdns -l /tmp/words-hosts-s3.txt -w /tmp/words-s3.txt -o /tmp/final-words-s3.txt.temp
## A ferramenta anterior é especializada em criar permutações para subdomínios, vamos filtrar essa lista
### Remover linhas terminadas com "."
cat /tmp/final-words-s3.txt.temp | grep -Ev "\.$" > /tmp/final-words-s3.txt.temp2
### Criar lista sem TLD
cat /tmp/final-words-s3.txt.temp2 | sed -E 's/\.[a-zA-Z0-9]+$//' > /tmp/final-words-s3.txt.temp3
### Criar lista sem pontos
cat /tmp/final-words-s3.txt.temp3 | tr -d "." > /tmp/final-words-s3.txt.temp4http://phantom.s3.amazonaws.com/
### Criar lista sem hífens
cat /tmp/final-words-s3.txt.temp3 | tr "." "-" > /tmp/final-words-s3.txt.temp5

## Gerar a wordlist final
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

## Chamar s3scanner
s3scanner --threads 100 scan --buckets-file /tmp/final-words-s3.txt  | grep bucket_exists

Saquear Buckets S3

Dado buckets S3 abertos, BucketLoot pode automaticamente procurar por informações interessantes.

Encontrar a Região

Você pode encontrar todas as regiões suportadas pela AWS em https://docs.aws.amazon.com/general/latest/gr/s3.html

Por DNS

Você pode obter a região de um bucket com um dig e nslookup fazendo uma solicitaçã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

Tentando

Se você tentar acessar um bucket, mas no nome do 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:

Enumerando o bucket

Para testar a abertura do bucket, um usuário pode simplesmente inserir a URL em seu navegador web. Um bucket privado responderá com "Access Denied". Um bucket público listará os primeiros 1.000 objetos que foram armazenados.

Aberto para todos:

Privado:

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

Get Account ID from public Bucket

É possível determinar uma conta AWS aproveitando a nova S3:ResourceAccount Policy Condition Key. Esta condição restringe o acesso com base no bucket S3 em que uma conta está (outras políticas baseadas em conta restringem com base na conta em que o principal solicitante está). E porque a política pode conter wildcards, é possível encontrar o número da conta apenas um número de cada 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 URLs do API Gateway, URLs do Lambda, conjuntos de dados do Data Exchange e até para obter o valor de tags (se você souber a chave da tag). Você pode encontrar mais informações na pesquisa original e na ferramenta conditional-love para automatizar essa exploração.

Confirmando que um bucket pertence a uma conta AWS

Como explicado neste post do blog, se você tiver permissões para listar um bucket é possível confirmar um accountID ao qual o bucket pertence enviando uma solicitaçã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 ID da conta estava errado.

Usando Emails como enumeração de conta root

Como explicado neste post do blog, é possível verificar se um endereço de email está relacionado a alguma conta AWS tentando 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'
}
}
)

Referências

Suporte HackTricks

Last updated