45+ boxes feitas. Esse é o workflow de enumeração que eu defini. Não o “correto” — o que realmente funciona sob pressão de tempo sem perder coisas.

A Abordagem de Dois Passes com Nmap

Eu costumava rodar um scan grande no nmap. Perdia tempo. Agora faço dois passes toda vez.

Passe 1 — Scan TCP Rápido

nmap -sC -sV -oN scans/initial.nmap $IP

Bate nas top 1000 portas. Leva uns 30 segundos. Me dá algo pra trabalhar imediatamente enquanto o scan completo roda.

Passe 2 — Scan de Todas as Portas (Background)

nmap -p- -sV -oN scans/allports.nmap $IP

Rode em outro terminal. Pega os serviços escondidos em portas altas estranhas — e quase sempre tem um. Já perdi tempo em boxes porque uma web app tava rodando na porta 8443 ou 50000 e eu só encontrei 45 minutos depois.

Quando Eu Também Rodo UDP

nmap -sU --top-ports 50 -oN scans/udp.nmap $IP

Só top 50. Scan UDP completo demora uma eternidade e raramente compensa. As portas que importam:

  • 53 — DNS (zone transfers)
  • 161 — SNMP (community strings = info grátis)
  • 389 — LDAP
  • 123 — NTP (às vezes útil pra enumeração de domínio)

Regra: Se é uma box AD, sempre rode UDP. SNMP e DNS por UDP já me deram footholds mais de uma vez.


Serviço por Serviço — O Que Eu Realmente Checo

A ordem importa. Eu passo pelos serviços pela probabilidade de me dar um foothold.

HTTP/HTTPS (80, 443, 8080, 8443)

Web é quase sempre a superfície de ataque. Bato nela primeiro.

Checks imediatos:

  1. Navegar no site manualmente. Ler tudo. Checar código fonte.
  2. Checar /robots.txt, /sitemap.xml
  3. Identificar a tech stack — Wappalyzer ou headers de resposta
whatweb http://$IP

Brute force de diretórios:

feroxbuster -u http://$IP -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,html -o scans/ferox.txt

Uso feroxbuster ao invés de gobuster agora. Recursivo por padrão, mais rápido, saída melhor.

Árvore de decisão pra extensões:

  • Box Linux -> -x php,txt,html,sh
  • Box Windows -> -x aspx,asp,txt,html,config
  • Framework identificado -> adicionar extensões específicas do framework (.jsp, .do, etc.)

Erros comuns que eu cometi:

  • Não adicionar hostname ao /etc/hosts. Virtual hosting tá em todo lugar. Se você ver um nome de domínio em qualquer lugar — headers, conteúdo da página, certificado — adicione e scaneie de novo.
  • Só scanear com uma wordlist. Se directory-list-2.3-medium não achar nada, tente raft-medium-words.txt. Listas diferentes pegam coisas diferentes.
  • Ignorar 403s. Um 403 significa que algo existe. Tente bypasses, tente adicionar extensões, tente enumeração mais profunda nesse path.

Enumeração de subdomínio/vhost:

ffuf -u http://$IP -H "Host: FUZZ.domain.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -fs <default_size>

A flag -fs é crítica. Filtre o tamanho da resposta padrão ou você vai se afogar em falsos positivos.


SMB (139, 445)

Segunda coisa que eu checo. SMB vaza info pra caramba.

# Check null session
smbclient -N -L //$IP/

# Enum4linux (barulhento mas completo)
enum4linux -a $IP

# Listar shares com credenciais depois
smbmap -H $IP
smbmap -H $IP -u 'guest' -p ''

O que eu tô procurando:

  • Shares legíveis — Baixar tudo. smbget -R smb://$IP/sharename/
  • Shares graváveis — Potencial pra ataques de arquivo SCF, dropar payloads
  • Listas de usuários — RID brute forcing se null sessions funcionarem
# RID brute force pra usernames
crackmapexec smb $IP -u '' -p '' --rid-brute

Pegadinha: smbclient -N e smbmap se comportam diferente com null sessions. Se um falhar, tente o outro. Já tive boxes onde smbclient não mostra nada mas smbmap com guest / senha vazia lista shares de boa.


FTP (21)

Check rápido. Ou é útil ou não é.

# Login anônimo
ftp $IP
# Username: anonymous
# Senha: (vazio ou qualquer coisa)

Se anônimo funcionar:

  • Baixar tudo: mget *
  • Checar se você pode fazer upload. Suba um arquivo teste. Se também tá servindo HTTP, você pode ter um caminho de webshell.
  • Checar arquivos ocultos: ls -la

Se anônimo não funcionar: Siga em frente. Volte com creds depois.


DNS (53)

Importa muito em boxes AD. Menos em standalone.

# Tentativa de zone transfer
dig axfr @$IP domain.htb

# Reverse lookup
dig -x $IP @$IP

# Qualquer registro
dig any domain.htb @$IP

Zone transfers são raros em engagements reais mas aparecem em boxes HTB/OSCP regularmente. Sempre tente.

Brute force de subdomínio via DNS:

dnsenum --dnsserver $IP --enum -f /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt domain.htb

LDAP (389, 636)

Se LDAP tá aberto, é uma box AD. Aja de acordo.

# Anonymous bind
ldapsearch -x -H ldap://$IP -b "DC=domain,DC=htb"

# Pegar naming contexts primeiro se você não sabe o domínio
ldapsearch -x -H ldap://$IP -s base namingcontexts

O que você quer do LDAP:

  • Lista completa de usuários
  • Group memberships
  • Campos de descrição (admins adoram colocar senhas nas descrições)
  • Service accounts
# Puxar todos os usuários
ldapsearch -x -H ldap://$IP -b "DC=domain,DC=htb" '(objectClass=person)' sAMAccountName description memberOf

Pegadinha: Anonymous bind nem sempre significa que você recebe dados. Alguns DCs permitem o bind mas retornam nada. Tente com um usuário válido depois.


Kerberos (88)

Kerberos aberto = box AD. Duas coisas pra fazer imediatamente sem creds.

Enumeração de usuários:

kerbrute userenum -d domain.htb --dc $IP /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt

Isso não é barulhento da forma que brute force é. Não gera eventos de logon falhado pra usuários válidos. Ótimo pra montar uma lista de usuários.

AS-REP Roasting (sem creds):

impacket-GetNPUsers domain.htb/ -dc-ip $IP -usersfile users.txt -no-pass

Se alguma conta tem “Do not require Kerberos preauthentication” setado, você pega um hash. Cracka ele.


MSSQL (1433)

# Creds padrão
impacket-mssqlclient sa:sa@$IP
impacket-mssqlclient sa:''@$IP

# Com creds encontradas depois
impacket-mssqlclient domain.htb/user:password@$IP -windows-auth

Se você entrar:

  • xp_cmdshell pra execução de comandos do SO (pode precisar habilitar)
  • xp_dirtree pra autenticação forçada / captura de hash
  • Checar linked servers — EXEC sp_linkedservers
-- Habilitar xp_cmdshell
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
EXEC xp_cmdshell 'whoami';

SNMP (161/UDP)

Criminalmente subestimado. SNMP com community string “public” dumpa tudo.

# Checar community strings
onesixtyone -c /usr/share/seclists/Discovery/SNMP/snmp.txt $IP

# Walk na árvore MIB
snmpwalk -v2c -c public $IP 1.3.6.1

OIDs úteis:

  • 1.3.6.1.2.1.25.4.2.1.2 — Processos rodando
  • 1.3.6.1.4.1.77.1.2.25 — Contas de usuário
  • 1.3.6.1.2.1.25.6.3.1.2 — Software instalado

Eu uso snmpwalk com OIDs específicos ao invés de andar na árvore inteira. Mais rápido, menos barulho.

Pegadinha: Se SNMPv1/v2c tá rodando, community strings são enviadas em texto claro. Padrão é quase sempre public. Mas também tente private, manager, internal.


WinRM (5985, 5986)

Não dá pra fazer muito com WinRM sem creds, mas anote que tá aberto. Uma vez que tiver credenciais:

evil-winrm -i $IP -u 'user' -p 'password'

Se porta 5985 tá aberta e você tem creds válidas -> shell instantânea. Esse é o go-to pra lateral movement no Windows.


SSH (22)

Não tem muito o que enumerar sem creds. Anoto a versão (às vezes revela versão do SO) e sigo em frente.

# Banner grab
nmap -sV -p22 $IP

Volte com credenciais encontradas. Tente reuso de username. Tente chaves encontradas em outros serviços.

Uma coisa: Se você achar uma chave privada SSH em qualquer lugar — diretório web, share SMB, FTP — tente imediatamente contra todo usuário que você conhece.


O Workflow na Prática

Assim que os primeiros 15 minutos numa box parecem:

  1. Terminal 1: Scan nmap rápido -> comece trabalhando nos resultados imediatamente
  2. Terminal 2: Scan completo de portas rodando em background
  3. Terminal 3: Se HTTP encontrado -> browser aberto, whatweb, feroxbuster rodando
  4. Anotações: Registrar todo achado, todo username, toda credencial potencial
Target: $IP
Hostname: ???
OS: ???
Domain: ???

Open Ports:
-

Users Found:
-

Credentials:
-

Interesting Findings:
-

Eu mantenho essa nota corrente e atualizo constantemente. Parece básico. É a coisa que mais me economiza tempo.


Quando Seguir em Frente vs. Ir Mais Fundo

Essa é a habilidade mais difícil e eu ainda tô aprendendo.

Vá mais fundo quando:

  • Você achou uma web app customizada (quase certamente tem uma vuln nela)
  • Você achou usernames mas sem senhas (hora de password spray)
  • Um serviço retornou informação parcial (provavelmente tem mais)
  • Você tem um conjunto de creds mas não consegue shell (reutilize em todo lugar)

Siga em frente quando:

  • Página padrão, sem conteúdo custom, directory busting não retorna nada depois de duas wordlists
  • Serviço requer autenticação e você tem zero creds
  • Você já gastou 30+ minutos em um serviço sem nada pra mostrar

O maior desperdiçador de tempo: Tentar explorar algo antes de terminar a enumeração. Já queimei horas tentando pegar foothold por um serviço enquanto o caminho real era por uma porta que eu nem tinha scaneado ainda.

Enumere tudo primeiro. Explore depois. Toda vez que eu quebro essa regra, eu me arrependo.


Referência Rápida — Porta pra Ação

PortaServiçoPrimeiro Move
21FTPLogin anônimo
22SSHAnotar versão, seguir em frente
25SMTPEnumeração de usuários (VRFY/EXPN)
53DNSZone transfer
80/443HTTPNavegar, tech stack, brute de diretórios
88KerberosEnum de usuários, AS-REP Roast
110/143POP3/IMAPTentar creds padrão
135MSRPCrpcclient null session
139/445SMBNull session, listagem de shares
161SNMPBrute de community string, walk
389/636LDAPAnonymous bind, dumpar usuários
1433MSSQLCreds padrão (sa:sa)
3306MySQLCreds padrão (root:root)
5985WinRMPrecisa creds -> evil-winrm
5432PostgreSQLCreds padrão (postgres:postgres)
6379RedisSem auth? -> RCE
8080HTTP AltMesmo que 80

Esse workflow não é perfeito. Eu atualizo ele depois de cada box que me ensina algo novo. O princípio central não muda: scaneie rápido, enumere amplo, tome notas, não explore até ter visto o cenário completo.