Arquivos sensíveis expostos (.env, .git, backups): como funciona, como testar e como corrigir
Arquivos como .env, .git/config ou backup.sql esquecidos na raiz do site entregam credenciais e código-fonte a quem pedir a URL certa.
Severidade típica: Crítica · Verificado pelo módulo da NovaPentest: Sensitive File Discovery
O que é
Um arquivo sensível exposto é um arquivo que nunca deveria ser público, mas que o servidor web entrega para qualquer pessoa que peça o caminho dele. Quase sempre é um acidente de deploy, não um bug no código da aplicação.
As causas costumam ser corriqueiras. O site é publicado com git clone direto na pasta pública, e a pasta .git vai junto. O .env com senha do banco e chaves de API fica ao lado do index.php porque o framework lê de lá. Alguém faz um backup rápido antes de uma atualização e esquece backup.zip ou dump.sql na pasta do site. Um phpinfo.php criado para depurar o servidor nunca é apagado. O editor ou o sistema operacional deixa para trás arquivos de metadados como .DS_Store.
O servidor web serve tudo o que está dentro do document root, a menos que seja configurado para não servir. Arquivo que começa com ponto só fica oculto na listagem da sua máquina; para o nginx ou o Apache o ponto não significa nada. E como esses caminhos são conhecidos, ninguém precisa de link para chegar neles: basta pedir direto, e ferramentas automatizadas fazem isso o tempo todo pela internet.
A categoria é ampla. Alguns arquivos são perigosos por si só, como um .env com credenciais válidas ou um dump completo do banco. Outros entregam informação que facilita outros ataques, como páginas de status do servidor, detalhes de configuração do PHP ou descritores de deploy Java. Alguns têm impacto baixo, mas mostram que o processo de deploy copia mais do que deveria.
A correção raramente é complicada, mas tem duas partes igualmente importantes: impedir que o arquivo seja servido e considerar que tudo o que ele continha já vazou.
Como é explorada
O que o atacante ganha depende do arquivo, e os mais comuns são justamente os mais graves.
Uma pasta .git acessível permite baixar os objetos do repositório e reconstruir o código-fonte, muitas vezes com o histórico. Esse histórico costuma guardar segredos que entraram em algum commit e depois foram removidos: os arquivos atuais parecem limpos, mas o commit antigo ainda tem a chave. O código também revela endpoints internos, rotas de admin e falhas de lógica que ficam muito mais fáceis de achar lendo do que testando de fora.
Um .env ou arquivo de configuração normalmente traz credenciais do banco, chaves de nuvem, segredos do gateway de pagamento, senhas de SMTP e chaves de assinatura de sessão ou de tokens. Com isso, o atacante pode nem precisar explorar a aplicação: conecta direto no banco, chama a API do fornecedor em seu nome ou forja tokens de sessão que a aplicação aceita como válidos.
Dumps SQL e arquivos de backup do site são uma cópia dos seus dados, com cadastros de usuários, hashes de senha e dados pessoais, entregues em um único download. Isso já é um incidente de vazamento de dados, com as obrigações de comunicação previstas na LGPD.
Páginas de diagnóstico como o phpinfo expõem caminhos do servidor, módulos carregados, valores de configuração e às vezes variáveis de ambiente. O server-status do Apache pode mostrar em tempo real as URLs que outros visitantes estão acessando, o que pode incluir tokens em query string. Isso é reconhecimento, não comprometimento direto, mas encurta bastante o caminho.
O ponto principal para quem cuida do site é o tempo. Esses caminhos são requisitados por scanners automatizados o tempo todo; se o arquivo ficou acessível por algum período, parta do princípio de que já foi lido. Bloquear depois impede novas leituras, mas não desfaz o vazamento.
Como detectar
O módulo Sensitive File Discovery roda só nos scans completos, não no scanner passivo gratuito. Ele pega esquema, host e porta do alvo, ignora qualquer caminho informado e requisita uma lista fixa de 32 caminhos na raiz do site com redirecionamento desligado, para que um 301 para a home não se passe por arquivo real. Entre eles estão /.git/config, /.git/HEAD, /.svn/entries, /.hg/hgrc, /.env e as variantes .local, .prod, .production e .backup, /wp-config.php.bak, /backup.sql, /dump.sql, /database.sql e /db.sql, todos com severidade Crítica. /config.php, /config.bak, /config.yml, /config.json, /backup.tar.gz, /backup.zip, /phpinfo.php, /info.php, /php-info.php, /web.xml e /WEB-INF/web.xml são Alta. /test.php, /.htaccess, /server-status e /server-info são Média, e /.DS_Store, /crossdomain.xml e /clientaccesspolicy.xml são Baixa.
Um caminho só é apontado se responder HTTP 200 com corpo de pelo menos 10 caracteres, que não pareça uma página genérica de não encontrado e que não bata com a resposta padrão do site, que o módulo identifica antes pedindo um caminho aleatório inexistente. Assim, SPAs que respondem 200 para qualquer rota não geram alarme falso.
Os limites existem. O módulo não analisa o conteúdo do arquivo, então um config.json público e legítimo servido pela aplicação também é reportado. Um arquivo real cujo texto contenha frases como page not found pode ser ignorado. Só a raiz é verificada, não subpastas. Se você informar uma URL http:// que redireciona para https, todos os pedidos recebem redirecionamento e nada é apontado, então use o endereço https. Outros nomes, como .env.dev ou .git/index, não são testados.
Para conferir na mão, rode curl -s -o /dev/null -w "%{http_code}\n" https://exemplo.com.br/.env e repita para cada caminho, inclusive subpastas onde você faz deploy. Um 200 merece ser aberto; no caso do .git, curl -s https://exemplo.com.br/.git/HEAD devolvendo uma linha que começa com ref: confirma a exposição. O esperado é 403 ou 404.
Como corrigir
Siga esta ordem: conter, trocar os segredos e evitar que se repita.
1. Bloqueie o acesso no servidor web imediatamente. No nginx, negue arquivos que começam com ponto sem quebrar os desafios ACME: location ~ /\.(?!well-known) { deny all; return 404; }. Acrescente bloqueios para extensões de backup e dump, por exemplo location ~* \.(sql|bak|zip|tar\.gz)$ { deny all; }. No Apache 2.4, use <FilesMatch "^\."> Require all denied </FilesMatch> e RedirectMatch 404 /\.git na configuração do site.
2. Apague os arquivos da pasta pública. Backup, dump, phpinfo e script de teste não têm motivo para estar no servidor; guarde os backups em um storage que não seja servido pela web.
3. Troque todo segredo que estava no arquivo, mesmo que os logs não mostrem acesso. Mude as senhas do banco, revogue e gere de novo as chaves de API e de nuvem, troque as credenciais do gateway de pagamento e do provedor de e-mail e substitua as chaves de assinatura de sessão ou de token, o que vai deslogar os usuários. Se a pasta .git ficou exposta, revise todo o histórico de commits atrás de segredos, não só os arquivos atuais, e troque esses também.
4. Procure nos logs de acesso pedidos ao caminho exposto para entender o que foi baixado e desde quando. Se um dump ou backup do banco estava acessível, trate como possível incidente de vazamento de dados.
5. Tire os segredos da pasta pública. Aponte o document root para uma subpasta pública (por exemplo public/), deixando a configuração um nível acima, ou injete os segredos como variáveis de ambiente pela plataforma de hospedagem ou por um cofre de segredos em vez de arquivos.
6. Corrija o deploy. Gere um pacote só com o que o site precisa em vez de clonar o repositório no servidor, mantenha o .env no .gitignore e desligue páginas de diagnóstico como o server-status, ou restrinja a endereços internos.
7. Rode o scan de novo depois da mudança e inclua a verificação no seu processo de release.
Verifique o seu próprio site
Comece pelo scan passivo gratuito: não precisa de conta e você recebe uma nota de A a F cobrindo cabeçalhos, TLS, cookies, DNS e outras configurações que qualquer visitante consegue observar. Ele não envia payloads de ataque, então não confirma todas as classes de falha. O scan completo, disponível com uma conta gratuita, executa as verificações ativas, incluindo a descrita nesta página.