Ferramentas de segurança
Noções básicas do OWASP ZAP contra o seu Juice Shop local
Rode a varredura passiva do ZAP contra o Juice Shop na sua máquina, leia o relatório e confirme um alerta à mão antes de confiar nele.
O Nmap lista as portas abertas do seu próprio computador. Veja scans connect e SYN, detecção de serviço e como ligar cada porta ao processo que a abriu.
Nmap é um scanner de rede. Você aponta para um host e ele informa quais portas respondem, em que estado cada uma está e, se você pedir, qual serviço e versão estão por trás de uma porta aberta. No seu próprio computador, isso vira uma ferramenta rápida de inventário. Você obtém a lista do que está escutando e pode comparar essa lista com o que você acha que está rodando.
Trate a saída do Nmap como um ponto de partida para o inventário. Ela não é um achado. Uma porta aberta só diz que um socket está escutando. Se esse socket é um problema depende de qual processo é o dono dele, de quem consegue alcançá-lo e de ele precisar existir. Este artigo termina com o passo que a maioria das pessoas pula: ligar cada porta aberta ao processo por trás dela.
A maior parte das surpresas em uma máquina vem de algo que ninguém lembra de ter iniciado. Um servidor de desenvolvimento deixado rodando desde a semana passada. Um contêiner que publicou uma porta em todas as interfaces. Um serviço em segundo plano que se instalou durante uma atualização. Você não consegue avaliar o que não listou, e um inventário de portas é o jeito mais barato de começar. O mesmo método funciona em um notebook, em uma máquina virtual que você montou ou em uma rede de cliente para a qual você tem autorização de teste.
Leia isto antes de rodar qualquer scan. O livro do Nmap tem um capítulo sobre questões legais, e o conselho central é simples: peça permissão antes de escanear uma rede que você não controla. Ele lembra que alguns provedores de internet proíbem o escaneamento não autorizado nas suas políticas de uso aceitável e podem desconectar quem as violar. Em trabalhos profissionais, diz que a melhor forma de evitar problemas é obter autorização por escrito de quem representa a rede-alvo, com o Statement of Work como lugar para registrá-la. Também observa que raramente alguém incomoda você por escanear a sua própria máquina ou as redes que você administra.
Para este artigo, a regra é:
Todo comando deste laboratório mira 127.0.0.1, o endereço de loopback. Os pacotes enviados para lá nunca saem da sua máquina. Por isso o laboratório é seguro para praticar, e o escopo é fácil de definir: o único host envolvido é o seu.
Uma porta é um número que o sistema operacional usa para entregar tráfego de entrada a um processo. Se um programa avisou o sistema de que vai aceitar conexões na porta TCP 3000, esse socket está escutando. Um scan pergunta, para cada porta, o que acontece quando uma sonda chega.
O Nmap informa um entre vários estados. Os três que você mais vai ver são:
Esses estados descrevem a sonda, não o risco. Uma porta fechada ainda pode causar problema se um serviço de que você depende estiver parado. Uma porta filtrada pode ser um firewall fazendo o trabalho dele. Mantenha o estado separado do que ele significa.
O Nmap tem vários tipos de scan. Dois deles importam para quem está começando.
Um scan connect pede ao sistema operacional que abra uma conexão TCP completa com cada porta. O sistema faz o aperto de mão de três vias normal. Se a conexão for bem-sucedida, a porta está aberta, e o Nmap a fecha. O guia do Nmap descreve o connect como o padrão quando o scan SYN não está disponível, porque ele não exige privilégios para enviar pacotes brutos. O Nmap usa a chamada connect do próprio sistema em vez de montar os pacotes.
O custo é a visibilidade. Uma conexão completa aparece nos logs do alvo, o que não tem problema no seu laboratório e merece atenção em qualquer rede que você não possui.
Um scan SYN envia um pacote SYN, o mesmo primeiro passo de uma conexão real, e depois lê a resposta. Um SYN/ACK significa que a porta está escutando. Um RST significa que nada escuta. O Nmap não completa o aperto de mão, e por isso esse scan costuma ser chamado de half-open. O guia diz que o scan SYN é o padrão quando o Nmap tem privilégio para enviar pacotes brutos, o que normalmente significa root ou direitos de administrador.
No Windows, confira nas notas de instalação do Nmap o suporte a pacotes brutos antes de depender de -sS. Este laboratório usa -sT porque ele funciona sem privilégios elevados e ainda dá os estados de porta que você precisa.
Para quem está começando, a diferença útil é o que cada scan deixa para trás. Um scan connect completa o aperto de mão e aparece nos logs dos dois lados. Um scan SYN para antes de o aperto de mão terminar.
O estado da porta diz que algo escuta na 8000. Não diz o que esse algo é. A opção -sV envia sondas para as portas abertas, compara as respostas com a base de assinaturas do Nmap e informa o nome e a versão do serviço quando reconhece.
A intensidade vai de 0, que envia o menor número de sondas, até 9, que tenta todas. Níveis mais altos demoram mais e geram mais tráfego. Por padrão, a detecção de versão pula a porta TCP 9100, uma porta de impressora que pode reagir mal a sondas. Use a menor intensidade que responda à sua pergunta e rode -sV apenas em sistemas que você controla.
Strings de versão são evidência, não prova. Quem administra um serviço pode alterar o banner, então um número de versão é uma afirmação a ser conferida no próprio software.
O Nmap pode gravar resultados em arquivo, além de mostrar na tela. Os formatos que você mais vai usar são:
-oN arquivo: saída normal, legível por uma pessoa.-oX arquivo: XML, para ferramentas que leem resultados automaticamente.-oG arquivo: saída "grepable", uma linha por host, para filtros rápidos no shell.Use -oN para anotações que você mesmo vai ler, e -oX quando outra ferramenta vai processar o resultado. Guarde os arquivos de scan junto das suas notas de laboratório. Um scan da semana passada registra o que era verdade na semana passada, não hoje.
Você precisa de Docker, Python 3, Nmap e de uma máquina em que as portas 3000 e 8000 estejam livres em 127.0.0.1. Se ainda não montou uma rede de laboratório, comece por como criar uma rede Docker isolada para laboratórios. Todo passo abaixo roda na sua máquina. Os comandos são os do laboratório. Quando eu rodei no meu Windows 11, mostro a saída que vi. Quando não consegui rodar, digo isso e explico o que procurar.
O OWASP Juice Shop é um app web deliberadamente vulnerável, feito para treino. Suba-o com a porta ligada só ao loopback:
docker run -d --name juice-local -p 127.0.0.1:3000:3000 bkimminich/juice-shopA parte 127.0.0.1 importa. Sem ela, o Docker publica a porta em todas as interfaces, e qualquer dispositivo da sua rede poderia alcançar um app feito só para treino.
Se o nome já estiver em uso, o Docker para com um erro de conflito. Não apague esse contêiner antes de saber quem o criou. Inspecione-o primeiro:
docker inspect juice-local --format 'image={{.Config.Image}} ports={{json .NetworkSettings.Ports}} status={{.State.Status}}'O que observei na minha máquina:
image=bkimminich/juice-shop ports={"3000/tcp":[{"HostIp":"127.0.0.1","HostPort":"3000"}]} status=runningSubi um novo para esta execução e confirmei o mapeamento com docker port juice-local, que mostrou 3000/tcp -> 127.0.0.1:3000. O Docker já tinha a imagem em cache, então nada foi baixado. Dê alguns segundos para o app iniciar antes de abri-lo no navegador.
python3 -m http.server 8000 --bind 127.0.0.1 &No Windows, python3 pode não existir. Na minha máquina ele não estava no PATH, então rodei o Python 3.12 pelo caminho completo da instalação, com os mesmos argumentos. O & deixa o servidor rodando em segundo plano no shell atual. Teste de outro terminal:
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/index.txtO arquivo que pedi existia na pasta onde iniciei o servidor, e o teste devolveu 200. O log do servidor registrou a requisição:
127.0.0.1 - - [08/Nov/2026 06:20:25] "GET /index.txt HTTP/1.1" 200 -Antes de escanear, pergunte ao sistema operacional. Essa lista é a sua referência, e ela não depende do Nmap.
No Linux:
ss -tlnpNo Windows, no PowerShell:
Get-NetTCPConnection -State ListenNa minha máquina usei uma versão que também mostra o processo dono:
Get-NetTCPConnection -State Listen | Where-Object { $_.LocalPort -lt 10000 } | Sort-Object LocalPort | ForEach-Object { $p = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue; '{0,-15} {1,6} {2,8} {3}' -f $_.LocalAddress, $_.LocalPort, $_.OwningProcess, $p.ProcessName }A saída na minha máquina, limitada às portas abaixo de 10000:
:: 135 2204 svchost
0.0.0.0 135 2204 svchost
192.168.0.100 139 4 System
172.23.112.1 139 4 System
:: 445 4 System
0.0.0.0 515 6084 svchost
:: 515 6084 svchost
127.0.0.1 1026 23620 com.docker.backend
127.0.0.1 3000 23620 com.docker.backend
:: 3311 11308 node
127.0.0.1 5000 43252 python
0.0.0.0 5040 10556 svchost
:: 7680 4604 svchost
127.0.0.1 8000 49736 python
127.0.0.1 8001 7976 python
127.0.0.1 8026 23620 com.docker.backendConte as linhas. Muitas dessas portas pertencem ao próprio Windows, não a algo que você iniciou. É normal, e é exatamente por isso que um inventário precisa dizer quem é o dono de cada porta.
nmap -sT -p 1-10000 127.0.0.1Eu não rodei este comando. O Nmap não está instalado na máquina que usei, e não o instalei. O que procurar quando você rodar: uma tabela PORT STATE SERVICE. Cada linha marcada como open deve bater com uma linha do passo 3. Neste laboratório, 3000/tcp e 8000/tcp devem aparecer como abertas. O Nmap costuma agrupar as portas fechadas numa linha de resumo, então as linhas a ler são as abertas.
Como substituto, escrevi uma verificação curta em loopback com a biblioteca padrão do Python. Ela abre uma conexão TCP para cada porta de 1 a 10000 em 127.0.0.1 e informa as que aceitam. Ela faz o mesmo aperto de mão que um scan connect faz, mas não é o Nmap:
import socket
from concurrent.futures import ThreadPoolExecutor
HOST = "127.0.0.1"
def is_open(port: int) -> bool:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(0.3)
return s.connect_ex((HOST, port)) == 0
if __name__ == "__main__":
with ThreadPoolExecutor(max_workers=200) as ex:
results = list(ex.map(is_open, range(1, 10001)))
open_ports = [p for p, ok in zip(range(1, 10001), results) if ok]
print(f"open on {HOST} in 1-10000: {open_ports}")Saída na minha máquina:
open on 127.0.0.1 in 1-10000: [135, 445, 515, 1026, 3000, 3311, 5000, 5040, 7680, 8000, 8001, 8026]Toda porta dessa lista também aparece na tabela de listeners do passo 3. As duas fontes concordam, e essa é a checagem que você quer antes de confiar em qualquer uma delas.
nmap -sV -p 3000,8000 127.0.0.1 -oN localhost-scan.txtNão rodei aqui, pelo mesmo motivo do passo 4. O que procurar: uma coluna VERSION ao lado de 3000 e 8000, e um arquivo chamado localhost-scan.txt na pasta atual. O texto de versão que o Nmap mostra para a porta 3000 é uma afirmação a conferir. Abra o app no navegador ou leia a documentação do próprio software antes de anotar a versão em qualquer lugar.
Este passo transforma um scan em inventário. Para cada porta aberta, você precisa do processo que a possui. No Linux, ss -tlnp mostra o nome do processo e o PID na última coluna. No Windows, pegue o PID de OwningProcess e consulte:
Get-Process -Id 23620 | Select-Object Id, ProcessNameFiz isso para as portas da lista. Eis quem eram os donos na minha máquina:
| Porta | Escutando em | PID | Dono | O que é |
|---|---|---|---|---|
| 3000 | 127.0.0.1 | 23620 | com.docker.backend | Proxy do Docker Desktop para o contêiner juice-local, confirmado com docker port juice-local |
| 8000 | 127.0.0.1 | 49736 | python | O http.server do passo 2 |
| 3311 | todas as interfaces (::) |
11308 | node | Um processo Node.js; o tasklist /svc não lista serviço para ele, então é um programa que alguém iniciou |
| 515 | todas as interfaces | 6084 | svchost | O serviço de impressão LPD do Windows; tasklist /svc /fi "PID eq 6084" mostra LPDSVC |
Duas linhas pedem uma decisão, e o scan sozinho não consegue tomá-la. O processo Node.js na 3311 escuta em todas as interfaces, então, se for um servidor de desenvolvimento para trabalho local, outros dispositivos conseguem alcançá-lo. O serviço LPD na 515 também escuta em todas as interfaces. Decidir se algum deles deve continuar rodando é uma escolha sua, e a correção cabe ao dono do processo, não ao scanner. Não pare um serviço só porque ele apareceu em uma lista.
A linha do Docker precisa de uma segunda checagem. O processo de backend repassa a porta, então o PID sozinho não diz qual contêiner está por trás. O docker port juice-local deu o mapeamento que eu esperava:
3000/tcp -> 127.0.0.1:3000PIDs mudam. O servidor Python tinha o PID 49668 numa listagem anterior nesta máquina. Depois que o reiniciei para esta execução, a mesma linha de comando passou a ocupar a porta 8000 sob o PID 49736. Leia o PID logo antes de agir, e confirme a linha de comando além do nome.
docker rm -f juice-local
kill %1Rode o primeiro comando só em um contêiner que você criou para este laboratório. O kill %1 só funciona no shell que iniciou o job; de outro shell, ache o PID como no passo 6, confira a linha de comando e então pare o processo.
Escanear um endereço que você não possui. Uma faixa privada como 192.168.x.x pode pertencer a um roteador ou a um dispositivo que outra pessoa administra. Escaneie apenas o que você tem permissão escrita para escanear.
Ler "open" como "vulnerável". Uma porta aberta é um fato sobre um listener. Ela só vira achado quando você sabe qual é o serviço, por que ele está alcançável e se deveria estar.
Esquecer o -p. Sem um intervalo de portas, o Nmap escaneia as 1.000 portas mais comuns de cada protocolo. O laboratório usa -p 1-10000 de propósito, porque um serviço em porta incomum é exatamente o que um inventário precisa pegar.
Publicar sem o endereço. -p 3000:3000 publica em todas as interfaces. Mantenha 127.0.0.1: na frente quando o app for só para você.
Confiar em uma string de versão. O -sV lê o que o serviço diz sobre si mesmo. Confira a versão no próprio software antes de depender dela.
Parar no scan. O scan entrega números de porta. Descobrir o dono de cada porta é a parte que você ainda precisa fazer.
Anote as portas que você espera antes de escanear e depois compare. É o jeito mais rápido de notar algo que você não sabia que estava rodando.
Escaneie duas vezes: uma com o servidor Python rodando e outra depois de pará-lo. Salve os dois arquivos com -oN e compare. A diferença é o que você mudou.
Leia no guia do Nmap as seções sobre -oX e -Pn. Quando souber os formatos de saída, você pode alimentar resultados de scan em um script e acompanhar mudanças ao longo do tempo, sempre só nas suas próprias máquinas.
O próximo artigo da série sai das portas e vai para a camada web, com OWASP ZAP: primeiros passos contra o Juice Shop rodando contra o mesmo contêiner.
Ferramentas de segurança
Rode a varredura passiva do ZAP contra o Juice Shop na sua máquina, leia o relatório e confirme um alerta à mão antes de confiar nele.