
Servidor DNS passivo que detecta buckets de armazenamento em nuvem expostos (AWS S3, GCP, Azure) resolvendo requisições DNS, rastreando cadeias CNAME e sinalizando potenciais sequestros de subdomínio durante o reconhecimento.
# S3DNS **s3dns** é um servidor DNS leve que ajuda a descobrir buckets de armazenamento em nuvem (AWS S3, Google Cloud Storage e Azure Blob) resolvendo consultas DNS, rastreando CNAMEs e combinando padrões conhecidos de URLs de buckets. É uma ferramenta útil para **testadores de penetração**, **caçadores de recompensas** e **analistas de segurança em nuvem** que desejam capturar buckets de nuvem expostos durante a análise de tráfego DNS. Se o S3DNS economizar seu tempo em uma sessão de reconhecimento, considere dar uma ⭐️ — isso ajuda outras pessoas a encontrarem o projeto. --- --- ### 🆕 Atualização 2026/03/06 * **Suporte a TCP/53** — O S3DNS agora escuta nas portas 53 UDP e TCP. Clientes que repetem a consulta via TCP após uma resposta UDP truncada são tratados corretamente, com a consulta encaminhada ao upstream via TCP para obter a resposta completa. * **Buffer DNS maior** — Buffer de recepção UDP aumentado de 512 para 4096 bytes. As opções EDNS0 do cliente são passadas intactas ao resolvedor upstream. * **Cache de respostas** — Cache LRU baseado em TTL para respostas DNS compartilhado entre os caminhos UDP e TCP. Reduz a carga no upstream e a latência durante sessões ativas de reconhecimento. Configurável via `CACHE_SIZE` (padrão: `1000` entradas; defina `0` para desativar). * **Limitação de taxa** — Limite de requisições por IP do cliente para evitar abuso. Configurável via `RATE_LIMIT` (padrão: `100` req/s; defina `0` para desativar). * **Detecção de takeover de subdomínio** — Quando um domínio corresponde a um padrão de armazenamento em nuvem, mas retorna `NXDOMAIN`, o S3DNS o marca como um **possível takeover de domínio**. Isso indica um registro DNS órfão apontando para um bucket não reivindicado que um atacante poderia registrar. * **Verificação de faixas de IP IPv6** — Registros AAAA também são agora resolvidos e verificados em relação a faixas de IP conhecidas de armazenamento em nuvem. Prefixos IPv6 do S3 da AWS são carregados junto com as faixas IPv4. * **Limite de profundidade de CNAME** — O seguimento recursivo de cadeias de CNAME agora tem limite (padrão: 10 saltos) para evitar loops infinitos em registros maliciosos ou cíclicos. Configurável via parâmetro `max_cname_depth`. ### Atualização 2025/08/19 * Adicionadas faixas AWS offline como arquivo JSON. * Adicionadas faixas Azure Storage offline como arquivo JSON. * Adicionada opção de desabilitar a verificação de faixas IP para cada serviço usando: * `AZURE_IP_RANGES=false` ou `AWS_IP_RANGES=false` (padrão é true). * Movidos `regex_patterns` e padrões fixos para a pasta `patterns` como arquivos YAML. Você pode adicionar seus próprios padrões. * **Padrões regex devem começar com `regex_`.** * Adicionados vários provedores de nuvem adicionais * IBM Cloud Object Storage * Oracle Object Storage * Alibaba OSS * Backblaze B2 * Linode Object Storage * Scaleway Object Storage * Vultr Object Storage * Cloudflare R2 ### Atualização 2025/06/21 * Adicionado suporte a AWS GovCloud. ### Atualização 2025/04/16 * Padrões regex atualizados. * Saída atualizada para melhor visibilidade (exibindo o domínio original para CNAMEs, o IP do cliente e indicadores de faixa IP). * Download automático de faixas IP da AWS — agora também verificando essas! * Opção de adicionar suas próprias faixas IP (ajuste manual dos padrões ou faixas IP na classe). ### Atualização 2025/04/14 * Adicionado suporte a regex para buckets do **Google Cloud Storage** e **Azure Blob Storage**. --- ## 🚀 Funcionalidades * Funciona como servidor DNS na porta `53` (UDP **e** TCP) * Detecta potenciais buckets de armazenamento em nuvem em consultas DNS: * **AWS S3** (virtual-host e path style, incluindo GovCloud) * **Buckets GCP** * **Containers Azure Blob** * **DigitalOcean Spaces**, **Wasabi**, **IBM COS**, **Oracle Object Storage**, **Alibaba OSS**, **Backblaze B2**, **Linode**, **Scaleway**, **Vultr**, **Cloudflare R2** * Segue **cadeias de CNAME** recursivamente (limite de profundidade configurável) para capturar links de bucket mascarados * Sinaliza **potenciais takeovers de subdomínio** — padrões de armazenamento em nuvem que retornam NXDOMAIN * Verifica IPs resolvidos (A e AAAA) em relação a faixas IP conhecidas de **AWS S3 e Azure Storage** * **Cache de respostas sensível a TTL** para reduzir latência e carga no upstream durante reconhecimento * **Limitação de taxa por IP** para evitar abuso * Registra todos os achados no console e em arquivo * Amigável para contêineres --- ## ⚙️ Como Funciona O S3DNS escuta na **porta 53 (UDP e TCP)** por consultas DNS. Para cada requisição ele: 1. **Extrai o domínio requisitado** 2. **Verifica o cache de respostas** — se uma resposta válida em cache existir, ela é retornada imediatamente 3. **Encaminha a requisição para um resolvedor DNS real** (ex.: `1.1.1.1`) — via UDP para clientes UDP, via TCP para clientes TCP 4. **Retorna a resposta DNS válida para o cliente** Em paralelo, ele: * **Verifica padrões de bucket de armazenamento em nuvem** (regex e correspondência de hostname fixo) * **Verifica IPs resolvidos em relação a faixas conhecidas de AWS S3 e Azure Storage** (IPv4 e IPv6) * **Segue cadeias de CNAME** recursivamente até a profundidade configurada * **Sinaliza acertos NXDOMAIN** em padrões correspondentes como possíveis candidatos a takeover de subdomínio * **Registra todos os achados** no console e em `s3dns.log` ⚡ Use isto como seu DNS durante o reconhecimento, e ele irá expor passivamente buckets na nuvem e candidatos a takeover para cada domínio que suas ferramentas ou navegador resolverem. --- ## 🧱 Pré-requisitos Você precisará apenas de um dos seguintes: * Python **3.11+** * Docker (opcional, mas recomendado) --- ## 🔧 Instalação *Necessário apenas se quiser executar localmente com Python* ### Clone o Repositório ```bash git clone https://github.com/olizimmermann/s3dns.git cd s3dns ``` ### Instale as Dependências (Recomenda-se o uso de ambiente virtual) ```bash python3 -m venv venv source venv/bin/activate pip install -r requirements.txt ``` --- ## 🧪 Uso ### Execute com Python A porta 53 requer privilégios elevados: ```bash sudo python s3dns.py ``` *Se `sudo` reclamar de um módulo faltando, tente: `sudo venv/bin/python s3dns.py`* * Se você construir a imagem manualmente, certifique-se de marcá-la com a mesma tag da versão do Docker Hub para consistência: `docker build -t ozimmermann/s3dns:latest .` ### Use Docker *A maneira mais fácil de começar com o S3DNS.* ```bash docker pull ozimmermann/s3dns:latest docker run --rm -p 53:53/udp -p 53:53/tcp \ -v "./bucket_findings/:/app/buckets/" \ --name "s3dns" \ ozimmermann/s3dns:latest ``` ### Construa e Execute com Docker ```bash docker build -t ozimmermann/s3dns:latest . ``` ```bash docker run --rm -p 53:53/udp -p 53:53/tcp \ -v "./bucket_findings/:/app/buckets/" \ --name "s3dns" \ ozimmermann/s3dns:latest ``` Os achados são salvos: * No **terminal**, e/ou * Em `./bucket_findings/` ### Solução de Problemas Ao usar o S3DNS na mesma máquina onde realiza a análise, pode ser útil definir a flag `--network host`: ```bash docker run --rm -p 53:53/udp -p 53:53/tcp \ -v "./bucket_findings/:/app/buckets/" \ --network host \ --name "s3dns" \ ozimmermann/s3dns:latest ``` Como a porta 53 requer privilégios elevados, alguns usuários (ex.: usuários Mac) podem precisar de `sudo`: ```bash sudo docker run --rm -p 53:53/udp -p 53:53/tcp \ -v "./bucket_findings/:/app/buckets/" \ --name "s3dns" \ ozimmermann/s3dns:latest ``` --- ## 🌐 Usando o S3DNS em Reconhecimento Configure o **resolvedor DNS** do seu sistema ou ferramenta para sua instância do S3DNS. > Enquanto navega ou faz fuzzing no seu alvo, o S3DNS analisa cada domínio e informa se ele resolve para: > > * Um **bucket AWS S3** > * Um **bucket GCP** > * Um **container Azure Blob** > * Qualquer um dos outros 13 provedores de armazenamento em nuvem suportados > > Ele **segue CNAMEs**, então se um domínio aponta para `cdn.example.com`, que por sua vez aponta para um bucket na nuvem, ele também capturará isso. > > Também **sinaliza potenciais takeovers de subdomínio** — se um domínio corresponde a um padrão de armazenamento em nuvem, mas o alvo não existe (NXDOMAIN), o registro órfão é destacado como um possível candidato a takeover. Use-o passivamente enquanto analisa um site para **detectar buckets expostos e oportunidades de takeover sem sondagem ativa**. --- ## ⚙️ Configuração Você pode ajustar o comportamento via flags de linha de comando, variáveis de ambiente ou modificando `s3dns.py`. A precedência para cada opção é: **flag de linha de comando > variável de ambiente > prompt interativo / padrão.** Executar sem flags se comporta exatamente como antes. ### Flags de Linha de Comando Execute `python s3dns.py -h` para a lista completa: | Flag | Variável de ambiente equivalente | Descrição | |---|---|---| | `-h`, `--help` | – | Mostra ajuda e sai | | `--version` | – | Mostra versão e sai | | `-d`, `--debug` | `DEBUG` | Habilita saída detalhada de depuração | | `-l`, `--listen IP` | `LOCAL_DNS_SERVER_IP` | Interface local para escutar | | `-u`, `--upstream IP` | `REAL_DNS_SERVER_IP` | Resolvedor DNS upstream para encaminhar | | `-b`, `--bucket-file CAMINHO` | `BUCKET_FILE` | Caminho para escrever domínios de bucket descobertos | | `--aws-ip-ranges` / `--no-aws-ip-ranges` | `AWS_IP_RANGES` | Ativa/desativa verificação de faixas IP do AWS S3 | | `--azure-ip-ranges` / `--no-azure-ip-ranges` | `AZURE_IP_RANGES` | Ativa/desativa verificação de faixas IP do Azure Storage | | `--rate-limit N` | `RATE_LIMIT` | Máx. de requisições DNS/s por IP do cliente (`0` = desativado) | | `--cache-size N` | `CACHE_SIZE` | Máx. de respostas DNS em cache (`0` = desativado) | | `--max-cname-depth N` | – | Profundidade máxima da cadeia de CNAME a seguir (padrão: 10) | Exemplo: ```bash sudo python s3dns.py -l 0.0.0.0 -u 1.1.1.1 --rate-limit 200 --no-azure-ip-ranges ``` ### Variáveis de Ambiente | Variável | Padrão | Descrição | |---|---|---| | `DEBUG` | `false` | Habilita saída detalhada de depuração | | `AWS_IP_RANGES` | `true` | Ativa verificação de faixas IP do AWS S3 | | `AZURE_IP_RANGES` | `true` | Ativa verificação de faixas IP do Azure Storage | | `REAL_DNS_SERVER_IP` | `1.1.1.1` | Resolvedor DNS upstream para encaminhar consultas | | `LOCAL_DNS_SERVER_IP` | `0.0.0.0` | Interface local para escutar | | `BUCKET_FILE` | `buckets.txt` | Caminho para escrever domínios de bucket descobertos | | `RATE_LIMIT` | `100` | Máx. de requisições DNS por segundo por IP do cliente (`0` = desativado) | | `CACHE_SIZE` | `1000` | Máx. de respostas DNS em cache (`0` = desativado) | #### ⚠️ Nota sobre Faixas IP do Azure Como a Microsoft não nomeia explicitamente suas faixas IP de Azure Blob Storage, o S3DNS usa **todos os endereços IP do Azure Storage fornecidos publicamente**. Isso pode levar a falsos positivos. Considere desabilitar essa verificação se encontrar problemas: ```bash AZURE_IP_RANGES=false ``` ### Adicionando Padrões Customizados Adicione arquivos YAML no diretório `patterns/`. Arquivos prefixados com `regex_` são tratados como padrões regex; todos os outros são tratados como correspondências de substring. --- ### Modo de Depuração **Python:** ```bash sudo su export DEBUG=true python s3dns.py ``` **Docker:** ```bash docker run --rm -p 53:53/udp -p 53:53/tcp \ -v "./bucket_findings/:/app/buckets/" \ -e "DEBUG=true" \ --name "s3dns" \ ozimmermann/s3dns:latest ``` Definindo múltiplas variáveis de ambiente no Docker: ```bash docker run --rm -p 53:53/udp -p 53:53/tcp \ -v "./bucket_findings/:/app/buckets/" \ -e "LOCAL_DNS_SERVER_IP=0.0.0.0" \ -e "REAL_DNS_SERVER_IP=1.1.1.1" \ -e "RATE_LIMIT=200" \ -e "CACHE_SIZE=2000" \ --name "s3dns" \ ozimmermann/s3dns:latest ``` --- ## Exemplo de Saída  --- ## Contribuindo Contribuições são bem-vindas — novos padrões de provedores de nuvem, correções de bugs e melhorias. Veja [CONTRIBUTING.md](https://github.com/olizimmermann/s3dns/blob/main/CONTRIBUTING.md) para diretrizes. Os arquivos de padrão ficam em `patterns/`. Adicionar suporte a um novo provedor é tão simples quanto adicionar uma entrada YAML — não é necessário Python. --- ## 📄 Licença Licença MIT — Gratuito para usar, melhorar e compartilhar. --- ## ⚠️ Aviso Legal Use com responsabilidade. Apenas escaneie domínios que você **possui** ou para os quais tenha **permissão explícita** de análise. Acesso não autorizado ou sondagem pode ser ilegal.