Introdução à Metodologia de Pentest
Penetration Testing, ou Pentest, é o processo de avaliação de segurança onde um profissional autorizado simula ataques contra um sistema, aplicação ou infraestrutura para identificar vulnerabilidades antes que atacantes maliciosos o façam. Diferente de testes de segurança passivos, o Pentest é agressivo e intencional, buscando explorar falhas reais que poderiam ser exploradas por agentes maliciosos. A metodologia estruturada garante que o teste seja completo, documentado e alinhado com os objetivos do cliente.
Uma das razões pelas quais a metodologia é crucial é simples: testes desordenados geram resultados incompletos, expõem riscos desnecessários e frequentemente violam a lei. Ao seguir um framework estabelecido — como OWASP, PTES (Penetration Testing Execution Standard) ou NIST — você garante que cada fase seja executada de forma controlada, rastreável e com valor real para a organização testada.
Fases da Metodologia de Pentest
Fase 1: Reconhecimento e Coleta de Informações
O reconhecimento é a fundação de qualquer Pentest bem-sucedido. Nesta fase, você coleta informações sobre o alvo sem tentar explorar nada — apenas mapeia o que está lá. Isso inclui identificar domínios, servidores, funcionários, tecnologias usadas e potenciais pontos de entrada. Existem duas abordagens: Passive Reconnaissance (sem contato direto) e Active Reconnaissance (com tráfego direto ao alvo).
Durante a fase passiva, ferramentas como WHOIS, DNS recon e busca em mecanismos de busca revelam informações públicas. Na fase ativa, ferramentas como Nmap começam a sondar a infraestrutura. Um exemplo prático usando Python com a biblioteca socket:
import socket
def reconhecer_hosts(dominio):
"""Coleta informações básicas de DNS e resolução IP"""
try:
# Resolve o domínio para IP
ip = socket.gethostbyname(dominio)
print(f"Domínio: {dominio}")
print(f"IP Resolvido: {ip}")
# Tenta fazer reverse DNS
hostname, aliaslist, ipaddrlist = socket.gethostbyaddr(ip)
print(f"Hostname Reverso: {hostname}")
print(f"IPs Associados: {ipaddrlist}")
except socket.gaierror as e:
print(f"Erro na resolução: {e}")
except socket.herror as e:
print(f"Erro no reverse DNS: {e}")
# Uso
reconhecer_hosts("google.com")
Este código simples executa o reconhecimento passivo. Na prática, você complementaria com Nmap para escanear portas abertas (nmap -sV target.com), ferramentas OSINT para e-mails e funcionários, e análise de tecnologias web.
Fase 2: Varredura (Scanning) e Enumeração
Após mapear o perímetro, você executa varreduras ativas para identificar serviços rodando, versões de software e portas abertas. Esta fase é onde você começa a produzir "barulho" detectável — por isso é crítica a validação prévia das regras de engajamento. A enumeração vai além de simplesmente abrir conexões: você interage com serviços para extrair banners, versões e configurações.
Usando Python com a biblioteca nmap (pyNmap), você pode automatizar varreduras de forma controlada:
import nmap
def escanear_portas(host, argumentos='-sV -sC -p-'):
"""
Escaneia um host usando Nmap.
-sV: Detecção de versão
-sC: Scripts padrão
-p-: Todas as portas
"""
nm = nmap.PortScanner()
print(f"Iniciando scan em {host}...")
nm.scan(host, arguments=argumentos)
# Analisa resultados
for host_encontrado in nm.all_hosts():
print(f"\nHost: {host_encontrado}")
print(f"Status: {nm[host_encontrado].state()}")
for proto in nm[host_encontrado].all_protocols():
print(f"Protocolo: {proto}")
puertos = nm[host_encontrado][proto].keys()
for port in puertos:
state = nm[host_encontrado][proto][port]['state']
name = nm[host_encontrado][proto][port].get('name', 'unknown')
version = nm[host_encontrado][proto][port].get('version', 'unknown')
print(f" Porta {port}: {state} | Serviço: {name} | Versão: {version}")
# Uso (requer Nmap instalado)
# escanear_portas("192.168.1.1")
Durante essa fase você também mapeia serviços como SMB, HTTP, SSH, etc., buscando banners que revelam versões vulneráveis. O objetivo é criar uma lista completa de alvos potenciais para a próxima fase.
Fase 3: Análise de Vulnerabilidades
Com a superfície de ataque mapeada, você agora busca identificar vulnerabilidades específicas. Isso inclui pesquisar CVEs (Common Vulnerabilities and Exposures) para versões identificadas, testar configurações inseguras e procurar por fraquezas lógicas. Ferramentas como OpenVAS, Qualys e Nessus automatizam esse processo, mas entender manualmente o que procurar é crucial.
Um exemplo de como verificar uma vulnerabilidade conhecida — como o CVE-2021-3129 em Laravel (Remote Code Execution via debug mode):
import requests
import json
def verificar_laravel_debug(url):
"""
Verifica se uma aplicação Laravel está com debug mode ativo.
Isso é uma vulnerabilidade crítica (RCE).
"""
# Tenta acessar o arquivo config em cache (informação sensível)
response = requests.get(f"{url}/_debugbar/cache", verify=False)
if response.status_code == 200:
print("[!] VULNERABILIDADE ENCONTRADA: Debug mode ativo!")
print(f"Response: {response.text[:200]}")
return True
# Tenta outro endpoint que vaza informações com debug ativo
response = requests.get(f"{url}/telescope", verify=False)
if response.status_code == 200:
print("[!] VULNERABILIDADE: Laravel Telescope exposto!")
return True
print("[+] Debug mode não detectado (ou está protegido)")
return False
# Uso
# verificar_laravel_debug("http://target.local")
Nesta fase, você documenta cada vulnerabilidade encontrada com seu nível de severidade, impacto potencial e possível remediação. A severidade deve ser classificada usando o CVSS (Common Vulnerability Scoring System).
Fase 4: Exploração
A exploração é onde você demonstra o impacto real das vulnerabilidades. Não é apenas "encontrar" uma falha — é provar que ela pode ser explorada para ganhar acesso, extrair dados ou causar dano. Esta é a fase mais sensível e requer os maiores cuidados com as regras de engajamento. Você só explora vulnerabilidades que foram explicitamente aprovadas pelo cliente.
Um exemplo prático de exploração de uma SQL Injection simples em uma aplicação web:
import requests
from urllib.parse import quote
def testar_sql_injection(url, parametro, payload_base="' OR '1'='1"):
"""
Testa SQL Injection básica em um parâmetro.
Exemplo: http://target.com/search.php?q=AQUI
"""
# Constrói a URL com o payload
payload = f"{payload_base}"
params = {parametro: payload}
try:
response = requests.get(url, params=params, timeout=5)
# Indicadores de sucesso (muito básico, real seria mais sofisticado)
if "unexpected token" in response.text.lower() or len(response.text) > 50000:
print(f"[!] Possível SQL Injection detectada!")
print(f"Payload: {payload}")
print(f"Response preview: {response.text[:300]}")
return True
else:
print("[+] Nenhuma indicação de SQL Injection")
return False
except requests.RequestException as e:
print(f"Erro na requisição: {e}")
return False
# Uso
# testar_sql_injection("http://target.local/search.php", "q")
A exploração deve ser cuidadosa: mude dados de teste sem afetar dados reais, mantenha logs de tudo que fez, e recue imediatamente se começar a causar impacto não autorizado.
Fase 5: Pós-Exploração e Análise
Após explorar com sucesso uma vulnerabilidade, você entra na fase de pós-exploração, onde busca aprofundar o acesso, escalbar privilégios, mover-se lateralmente pela rede ou extrair dados sensíveis. O objetivo é demonstrar o impacto completo de uma cadeia de exploração realista.
Nesta fase você também documenta:
- Comandos executados
- Dados acessados
- Mudanças feitas (se houver)
- Evidências de comprometimento
Um exemplo simples de enumeração após ganhar shell em um sistema Linux:
import subprocess
import platform
def enumerar_sistema():
"""
Enumeração básica pós-exploração em Linux/Unix.
Obtém informações do sistema comprometido.
"""
if platform.system() != "Linux":
print("Este script foi feito para Linux")
return
comandos = {
"ID do Usuário": "id",
"Sudoers": "sudo -l 2>/dev/null",
"Kernel": "uname -a",
"Processos Rodando": "ps aux | head -20",
"Conexões Abertas": "netstat -tuln 2>/dev/null || ss -tuln",
"Arquivos no Home": "ls -la ~",
"Variáveis de Ambiente": "env"
}
for descricao, comando in comandos.items():
print(f"\n===== {descricao} =====")
try:
resultado = subprocess.run(comando, shell=True, capture_output=True, text=True, timeout=5)
print(resultado.stdout if resultado.stdout else resultado.stderr)
except subprocess.TimeoutExpired:
print(f"Comando expirou: {comando}")
except Exception as e:
print(f"Erro: {e}")
# Uso (apenas em ambientes autorizados!)
# enumerar_sistema()
Regras de Engajamento (Rules of Engagement)
Importância e Escopo
As Regras de Engajamento (RoE) são o documento legal e técnico que define exatamente o que você pode e não pode fazer durante um Pentest. Sem isso, você está operando cegamente e pode cometer crimes inadvertidamente. O RoE estabelece o escopo técnico (quais sistemas testar), escopo legal (qual jurisdição, leis aplicáveis), métodos permitidos (tipos de teste), dados que podem ser tocados e janelas de tempo.
Um RoE bem definido protege tanto o testador quanto o cliente. Deve ser assinado por ambas as partes antes de qualquer trabalho começar. Qualquer desvio do escopo aprovado é uma violação contratual e potencialmente uma violação legal.
Elementos Essenciais de um RoE
Um RoE profissional contém:
- Escopo Técnico: Quais IPs, domínios, aplicações serão testados; quais estão fora do escopo
- Período de Teste: Datas, horários específicos (não teste em plena produção sem aviso)
- Métodos Proibidos: O que absolutamente não fazer (ex: DoS, modificar dados, remover arquivos)
- Métodos Permitidos: Quais técnicas podem ser usadas (ex: phishing, força bruta, exploração de código)
- Contatos de Emergência: Número para parar o teste imediatamente se algo der errado
- Dados Sensíveis: Como lidar com dados encontrados (criptografar relatórios, descartar cópias)
- Limitações: Não tocar em sistemas críticos de pacientes, sistemas financeiros não autorizados, etc.
- Liabilidade e Indenização: Quem é responsável por danos acidentais
Um template básico seria:
RULES OF ENGAGEMENT - PENTEST
Cliente: Acme Corp
Testador: João da Segurança
Data: 15 de Janeiro a 20 de Janeiro de 2024
ESCOPO TÉCNICO:
✓ Incluído:
- Domínio: acmecorp.com.br (todos os subdomínios)
- IPs: 192.168.1.0/24
- Aplicação Web: portal.acmecorp.local
- Testes de Engenharia Social: E-mail phishing (pré-aprovado)
✗ Excluído:
- Sistema de Backup (192.168.100.0/24)
- Banco de Dados de Produção (toques leitura apenas)
- Dados de Pacientes/PII (não extrair/armazenar)
- Infraestrutura de Telecomunicações
MÉTODOS:
✓ Permitido:
- Network scanning (Nmap)
- Exploit de vulnerabilidades conhecidas (CVEs)
- Testes de autenticação
- Brute force em contas de teste (não contas reais)
✗ Proibido:
- Denial of Service (DoS/DDoS)
- Modificação de dados em produção
- Violação física de propriedade
- Qualquer atividade fora do período aprovado
CONTATOS DE EMERGÊNCIA:
- PARAR TESTE: gerente.ti@acmecorp.com.br / +55 11 98765-4321
- Resposta desejada em: 15 minutos máximo
RESPONSABILIDADE:
- Testador indeniza danos causados por desvio do escopo
- Cliente aceita riscos inerentes ao pentest
Assinado:
___________________ ___________________
Cliente Testador
Data: ___________ Data: ___________
Elaboração de Relatórios Profissionais
Estrutura e Objetivos do Relatório
O relatório é o produto final do Pentest e deve comunicar claramente para públicos diferentes: executivos, gerentes de TI e desenvolvedores. Não é suficiente dizer "encontrei 50 vulnerabilidades" — você precisa contextualizar cada uma, explicar o impacto e propor remediação prática. Um bom relatório transforma achados técnicos em decisões de negócio.
A estrutura típica de um relatório profissional inclui:
- Executive Summary (1-2 páginas): Achados críticos, impacto de negócio, recomendações de alto nível
- Metodologia: Como o teste foi conduzido, ferramentas usadas, período
- Achados Detalhados: Cada vulnerabilidade com evidências, severidade, remediação
- Evidências Técnicas: Screenshots, logs, outputs de ferramentas
- Recomendações: Plano de ação priorizado
- Conclusões: Postura de segurança geral
Exemplo de Relatório Estruturado
Aqui um exemplo em Python que gera um relatório automatizado em HTML:
from datetime import datetime
from enum import Enum
class Severidade(Enum):
CRITICA = 5
ALTA = 4
MEDIA = 3
BAIXA = 2
INFORMACAO = 1
class Vulnerabilidade:
def __init__(self, titulo, severidade, descricao, impacto, remediacao, evidencia=""):
self.titulo = titulo
self.severidade = severidade
self.descricao = descricao
self.impacto = impacto
self.remediacao = remediacao
self.evidencia = evidencia
self.data_encontrada = datetime.now().strftime("%d/%m/%Y %H:%M")
class RelatorioPentest:
def __init__(self, cliente, testador, data_inicio, data_fim):
self.cliente = cliente
self.testador = testador
self.data_inicio = data_inicio
self.data_fim = data_fim
self.vulnerabilidades = []
self.resumo_executivo = ""
def adicionar_vulnerabilidade(self, vuln):
self.vulnerabilidades.append(vuln)
def gerar_html(self, caminho_saida="relatorio.html"):
"""Gera relatório em HTML formatado"""
# Ordena por severidade
vulns_ordenadas = sorted(self.vulnerabilidades,
key=lambda x: x.severidade.value,
reverse=True)
# Conta por severidade
contagemPorSeveridade = {}
for severidade in Severidade:
contagemPorSeveridade[severidade.name] = len([v for v in vulns_ordenadas if v.severidade == severidade])
html = f"""
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Relatório de Pentest - {self.cliente}</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; color: #333; }}
.header {{ background: #1a1a2e; color: white; padding: 20px; border-radius: 5px; }}
.summary {{ background: #f0f0f0; padding: 15px; margin: 20px 0; border-left: 4px solid #d9534f; }}
.vulnerabilidade {{ margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }}
.critica {{ border-left: 4px solid #d9534f; background: #fff5f5; }}
.alta {{ border-left: 4px solid #f0ad4e; background: #fffaf0; }}
.media {{ border-left: 4px solid #5bc0de; background: #f0f9fc; }}
.baixa {{ border-left: 4px solid #5cb85c; background: #f5fff5; }}
.informacao {{ border-left: 4px solid #999; background: #f9f9f9; }}
.titulo-vulner {{ font-size: 18px; font-weight: bold; margin-bottom: 10px; }}
.severidade {{ display: inline-block; padding: 5px 10px; border-radius: 3px; color: white; font-weight: bold; }}
.sev-critica {{ background: #d9534f; }}
.sev-alta {{ background: #f0ad4e; }}
.sev-media {{ background: #5bc0de; }}
.sev-baixa {{ background: #5cb85c; }}
.sev-info {{ background: #999; }}
.stats {{ display: flex; gap: 20px; margin: 20px 0; }}
.stat-box {{ background: white; border: 1px solid #ddd; padding: 15px; border-radius: 5px; text-align: center; }}
.stat-numero {{ font-size: 32px; font-weight: bold; }}
pre {{ background: #f5f5f5; padding: 10px; overflow-x: auto; }}
</style>
</head>
<body>
<div class="header">
<h1>Relatório de Penetration Testing</h1>
<p><strong>Cliente:</strong> {self.cliente}</p>
<p><strong>Testador:</strong> {self.testador}</p>
<p><strong>Período:</strong> {self.data_inicio} a {self.data_fim}</p>
<p><strong>Data do Relatório:</strong> {datetime.now().strftime("%d/%m/%Y")}</p>
</div>
<h2>Resumo Executivo</h2>
<div class="summary">
<p>Este Pentest identificou <strong>{len(vulns_ordenadas)} vulnerabilidades</strong> na infraestrutura testada.</p>
<div class="stats">
<div class="stat-box">
<div class="stat-numero" style="color: #d9534f;">{contagemPorSeveridade['CRITICA']}</div>
<div>Críticas</div>
</div>
<div class="stat-box">
<div class="stat-numero" style="color: #f0ad4e;">{contagemPorSeveridade['ALTA']}</div>
<div>Altas</div>
</div>
<div class="stat-box">
<div class="stat-numero" style="color: #5bc0de;">{contagemPorSeveridade['MEDIA']}</div>
<div>Médias</div>
</div>
<div class="stat-box">
<div class="stat-numero" style="color: #5cb85c;">{contagemPorSeveridade['BAIXA']}</div>
<div>Baixas</div>
</div>
</div>
<p><strong>Recomendação:</strong> Todas as vulnerabilidades críticas e altas devem ser remediadas em até 30 dias.</p>
</div>
<h2>Vulnerabilidades Encontradas</h2>
"""
for i, vuln in enumerate(vulns_ordenadas, 1):
classe_severidade = vuln.severidade.name.lower()
html += f"""
<div class="vulnerabilidade {classe_severidade}">
<div class="titulo-vulner">
{i}. {vuln.titulo}
<span class="severidade sev-{classe_severidade}">{vuln.severidade.name}</span>
</div>
<h4>Descrição:</h4>
<p>{vuln.descricao}</p>
<h4>Impacto de Negócio:</h4>
<p>{vuln.impacto}</p>
<h4>Remediação Recomendada:</h4>
<p>{vuln.remediacao}</p>
<h4>Data Encontrada:</h4>
<p>{vuln.data_encontrada}</p>
"""
if vuln.evidencia:
html += f"""
<h4>Evidência Técnica:</h4>
<pre>{vuln.evidencia}</pre>
"""
html += " </div>\n"
html += """
<hr>
<p><strong>Documento Confidencial - Restrito ao Cliente</strong></p>
<p>Este relatório contém informações sensíveis sobre vulnerabilidades de segurança e deve ser protegido adequadamente.</p>
</body>
</html>
"""
with open(caminho_saida, 'w', encoding='utf-8') as f:
f.write(html)
print(f"Relatório gerado: {caminho_saida}")
# Uso prático
if __name__ == "__main__":
# Criar relatório
relatorio = RelatorioPentest("Acme Corp", "João Silva", "15/01/2024", "20/01/2024")
# Adicionar vulnerabilidades
relatorio.adicionar_vulnerabilidade(Vulnerabilidade(
titulo="SQL Injection em Formulário de Login",
severidade=Severidade.CRITICA,
descricao="A aplicação não sanitiza entrada de usuário no campo 'email' do formulário de login, permitindo SQL injection.",
impacto="Um atacante pode acessar dados de todos os usuários, modificar permissões ou deletar registros no banco de dados.",
remediacao="Implementar prepared statements (parametrized queries) em todas as queries de banco de dados. Use ORMs como SQLAlchemy.",
evidencia="Payload: ' OR '1'='1\nResposta: Acesso concedido para user_id=1 (administrador)"
))
relatorio.adicionar_vulnerabilidade(Vulnerabilidade(
titulo="Senhas Padrão em Serviço SSH",
severidade=Severidade.ALTA,
descricao="O servidor SSH está usando credenciais padrão (admin:admin) no sistema de backup.",
impacto="Um atacante com acesso à rede pode ganhar acesso ao servidor e copiar todos os backups.",
remediacao="Altere a senha do usuário 'admin' para uma senha forte e única. Implemente autenticação por chave SSH.",
evidencia="SSH 192.168.1.10 - Login bem-sucedido com admin:admin"
))
relatorio.adicionar_vulnerabilidade(Vulnerabilidade(
titulo="Informação Sensível em Comentários HTML",
severidade=Severidade.BAIXA,
descricao="Comentários HTML contêm nomes de desenvolvedores, IPs internos e tecnologias usadas.",
impacto="Exposição de informações que podem ser usadas em ataques direcionados.",
remediacao="Remova comentários sensíveis de código antes de deployment. Use minificação automática.",
evidencia="<!-- API backend rodando em 10.0.0.5:8080 - Desenvolvido por Carlos -->"
))
# Gerar HTML
relatorio.gerar_html("relatorio_pentest.html")
Este código gera um relatório HTML profissional com visualização clara de cada vulnerabilidade, agrupada por severidade e com evidências técnicas.
Boas Práticas na Redação
Ao escrever um relatório, lembre-se que:
- Linguagem Clara: Evite jargão técnico desnecessário. Se usar, explique.
- Prova Concreta: Cada achado deve ter evidência — screenshot, log, output de ferramenta.
- Remediação Prática: Não diga "corrija a vulnerabilidade". Diga "implemente validação de entrada com regex pattern
^[a-zA-Z0-9@.]{1,50}$". - Priorização: Vulnerabilidades críticas no topo. Recomende plano de ação com prazos.
- Confidencialidade: Marque como "Confidencial", armazene criptografado, destrua rascunhos e logs após entregar.
Conclusão
Ao longo deste artigo, cobrimos três pilares essenciais da metodologia de Pentest profissional. Primeiro, as cinco fases estruturadas — reconhecimento, varredura, análise, exploração e pós-exploração — garantem cobertura completa do escopo sem deixar brechas. Cada fase construi sobre a anterior, transformando informações em descobertas tangíveis. Segundo, as Regras de Engajamento são o contrato que protege legalmente ambas as partes e define exatamente onde e como você pode testar — negligenciar isso é negligência profissional. Terceiro, o relatório não é um documento técnico desconectado da realidade; é uma ferramenta de persuasão que converte achados em decisões executivas de negócio, por isso deve ser claro, priorizado e acionável.
Domine essas três áreas e você terá a base de um Pentester profissional. A prática vem com o tempo, mas a metodologia é o que diferencia um testador amador de um profissional reconhecido.
Referências
- OWASP Testing Guide — Framework completo para testes de segurança em aplicações web
- PTES - Penetration Testing Execution Standard — Padrão de execução de pentests, metodologia detalhada em 7 fases
- NIST Cybersecurity Framework — Documentação oficial do framework de cibersegurança do NIST com melhores práticas
- PortSwigger Web Security Academy — Laboratórios práticos e tutoriais sobre vulnerabilidades reais com exemplos funcionais