Pentest Black-Box: Como um Painel de Controle Revelou 30 Subdomínios e Zabbix Exposto
Introdução: Todos os nomes de empresas, nomes de desenvolvedores e endereços IP reais foram alterados. Detalhes técnicos e vetores de ataque são reais.
Recentemente, recebi a tarefa de realizar um pentest externo black-box em um painel de controle de cliente. As informações de entrada eram mínimas: apenas o URL. Nenhum intervalo de IP, nenhum esquema de rede, nenhuma descrição da arquitetura.
Parece uma história típica, mas no processo, deparei-me com tantos obstáculos que decidi compartilhar a metodologia. O artigo será útil tanto para pentester iniciantes quanto para administradores que desejam entender como sua infraestrutura é vista pela internet.
Etapa 1: Reconhecimento
Coleta Passiva
Comecei com o básico: verifiquei o que respondia às requisições.
bashcurl -skI https://target-panel.example.ru
O servidor respondeu:
HTTP/2 200
Server: nginx
Via: 1.1 Caddy
Set-Cookie: XSRF-TOKEN=...
Set-Cookie: panel_session=...
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Já é interessante. Vemos que por trás do servidor web está o Caddy como reverse proxy, e o upstream em si é o nginx. Cookies como XSRF-TOKEN e o nome panel_session sugerem Laravel.
Em seguida, a detecção de WAF:
bashwafw00f https://target-panel.example.ru
Resultado: WAF não detectado. Este é um bom sinal para o teste.
Escaneamento Ativo de Portas
bashnmap -p- --min-rate=5000 -T4 -Pn -sS target-panel.example.ru
O resultado me surpreendeu:
PORT STATE SERVICE
80/tcp open http
443/tcp open https
65533 ports filtered
De 65535 portas, apenas duas estão abertas. Este é um excelente indicador – o firewall está configurado corretamente. A maioria das aplicações API modernas funciona assim: 80 → redirecionamento para 443, 443 → aplicação.
Verifiquei também o UDP – todas as portas estão filtradas. A rede está protegida.
SSL/TLS
Uma análise rápida do TLS mostrou que tudo está bem com isso:
- TLS 1.2: ECDHE-ECDSA-AES128-GCM-SHA256 (Classe A)
- TLS 1.2: ECDHE-ECDSA-AES256-GCM-SHA384 (Classe A)
- TLS 1.3: TLS_AKE_WITH_AES_128_GCM_SHA256 (Classe A)
- TLS 1.3: TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (Classe A)
Certificado Let's Encrypt em chave EC P-256, Heartbleed/POODLE/CCS Injection — tudo limpo. Ótimo, vamos em frente.
Etapa 2: Análise da Aplicação Web
Detecção de Tecnologias
Redirecionei o navegador para a página /login — encontrei um formulário de autenticação com o título "Login - Client Panel".
Analisei o código-fonte da página. Imediatamente chama a atenção:
html<meta name="csrf-token" content="..."> <script src="https://cdn.tailwindcss.com"></script> <script defer src="/js/alpine.min.js"></script> <link rel="manifest" href="/manifest.json">
E na parte inferior da página — registro PWA:
javascriptnavigator.serviceWorker.register("/sw.js");
E um script de serviço alpine:init com uma função para enviar requisições AJAX:
javascriptasync sendRequestWithHandleResponse({ url, method = 'GET', body = null, headers = {} }) { const assignedHeaders = { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content, 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest', ...headers }; ... }
O stack tecnológico nesta etapa:
| Componente | Tecnologia |
|---|---|
| Backend | Laravel (PHP) |
| Proteção API | Laravel Sanctum |
| Frontend | Tailwind CSS + Alpine.js |
| Servidor Web | nginx + Caddy |
| PWA | Service Worker + Manifest |
Formulário de Login
O próprio formulário continha quatro campos:
| Campo | Tipo | Placeholder |
|---|---|---|
| Account | text | account-name |
| you@example.com | ||
| Password | password | •••••••• |
| Remember me | checkbox | - |
Pareceu-me incomum que fosse necessário tanto o account quanto o email. Possivelmente, account é o identificador do cliente no sistema de billing, e email é o e-mail associado.
Etapa 3: Descoberta de Vulnerabilidades
3.1. Modo de Debug em Produção
A descoberta mais impactante. Verifiquei o que aconteceria se eu enviasse um método HTTP não suportado para um endpoint da API:
bashcurl -sk -X POST -H "Accept: application/json" https://target-panel.example.ru/api/user
E recebi um stack trace completo:
json{ "message": "The POST method is not supported for route api/user. Supported methods: GET, HEAD.", "exception": "Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException", "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php", "line": 131, "trace": [ { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php", "line": 116, "function": "methodNotAllowed" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php", "line": 56, "function": "getAllowedMethods" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", "line": 802, "function": "methodNotAllowed" } ] }
Imediatamente vazaram:
- o caminho completo no servidor:
/var/www/html/ - versões do framework (caminhos do vendor)
- estrutura interna de roteamento
- três quadros completos de stack trace.
Este é um clássico APP_DEBUG=true. Parece que centenas de artigos foram escritos sobre isso, mas a situação persiste. Atribuo CVSS 6.5 — assumindo que o debug não vaza APP_KEY e DB-credentials (neste caso, apenas caminhos e arquitetura vazaram). Se o APP_KEY vazar, através de deserialization é possível obter RCE, e então a pontuação sobe para 7.5–9.0.
3.2. Cookie XSRF-TOKEN sem HttpOnly
Analisei mais de perto os cabeçalhos Set-Cookie:
Set-Cookie: XSRF-TOKEN=eyJpdiI6...; expires=...; Max-Age=7200; path=/; secure; samesite=lax
Set-Cookie: panel_session=eyJpdiI6...; expires=...; Max-Age=7200; path=/; secure; httponly; samesite=lax
Você vê a diferença?
O cookie de sessão (panel_session) tem httponly, o XSRF-TOKEN não.
O site também não possui CSP — qualquer script inline ou de CDN é executado sem restrições. A combinação de um token não-HttpOnly e a ausência de CSP simplifica seriamente o ataque: encontre um XSS — e o token é seu. Atribuo CVSS 6.1.
3.3. CORS Aberto
Verifiquei os cabeçalhos CORS:
bashcurl -sk -H "Origin: https://evil.ru" -H "Access-Control-Request-Method: GET" -X OPTIONS https://target-panel.example.ru/sanctum/csrf-cookie
Resposta:
access-control-allow-origin: *
CORS wildcard nos endpoints de autenticação. Sim, considerando que Access-Control-Allow-Credentials não está definido, roubar a sessão através do navegador não será possível. Mas a própria presença do * permite que qualquer site faça requisições pré-flight e colete informações sobre a API. CVSS 5.0.
3.4. Ausência de HSTS
Apesar do redirecionamento correto da porta 80 (308 Permanent Redirect), o cabeçalho Strict-Transport-Security não estava presente. Na primeira carga via HTTP, o usuário é teoricamente vulnerável a SSL-stripping. CVSS 5.9.
3.5. Admin Panel e API
Notei mais alguns endpoints no caminho:
/admin→ 401 (Unauthorized) — painel de administrador/api/login→ GET/HEAD permitidos, POST — 405/api/user→ protegido por middleware/sanctum/csrf-cookie→ 204 (Sanctum CSRF)
O fato de /admin retornar 401 em JSON, e não um redirecionamento para a página de login, sugere que esta é uma arquitetura semelhante a SPA: Angular/React/Vue no frontend, API no backend.
Etapa 4: Subdomínios — Uma Mina de Ouro
O mais interessante começou quando passei para os subdomínios. Usei três fontes:
- Logs de Transparência de Certificados (crt.sh)
- Enumeração Passiva (Subfinder)
- Requisições DNS
O resultado superou as expectativas — mais de 30 subdomínios:
target-panel.example.ru← painel do cliente (nosso alvo)dev1-panel.example.ru← outro ambiente de desenvolvimentodev2-panel.example.ru← e mais umapi.example.ru← APIgpt-api.control-panel.example.ru← API GPT (!)passport.example.ru← autenticaçãobilling.example.ru← billingadmin.billing.example.ru← admin do billingzabbix.control-panel.example.ru← ZABBIXnc.control-panel.example.ru← Nextcloudjitsi.example.ru← Jitsi Meetexchange.control-panel.example.ru← MS Exchangemail.example.ru← e-mailb24.example.ru← Bitrix24?ai.example.ru← serviço com AI
O que está acessível disso?
Verifiquei rapidamente quais deles respondiam:
zabbix.control-panel.example.ru— 200 OK «Zabbix docker: Zabbix» ← aberto!jitsi.example.ru— 200 OK «Jitsi Meet» ← aberto!nc.control-panel.example.ru— 200 OK «Login – Nextcloud» ← página de loginexchange.control-panel.example.ru— 502 ← caiu com erroname-panel.example.ru— 302 ← outro ambiente de desenvolvimentoapi.example.ru— timeout ← não responde
Zabbix acessível publicamente sem restrição de IP é, talvez, a segunda descoberta mais crítica após APP_DEBUG. Zabbix é um alvo cobiçado: através dele é possível saber versões de SO, nomes de hosts, métricas de desempenho e, em versões antigas, obter RCE.
Jitsi Meet também está totalmente aberto — qualquer pessoa pode criar uma sala e se comunicar usando a infraestrutura da empresa.
Etapa 5: Resultados Intermediários
Matriz de Vulnerabilidades Encontradas
| # | Vulnerabilidade | CVSS | Prioridade |
|---|---|---|---|
| 1 | Laravel APP_DEBUG=true (stack trace exposto) | 6.5 | Alta |
| 2 | Zabbix publicamente acessível | 7.5 | Alta |
| 3 | CORS Wildcard Origin | 5.0 | Média |
| 4 | Cookie XSRF-TOKEN sem HttpOnly (combinação com ausência de CSP) | 6.1 | Média |
| 5 | Ausência de HSTS | 5.9 | Média |
| 6 | Cabeçalho Server (nginx) | — | Info |
| 7 | Jitsi, Nextcloud expostos | 5.0 | Média |
Por que isso aconteceu?
Pelos nomes dos subdomínios (dev1, dev2, nomes de desenvolvedores), o servidor alvo é um ambiente de desenvolvimento ou staging não destinado ao acesso público. Mas ele estava na internet aberta, e os logs de Certificate Transparency indexaram corretamente cada subdomínio.
Esta é uma situação clássica: a equipe de DevOps configurou um ambiente, esqueceu de protegê-lo com VPN ou basic auth, e ele ficou acessível publicamente.
Etapa 6: O que fazer se encontrar algo assim em sua infraestrutura
Compilei uma lista de recomendações em ordem de prioridade.
Crítico
- APP_DEBUG → false — verifique o
.envem todos os servidores. Laravel, Django, Rails — não importa. O modo de depuração em produção é inaceitável. - Proteger Zabbix e painéis de administração — via VPN, lista branca de IPs ou, no mínimo, basic auth.
- CORS —
*é aceitável apenas para APIs públicas. Para todo o resto — uma lista explícita de origins. - HttpOnly em todos os cookies — especialmente em tokens.
- HSTS e CSP — sem eles, um site moderno é como uma porta sem fechadura.
Planejado
- Auditoria de subdomínios — logs CT mostrarão tudo o que você esqueceu de proteger.
- Ativar WAF, se o provedor oferecer.
- Remover ambientes de desenvolvimento não utilizados — cada subdomínio aumenta a superfície de ataque.
Conclusão
Esta história é sobre como um pequeno erro (debug não desativado) e um serviço esquecido (Zabbix exposto) podem revelar mais sobre uma empresa do que ela gostaria. Cada subdomínio fixado ao DNS público é uma porta. Não se esqueça de fechá-las.
Esta história é uma ilustração vívida de por que o perímetro externo deve ser verificado pelas mãos de um atacante. Debug não desativado, ambiente de desenvolvimento esquecido, Zabbix exposto — cada uma dessas pequenas coisas pode parecer inofensiva isoladamente, mas juntas pintam um mapa detalhado da sua infraestrutura para um olhar externo. Encontrar essas portas antes que alguém as encontre é exatamente para o que serve um pentest.
A Cloud4Y oferece testes de penetração (pentest) — uma verificação abrangente de segurança através da simulação de ações de um invasor. Não entregamos apenas uma lista de CVEs: procuramos pontos fracos, confirmamos cada vulnerabilidade com exploração e formamos um relatório compreensível com cenários de ataque, avaliação de riscos de negócios e recomendações passo a passo. Testamos aplicações web e APIs com a metodologia OWASP, infraestrutura — com o padrão PTES, em formatos black-box ou gray-box. Todo o trabalho é estritamente sob contrato e com permissão por escrito, os resultados são confidenciais (NDA).
E para novos clientes do Habr — um desconto de 20% com o código promocional HABR20 nos serviços Cloud4Y, detalhes na página da promoção.
Todos os dados foram anonimizados. Detalhes técnicos dos ataques correspondem aos reais.
As informações fornecidas sobre métodos de pentest destinam-se a aprimorar as qualificações de especialistas em segurança e não podem servir como guia para ações ilegais. A distribuição ou uso desses dados para fins maliciosos viola a legislação da Federação Russa e é punível por lei.






