6. System and Network Security
This chapter moves from the single machine to the networks that connect machines, where most real-world attacks travel. It builds a working model of how networks operate, then layers on the controls that defend them — authentication, access control, firewalls, secure protocols, and wireless security — alongside the attacks each control exists to stop. The recurring theme is that the network was designed for connectivity, not trust, so security must be added deliberately at every layer.
<a id="61-networking-refresher-for-security"></a>
6.1 Networking Refresher for Security
Before you can defend or attack a network you must be able to reason about how a packet actually travels, where it can be observed or altered, and which layer each control lives at. This section is a security-focused refresher on the networking fundamentals the rest of the chapter assumes.
OSI and TCP/IP Models
Theory
A network stack is a tower of abstractions: the application at the top wants to send a message, and each layer below wraps that message in its own envelope, adds the information its peer on the other machine needs, and hands it down. The reason to learn the layers is not academic taxonomy — it is that every attack and every defense lives at a specific layer, and naming the layer tells you what information is available, what can be inspected, and what can be spoofed.
The OSI model is the seven-layer reference model used for discussion; the TCP/IP model is the four-layer model that real networks actually implement. They map onto each other loosely, and in practice engineers mix the vocabularies — "Layer 2" (OSI data link) and "Layer 7" (OSI application) are everyday terms even though the traffic runs on TCP/IP.
| OSI layer | TCP/IP layer | Unit (PDU) | Example | Security relevance |
|---|---|---|---|---|
| 7 Application | Application | data | HTTP, DNS, TLS | input validation, app logic, auth |
| 6 Presentation | Application | data | TLS, encoding | encryption, serialization bugs |
| 5 Session | Application | data | sockets, RPC | session hijacking |
| 4 Transport | Transport | segment | TCP, UDP | port scanning, SYN floods |
| 3 Network | Internet | packet | IP, ICMP | IP spoofing, routing attacks |
| 2 Data link | Link | frame | Ethernet, ARP, Wi-Fi | ARP spoofing, MAC flooding |
| 1 Physical | Link | bits | cables, radio | wiretapping, jamming |
The key mechanism is encapsulation: as data descends, each layer prepends (and sometimes appends) a header. An HTTP request becomes a TCP segment (adds ports and sequence numbers), which becomes an IP packet (adds source/destination addresses), which becomes an Ethernet frame (adds MAC addresses). On arrival the process reverses — decapsulation — each layer strips its header and passes the payload up. A defender watching traffic sees all these headers nested, which is exactly why packet capture is so powerful: the envelopes reveal who is talking to whom, how, and with what.
Examples
Encapsulation of an HTTP GET as it descends the stack:
Application: [ GET /index.html HTTP/1.1 ... ]
Transport (TCP): [TCP hdr | GET /index.html HTTP/1.1 ... ]
src:49152 dst:80 seq/ack flags
Internet (IP): [IP hdr |TCP hdr | ...payload... ]
src:10.0.0.5 dst:93.184.216.34 TTL proto=6
Link (Ethernet):[Eth hdr |IP hdr |TCP hdr | ...payload... | CRC]
src MAC dst MAC type=0x0800
\_____ each layer only trusts its own header _____/
# See the layers of a real connection without a full packet capture.
ss -tnp # transport layer: TCP sockets, ports, owning process
ip route get 93.184.216.34 # network layer: which route/interface a packet takes
ip neigh # link layer: the ARP/neighbour table (IP <-> MAC)
Key Takeaways
- Network stacks are layered abstractions; every attack and defense maps to a specific layer, so naming the layer tells you what data is visible and what can be spoofed.
- OSI has seven layers (reference/discussion); TCP/IP has four (implementation). Engineers mix the vocabularies — "Layer 2" and "Layer 7" are everyday terms.
- Encapsulation wraps data in a header at each descending layer; decapsulation strips them on the way up. Packet capture sees all nested headers.
- Each layer trusts only its own header, which is why spoofing at a lower layer (MAC, IP) can deceive everything above it.
- Lower layers (1–2) are the local link; upper layers (3–7) cross networks — knowing which, bounds how far an attack at that layer can reach.
🧪 Practice
- For each of these, name the OSI layer: a SYN flood, ARP spoofing, SQL injection, TLS, IP spoofing.
- Capture one HTTP request with
tcpdump -Xand identify the Ethernet, IP, and TCP headers in the hex output.- Explain, in encapsulation terms, why a firewall that only reads Layer 3/4 headers cannot block a specific URL.
- Interview-style: "Why is a Layer 2 attack like ARP spoofing limited to the local network, while a Layer 3 attack can originate from anywhere?" Hint: think about which headers are rewritten at each router hop and which are not.
IP Addressing, Subnetting, and NAT
Theory
Every device on an IP network needs an address so packets can be routed to it, much like every building needs a postal address. An IPv4 address is 32 bits (written as four dotted decimal octets, e.g. 192.168.1.10); IPv6 is 128 bits to escape the exhaustion of the IPv4 space. An address alone is not enough — a device also needs to know which other addresses are local (reachable directly) versus remote (reachable only through a router). That distinction is what the subnet mask encodes.
A subnet mask splits an address into a network portion (the leading bits, shared by every host on the same link) and a host portion (the trailing bits, unique per host). CIDR notation writes the mask as the number of network bits: 192.168.1.0/24 means the first 24 bits are the network, leaving 8 bits (254 usable hosts) for the host portion. Subnetting — carving a large network into smaller ones — is a security tool as much as an addressing one: each subnet is a boundary where you can place a firewall and limit how far an attacker who compromises one host can reach (the segmentation idea developed later in this chapter).
Private address ranges (RFC 1918: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) are not routable on the public internet. That is where NAT (Network Address Translation) comes in: a router rewrites the private source address of outbound packets to its own public address, remembers the mapping, and rewrites the replies back. NAT lets many internal hosts share one public IP, and as a side effect it hides the internal topology and blocks unsolicited inbound connections — a crude but real security benefit. It is not a firewall, though: NAT provides no policy, and its "protection" disappears the moment a port is forwarded or the host initiates the connection.
Examples
192.168.1.0/24 breakdown:
address 192.168.1.0
mask 255.255.255.0 = /24 (24 network bits, 8 host bits)
network 192.168.1.0 <- all-zero host part: the network id
first 192.168.1.1
last 192.168.1.254
broadcast192.168.1.255 <- all-one host part: not assignable
usable hosts = 2^8 - 2 = 254 (minus network and broadcast)
NAT translation (outbound then inbound reply):
internal 10.0.0.5:51000 --> 93.184.216.34:443
router rewrites source:
public 203.0.113.9:40001 --> 93.184.216.34:443
reply comes back to 203.0.113.9:40001, router maps it back to 10.0.0.5:51000
# Compute subnet details and scan a subnet's live hosts.
ipcalc 192.168.1.0/24 # prints network, broadcast, host range
nmap -sn 192.168.1.0/24 # ping sweep: which hosts in the subnet are up
# A /24 gives 254 hosts; splitting into /26 gives 4 subnets of 62 hosts each,
# each of which can be isolated behind its own firewall rule.
Key Takeaways
- An IP address identifies a host; the subnet mask (CIDR, e.g.
/24) splits it into network and host portions and defines what is local versus routed. - Subnetting carves networks into smaller segments — an addressing tool that doubles as a security boundary for firewalls and containment.
- Private ranges (
10/8,172.16/12,192.168/16) are not internet-routable; NAT rewrites private addresses to a shared public one and maps replies back. - NAT hides internal topology and blocks unsolicited inbound connections as a side effect, but it is not a firewall — it enforces no policy and is bypassed by port forwarding.
- Usable hosts in a subnet is
2^(host bits) − 2, excluding the network and broadcast addresses.
🧪 Practice
- For
10.20.30.0/27, compute the network address, broadcast address, usable host range, and host count.- Split
192.168.0.0/24into four equal subnets and give the CIDR and range of each.- Explain why an attacker on the public internet cannot directly initiate a TCP connection to a host behind NAT with no port forwarding — and how the host can still be reached by tricking it into connecting out.
- Interview-style: "Is NAT a security control? Justify your answer." Hint: distinguish a side effect of address scarcity from a deliberate, policy-driven access decision.
TCP Handshake and Session States
Theory
TCP exists to turn the unreliable, unordered delivery of IP into a reliable, ordered byte stream. To do that both ends must agree they are talking, agree on where the numbering starts, and track the conversation's progress — this agreement is the three-way handshake, and the tracking is the connection state machine. Understanding both is essential because many network attacks and scans are precisely about manipulating the handshake or lying about the state.
The handshake is three segments. The client sends SYN (synchronize) carrying its initial sequence number (ISN). The server replies SYN-ACK, acknowledging the client's ISN and sending its own. The client replies ACK. After these three, the connection is ESTABLISHED and data flows. Each side's sequence numbers increment per byte, which is how TCP detects loss and reordering — and why an attacker who wants to inject into or hijack a session must predict or observe those sequence numbers (the session-hijacking topic later).
The connection progresses through a defined set of states, and the states are what port scanners and firewalls reason about. A closed port replies to a SYN with RST (reset); an open port replies with SYN-ACK; a filtered port (firewalled) sends nothing. This is the entire basis of nmap's SYN scan: send a SYN, read the one-packet reply, infer the state, and never complete the handshake (a "half-open" scan that is stealthier and faster because it leaves no established connection). Teardown has its own states (FIN/FIN-ACK, then TIME_WAIT), and a glut of half-open or TIME_WAIT connections is itself a signal — a SYN flood is nothing more than thousands of SYNs whose handshakes are never completed, exhausting the server's table of pending connections.
Examples
Three-way handshake and a SYN-scan probe side by side:
Normal connect: nmap -sS (half-open) scan:
client server scanner target
| --- SYN ----> | | --- SYN ----> |
| <-- SYN/ACK - | | <-- SYN/ACK - | port OPEN
| --- ACK ----> | | --- RST ----> | (abort, no ACK)
[ESTABLISHED] (never established = stealthier)
closed port: SYN -> ... <- RST (port CLOSED)
filtered: SYN -> ... (silence) (port FILTERED by firewall)
# Observe states and the scans that probe them.
ss -tan state established # list currently established TCP connections
ss -tan state syn-recv # half-open: a flood of these suggests a SYN flood
nmap -sS -p 1-1000 10.0.0.5 # SYN (half-open) scan: infer open/closed/filtered
nmap -sT -p 22,80,443 10.0.0.5 # full-connect scan: completes the handshake (noisier)
Key Takeaways
- TCP's three-way handshake (SYN, SYN-ACK, ACK) establishes agreement and synchronizes sequence numbers before any data flows.
- Sequence numbers increment per byte and underpin reliability; an attacker hijacking a session must predict or observe them.
- Port state is inferred from the reply: SYN-ACK = open, RST = closed, silence = filtered — the basis of all TCP port scanning.
- A half-open (SYN) scan sends SYN and aborts with RST, never establishing the connection: stealthier and faster than a full-connect scan.
- A SYN flood is a flood of SYNs whose handshakes are never completed, exhausting the server's pending-connection table.
🧪 Practice
- Draw the full state diagram a TCP connection passes through from
SYN_SENTtoCLOSED, includingTIME_WAIT.- Run a SYN scan and a connect scan against the same host; use
ssor a capture to show which one leaves an established connection.- Explain why a closed port returns RST but a firewalled port returns nothing, and how a scanner distinguishes "closed" from "filtered".
- Interview-style: "How does a SYN flood exhaust a server, and how do SYN cookies defend against it without keeping per-connection state?" Hint: think about what the server must remember between the SYN and the final ACK, and how encoding that state into the sequence number removes the need to store it.
UDP and ICMP Behavior
Theory
Not every conversation needs TCP's reliability machinery. UDP (User Datagram Protocol) is the deliberately minimal alternative: no handshake, no sequence numbers, no acknowledgements, no connection state — just "send this datagram and hope it arrives." The trade is speed and simplicity for reliability, which is exactly right for DNS lookups, DHCP, VoIP, and streaming, where a lost packet is cheaper to ignore than to retransmit. The security consequences flow directly from the lack of a handshake: because there is no return-path verification, UDP source addresses are trivially spoofable, which makes UDP the workhorse of amplification/reflection DDoS (covered later) — a small spoofed request elicits a large reply aimed at the victim.
The absence of a handshake also changes how UDP ports are scanned. There is no SYN-ACK to confirm "open," so a scanner sends a datagram and interprets the lack of response as "open or filtered," while an ICMP port-unreachable reply means "closed." This makes UDP scanning slow and ambiguous, which is itself security-relevant: UDP services are often under-monitored precisely because they are harder to enumerate.
ICMP (Internet Control Message Protocol) is the network layer's signaling channel — it carries error and diagnostic messages, not application data. ping uses ICMP echo request/reply; traceroute relies on ICMP time-exceeded messages as TTL expires hop by hop; and "destination unreachable" messages report routing and port failures. ICMP is operationally essential, but it is also abused: ping sweeps for host discovery, ICMP tunneling to exfiltrate data inside echo payloads, and crafted messages to map or disrupt networks. The defensive tension is real — blocking ICMP entirely breaks Path MTU Discovery and useful diagnostics, so the mature approach is to rate-limit and filter specific ICMP types rather than drop all of it.
Examples
TCP vs UDP scan logic:
TCP SYN scan: SYN -> SYN/ACK = OPEN ; SYN -> RST = CLOSED
UDP scan: UDP -> (silence) = OPEN|FILTERED (ambiguous!)
UDP -> ICMP port-unreach = CLOSED
ICMP in traceroute (TTL expiry reveals each hop):
packet TTL=1 -> router1 decrements to 0 -> ICMP time-exceeded (reveals router1)
packet TTL=2 -> router2 ... -> ICMP time-exceeded (reveals router2)
... until the destination replies, mapping the full path.
nmap -sU -p 53,123,161 10.0.0.5 # UDP scan: DNS, NTP, SNMP (slow, ambiguous)
traceroute -I 93.184.216.34 # -I forces ICMP echo probes
# Rate-limit ICMP echo rather than dropping it wholesale (keeps diagnostics):
nft add rule inet filter input icmp type echo-request limit rate 5/second accept
Key Takeaways
- UDP is connectionless and minimal (no handshake, ordering, or acknowledgement): fast and simple, chosen for DNS, DHCP, VoIP, and streaming.
- No handshake means UDP source addresses are easily spoofed, making UDP the basis of amplification/reflection DDoS attacks.
- UDP scanning is slow and ambiguous: silence means "open or filtered," while an ICMP port-unreachable means "closed."
- ICMP is the network's signaling channel (ping, traceroute, unreachable messages) — essential for diagnostics but abused for discovery and tunneling.
- Do not blanket-block ICMP (it breaks Path MTU Discovery); rate-limit and filter specific types instead.
🧪 Practice
- Explain why a UDP scan cannot reliably distinguish "open" from "filtered," and what a scanner infers from silence versus an ICMP reply.
- Use
tracerouteand describe, per hop, which ICMP message type reveals each router.- Give two reasons UDP is preferred for DNS over TCP, and the one situation where DNS falls back to TCP.
- Interview-style: "Why is UDP, not TCP, the protocol of choice for reflection/amplification DDoS?" Hint: consider what TCP's handshake proves about the source address that UDP never checks.
DNS Resolution Flow
Theory
DNS (Domain Name System) is the internet's directory: it translates human-friendly names like example.com into the IP addresses machines route to. It matters enormously for security because it is a trust dependency for almost everything — if an attacker can make a victim resolve a name to the wrong address, they can redirect traffic without touching the victim's machine at all. Understanding the resolution flow tells you exactly where that redirection can happen.
Resolution is a hierarchical, delegated lookup. A client asks its recursive resolver (usually run by the ISP or a public service like 8.8.8.8) to find www.example.com. If the answer is not cached, the resolver walks the hierarchy: it asks a root server ("who handles .com?"), then the .com TLD server ("who handles example.com?"), then the authoritative server for example.com ("what is www?"), which returns the address. The resolver caches the result for the record's TTL and returns it to the client. The client's query is recursive (asks for the final answer); the resolver's queries are iterative (follows referrals).
Every step is a security surface. Classic DNS is unauthenticated UDP, so responses can be forged if an attacker guesses the query's transaction ID and source port before the real answer arrives — cache poisoning (detailed in Network Attacks). Records come in types that each carry risk: A/AAAA (addresses), CNAME (aliases — dangling CNAMEs enable subdomain takeover), MX (mail — tied to SPF/DKIM/DMARC), TXT (arbitrary text, used for domain verification and sometimes data exfiltration), and NS (delegation). The defenses layer on top of this flow: DNSSEC cryptographically signs records so forgery is detectable, and DoH/DoT encrypt the client-to-resolver query so it cannot be observed or tampered with in transit — both covered under Secure Communication Protocols.
Examples
Recursive resolution of www.example.com (cold cache):
client --recursive--> resolver
|-- iterative --> root server ("ask .com at x.x.x.x")
|-- iterative --> .com TLD ("ask example.com at y.y")
|-- iterative --> authoritative ("www = 93.184.216.34")
<-- cached for TTL, answer returned to client
dig +trace www.example.com # show the full delegation walk, root -> TLD -> auth
dig example.com MX # mail servers (ties into SPF/DKIM/DMARC)
dig example.com TXT # text records: domain verification, SPF policy
dig example.com +dnssec # request DNSSEC signatures (RRSIG records)
# A dangling CNAME is a takeover risk: it points to a decommissioned service.
dig sub.example.com CNAME
Key Takeaways
- DNS maps names to addresses through a hierarchical, delegated lookup: client → recursive resolver → root → TLD → authoritative server.
- The client query is recursive (wants the final answer); the resolver's queries are iterative (follows referrals); results are cached for their TTL.
- DNS is a universal trust dependency — redirecting a name resolution redirects traffic without touching the victim's host.
- Classic DNS is unauthenticated UDP and thus forgeable (cache poisoning); record types (A, CNAME, MX, TXT, NS) each carry distinct risks like subdomain takeover.
- DNSSEC signs records to make forgery detectable; DoH/DoT encrypt the query in transit — complementary, not interchangeable, defenses.
🧪 Practice
- Use
dig +traceto follow a domain's resolution and label each server (root, TLD, authoritative).- Explain the difference between a recursive and an iterative query and which party performs each.
- Describe how a dangling CNAME leads to subdomain takeover, and how you would detect one across a domain's records.
- Interview-style: "Why does DNSSEC protect integrity but not confidentiality, and what protocol complements it?" Hint: separate 'the answer is genuine' from 'nobody saw the question,' and match each to the right mechanism.
ARP and Layer 2 Operation
Theory
IP addresses route packets across networks, but within a single local network (one broadcast domain) delivery happens by MAC address at Layer 2. Something must translate "I want to send to IP 192.168.1.1" into "send to the device with MAC aa:bb:cc:...." That something is ARP (Address Resolution Protocol), and its design — built in an era that assumed a trusted LAN — is the root of a whole family of local-network attacks.
ARP works by broadcast question and unicast answer: a host that needs the MAC for an IP broadcasts "who has 192.168.1.1?" to the entire segment; the owner replies "that's me, here's my MAC"; the asker caches the mapping in its ARP table and uses it. The fatal flaw is that ARP is stateless and unauthenticated: a host will accept and cache an ARP reply even if it never asked, and it will believe whoever answers. This is ARP spoofing (or ARP cache poisoning): an attacker sends forged replies claiming the gateway's IP maps to the attacker's MAC, so victims send their traffic to the attacker — a Layer 2 man-in-the-middle (developed in Network Attacks).
The switch itself is attackable at Layer 2. A switch forwards frames using its CAM/MAC address table, which maps MACs to physical ports. The table is finite; flooding the switch with frames from thousands of fake source MACs — MAC flooding — can overflow it, forcing the switch to "fail open" and broadcast all frames to every port like a dumb hub, re-enabling eavesdropping that switching was supposed to prevent. Because all of this lives at Layer 2, it is confined to the local segment — but on that segment it is devastating, which is why defenses like Dynamic ARP Inspection and port security exist on managed switches.
Examples
Normal ARP vs ARP spoofing:
Normal: HostA broadcasts "who has 192.168.1.1 (gateway)?"
Gateway replies "192.168.1.1 is at AA:AA:AA" -> HostA caches truth
Spoofed: Attacker (unsolicited) -> HostA "192.168.1.1 is at EE:EE:EE"
Attacker (unsolicited) -> Gateway "192.168.1.x is at EE:EE:EE"
Now HostA <-> Attacker <-> Gateway (Layer 2 man-in-the-middle)
ip neigh show # the local ARP/neighbour table (IP -> MAC)
arp -a # same, classic tool
# A gateway whose MAC suddenly matches another host's MAC = spoofing signal:
ip neigh show | sort -k5 # group by MAC; duplicates across IPs are suspicious
# Switch-side defenses (managed switch CLI concept):
# port-security max 1 -> limit MACs per port (stops MAC flooding)
# ip arp inspection -> validate ARP replies against DHCP bindings
Key Takeaways
- Within a local segment, delivery is by MAC address at Layer 2; ARP translates IP addresses to MAC addresses via broadcast request and unicast reply.
- ARP is stateless and unauthenticated — hosts cache any reply, even unsolicited ones — which enables ARP spoofing (a Layer 2 man-in-the-middle).
- Switches forward using a finite CAM/MAC table; MAC flooding overflows it and forces the switch to broadcast like a hub, re-enabling sniffing.
- Layer 2 attacks are confined to the local broadcast domain but are severe within it.
- Defenses live on managed switches: Dynamic ARP Inspection validates replies against DHCP bindings; port security caps MACs per port.
🧪 Practice
- Inspect your ARP/neighbour table and identify which entry is the default gateway.
- Explain, step by step, how an attacker positions themselves between a victim and the gateway using forged ARP replies.
- Describe how MAC flooding degrades a switch to hub-like behavior and which switch feature prevents it.
- Interview-style: "Why is ARP spoofing impossible to launch from outside the local network, and what does that imply for where you place Layer 2 defenses?" Hint: recall that ARP is never forwarded by routers and operates only within one broadcast domain.
Common Ports and Services
Theory
A single IP host runs many services at once, so the transport layer needs a way to say which service a segment is for. That is the port number — a 16-bit label (0–65535) that, combined with the IP address, forms a socket (93.184.216.34:443) uniquely identifying one endpoint of one conversation. Knowing the common port-to-service mappings is foundational for both attack and defense: a scanner infers what a host is from the ports it exposes, and a defender's firewall policy is written almost entirely in terms of ports.
Ports fall into ranges by convention: well-known (0–1023, reserved for standard services and historically requiring privilege to bind), registered (1024–49151), and dynamic/ephemeral (49152–65535, used as the client's temporary source port). The security value of memorizing the common well-known ports is that an open port is a hypothesis about risk: port 23 (Telnet) open means cleartext administration; 445 (SMB) exposed to the internet is a notorious ransomware vector; 3389 (RDP) open invites brute-force and exploit attempts. The reverse is also true for defenders — an unexpected open port is one of the strongest signals of compromise or misconfiguration.
| Port | Service | Security note |
|---|---|---|
| 22 | SSH | secure admin; brute-force target, key auth preferred |
| 23 | Telnet | cleartext — should never be exposed |
| 25 / 587 | SMTP | mail; 587 submission; tied to SPF/DKIM/DMARC |
| 53 | DNS | UDP+TCP; poisoning and tunneling target |
| 80 / 443 | HTTP / HTTPS | web; 80 should redirect to 443 |
| 110 / 143 | POP3 / IMAP | mail retrieval; use TLS variants (995/993) |
| 135 / 139 / 445 | RPC / NetBIOS / SMB | Windows; 445 a major ransomware/worm vector |
| 161 | SNMP | device management; weak community strings leak data |
| 389 / 636 | LDAP / LDAPS | directory; 636 is TLS-protected |
| 3306 / 5432 | MySQL / PostgreSQL | databases — never expose to the internet |
| 3389 | RDP | remote desktop; brute-force and exploit magnet |
The deeper principle is attack surface minimization: every open port is a potential entry point, so the defensive baseline is to close or filter everything that is not explicitly required (default deny), and to put a firewall in front of the rest. A host's listening ports are therefore the first thing both an attacker and a defender enumerate.
Examples
# What is THIS host actually listening on? (the defender's first question)
ss -tulpn # TCP+UDP listening sockets with ports and process
# LISTEN 0.0.0.0:445 -> SMB exposed on all interfaces: investigate/close
# What is a REMOTE host exposing? (the attacker's/auditor's first question)
nmap -sV -p- 10.0.0.5 # all 65535 ports + service/version detection
nmap --top-ports 100 10.0.0.0/24 # the 100 most common ports across a subnet
# Service fingerprint from a banner (port implies service; banner confirms it):
nc -nv 10.0.0.5 22 # SSH banner reveals software and version
Interpreting a scan result as a risk hypothesis:
22/tcp open ssh -> admin access; check for key-only auth
445/tcp open smb -> HIGH RISK if internet-facing (ransomware/worms)
3389/tcp open rdp -> HIGH RISK; brute-force and CVE target
8080/tcp open http-alt -> unexpected? possible dev/debug service left running
Key Takeaways
- A port (0–65535) plus an IP forms a socket that uniquely identifies one endpoint; ports let one host run many distinguishable services.
- Ranges: well-known (0–1023), registered (1024–49151), ephemeral (49152–65535, client source ports).
- Each open port is a hypothesis about risk — an open 23/445/3389 signals cleartext admin, ransomware exposure, or brute-force surface.
- An unexpected open port is among the strongest indicators of compromise or misconfiguration.
- Attack surface minimization (default deny, close everything not required, firewall the rest) is the baseline defense; enumerating listening ports is step one for both sides.
🧪 Practice
- From memory, list the service and default port for SSH, HTTPS, DNS, SMB, RDP, and LDAPS.
- Run
ss -tulpnon a machine and justify why each listening service is needed, or should be closed.- Explain why exposing 3306 or 5432 to the internet is almost always a mistake, and the correct alternative.
- Interview-style: "You scan a server you believe is only a web server and find 80, 443, and 6379 open. What is your immediate concern?" Hint: recall what 6379 is and whether it typically authenticates by default.
Packet Capture and Analysis with Wireshark
Theory
Everything in this section — layers, handshakes, ARP, DNS — becomes concrete the moment you watch real packets. Packet capture is the practice of recording the raw frames crossing a network interface, and it is the single most important investigative skill in network security: it is ground truth. When logs disagree, documentation lies, or an attack is subtle, the packets do not lie. The core tools are tcpdump (command-line, ideal on servers and for scripting) and Wireshark (graphical, with deep protocol dissection and analysis), both built on the same libpcap capture library and the same BPF (Berkeley Packet Filter) syntax.
There are two distinct filtering stages, and confusing them is a common mistake. Capture filters (BPF syntax, e.g. tcp port 443) decide what gets recorded and are applied before storage — use them to limit volume on a busy link. Display filters (Wireshark's own richer syntax, e.g. http.request.method == "POST") decide what gets shown from an already-captured set and are far more expressive. The workflow is usually "capture broadly with a loose BPF filter, then analyze with precise display filters."
Capture only shows what reaches the interface, which is the central caveat: on a switched network you normally see only your own traffic plus broadcasts, so analysts use a SPAN/mirror port or network TAP to see others' traffic (or, as attackers, ARP spoofing to redirect it). The second caveat is encryption: TLS means you see the handshake and metadata (who, when, how much, SNI) but not the plaintext — which is exactly why metadata analysis and TLS fingerprinting matter. Analysis skills that pay off immediately include Follow TCP Stream (reassemble a full conversation from scattered packets), protocol dissectors (Wireshark decodes hundreds of protocols field by field), and statistics/IO graphs (spot scans, beaconing, and exfiltration by shape, not content).
Examples
# tcpdump: capture to a file with a BPF *capture* filter, then analyze later.
tcpdump -i eth0 -w capture.pcap 'tcp port 80 or tcp port 443'
# ^iface ^write file ^BPF: only web traffic is recorded
tcpdump -nr capture.pcap 'host 10.0.0.5 and tcp[tcpflags] & tcp-syn != 0'
# ^no DNS ^read file ^only SYN packets (handshake starts/scans)
# Headless capture for Wireshark analysis, rotating files to bound disk use:
tshark -i eth0 -b filesize:100000 -w ring.pcap # 100 MB ring buffer
Wireshark DISPLAY filters (richer than BPF, applied after capture):
http.request.method == "POST" show only HTTP POSTs
dns.flags.response == 0 show only DNS queries (not answers)
tcp.flags.syn == 1 && tcp.flags.ack == 0 bare SYNs (scan/flood indicator)
tls.handshake.extensions_server_name contains "example" SNI filter
ip.addr == 10.0.0.5 && tcp.analysis.retransmission trouble/odd flows
Key GUI moves:
Right-click a packet -> Follow -> TCP Stream (reassemble the conversation)
Statistics -> Conversations (top talkers; spot exfiltration)
Statistics -> I/O Graph (beaconing shows as regular spikes)
Key Takeaways
- Packet capture records raw frames on an interface and is ground truth — the most important investigative skill when logs and documentation are unreliable.
- tcpdump (CLI) and Wireshark (GUI) share libpcap and BPF; Wireshark adds deep dissection and analysis.
- Capture filters (BPF) decide what is recorded before storage; display filters (Wireshark syntax) decide what is shown afterward and are more expressive — capture broad, analyze precise.
- You only see traffic that reaches your interface: switched networks require a SPAN port or TAP (or, for attackers, ARP spoofing) to see others' traffic.
- TLS leaves only metadata visible (endpoints, timing, volume, SNI), not plaintext — making metadata analysis, Follow Stream, and statistics essential.
🧪 Practice
- Capture a DNS lookup and an HTTPS connection, then use display filters to isolate the DNS query and the TLS
ClientHellowith its SNI.- Write capture filters for: only traffic to one host, only SYN packets, only UDP port 53. Then write the equivalent display filters.
- Use "Follow TCP Stream" on a plaintext HTTP request and extract the full request and response.
- Interview-style: "On a switched network you plug in a laptop and capture, but see only your own traffic and broadcasts. Why, and what are your options to see more?" Hint: contrast a hub with a switch, and recall SPAN ports, TAPs, and the attacker's Layer 2 trick.
<a id="62-identification-and-authentication"></a>
6.2 Identification and Authentication
Authentication is the gate every other control depends on: access control, auditing, and accountability all assume you know who is acting. This section covers how identity is claimed and proven, the factors and protocols that prove it, and the attacks that target the weakest proof of all — the password.
Identification vs. Authentication vs. Authorization
Theory
These three words are used loosely in conversation but mean strictly different things, and security failures routinely trace to conflating them. The clean mental model is a sequence of three questions: identification answers "who do you claim to be?", authentication answers "can you prove it?", and authorization answers "what are you allowed to do?". They happen in that order, and each depends on the previous one being sound.
Identification is the assertion of an identity — typing a username, presenting an account number, inserting a card. It is just a claim; anyone can claim to be anyone, so identification alone grants nothing. Authentication is the proof that backs the claim — a password, a fingerprint, a cryptographic key — evaluated against something the system already knows. Only after authentication succeeds does the system treat the claimed identity as established. Authorization then decides what that established identity may do, and it is a separate decision governed by policy (the entire Access Control section that follows). A useful shorthand: identification is the subject of the sentence, authentication is the verb that proves it, authorization is the permissions that follow.
The reason to keep them distinct is that each fails differently and is attacked differently. A weak authentication mechanism (guessable password) lets an attacker prove a false claim. A broken authorization check lets a correctly-authenticated user do things they should not — the "broken access control" that tops web vulnerability lists, where the user is who they say they are but the system fails to restrict them. A fourth concept, accountability (or auditing), closes the loop: because actions are tied to an authenticated identity, they can be logged and attributed — which is why shared accounts are a security anti-pattern (they destroy attribution).
Examples
The three questions in order, with where each can fail:
IDENTIFICATION "I am alice" <- a claim; proves nothing
|
v
AUTHENTICATION "here is my password/key/fingerprint"
| <- weak factor => attacker proves a FALSE claim
v
AUTHORIZATION "alice may read /reports but not /admin"
<- broken check => REAL alice does forbidden things
|
v
ACCOUNTABILITY "alice deleted record 42 at 14:03" (log tied to identity)
# The order encoded in a login flow. Each stage is a distinct failure point.
def handle_request(claimed_user, credential, action, resource):
user = lookup(claimed_user) # IDENTIFICATION: resolve the claim
if user is None:
return deny("unknown identity")
if not verify_credential(user, credential): # AUTHENTICATION: prove it
return deny("authentication failed") # weak factor -> false proof
if not is_authorized(user, action, resource): # AUTHORIZATION: separate check
return deny("not permitted") # broken here -> real user, wrong access
audit_log(user, action, resource) # ACCOUNTABILITY: attributable
return perform(action, resource)
Key Takeaways
- Identification claims an identity, authentication proves it, authorization decides what the proven identity may do — in that strict order.
- Identification alone grants nothing; it is just a claim anyone can make.
- Weak authentication lets an attacker prove a false claim; broken authorization lets a genuine user exceed their permissions ("broken access control").
- Authorization is a separate, policy-driven decision — never assume authentication implies permission.
- Accountability depends on actions being tied to an authenticated identity, which is why shared accounts destroy attribution.
🧪 Practice
- Classify each as identification, authentication, or authorization: entering a username, scanning a fingerprint, a check that a user owns the record they are editing.
- Give a concrete scenario where authentication is perfect but authorization is broken, and describe the impact.
- Explain why shared service accounts undermine accountability, and one mitigation if they are unavoidable.
- Interview-style: "A user reports they can access another customer's invoice by changing the ID in the URL, even though they are logged into their own account. Which of the three concepts failed?" Hint: the user's identity was correctly established — so the failure is in the decision made after authentication.
Authentication Factors and Categories
Theory
If authentication is "prove your claim," the natural question is with what kind of evidence? The field organizes all evidence into a small number of factor categories, and the categorization matters because combining factors from different categories is what makes multi-factor authentication strong — two things of the same kind fail to the same attack.
The three classic categories are: something you know (a password, PIN, passphrase — knowledge), something you have (a phone, hardware token, smart card — possession), and something you are (a fingerprint, face, iris — inherence/biometric). Two modern additions are sometimes listed: somewhere you are (location/geofencing) and something you do (behavioral patterns like typing cadence), though these are usually treated as risk signals rather than primary factors.
| Category | Examples | Strength | Main weakness |
|---|---|---|---|
| Know | password, PIN, security question | weak alone | phishable, guessable, reusable, leaked in breaches |
| Have | phone (TOTP/push), hardware key, smart card | strong | can be lost, stolen, or (for SMS) SIM-swapped |
| Are | fingerprint, face, iris | convenient | not secret, not revocable, false accept/reject rates |
The crucial principle is that true multi-factor authentication requires factors from different categories. A password plus a security question is not MFA — both are "something you know," and both leak in the same data breach. A password (know) plus a hardware key (have) is genuine MFA, because compromising one does not compromise the other: the attacker must both steal your secret and physically possess your token. This is why the quality of MFA depends not just on how many factors but on their independence — and why phishing-resistant possession factors (FIDO2) are now preferred over phishable ones (SMS codes), as the later topics develop.
Examples
What is and is NOT multi-factor:
password + security question = ONE category (know+know) -> NOT MFA
password + SMS code = two categories (know+have) -> MFA (weak have)
password + hardware key tap = two categories (know+have) -> strong MFA
fingerprint + PIN on a phone = two categories (are+know) -> MFA
Rule: count CATEGORIES, not secrets. Same category = same breach kills both.
# Enforcing that MFA spans distinct categories, not just "two credentials".
CATEGORY = {"password": "know", "pin": "know", "security_q": "know",
"totp": "have", "hardware_key": "have", "sms": "have",
"fingerprint": "are", "face": "are"}
def is_true_mfa(methods):
cats = {CATEGORY[m] for m in methods} # collapse to distinct categories
return len(cats) >= 2 # MFA requires >= 2 CATEGORIES
# is_true_mfa(["password", "security_q"]) -> False (both 'know')
# is_true_mfa(["password", "hardware_key"]) -> True (know + have)
Key Takeaways
- Authentication evidence falls into categories: something you know, have, and are (plus the weaker somewhere-you-are and something-you-do).
- Knowledge factors are weakest (phishable, guessable, leaked in breaches); possession factors are stronger; inherence is convenient but not secret or revocable.
- True MFA requires factors from different categories — two of the same kind fail to the same attack.
- Password + security question is not MFA (both knowledge); password + hardware key is strong MFA.
- MFA strength depends on factor independence and phishing-resistance, not just the count.
🧪 Practice
- Categorize: a smart card, a memorized passphrase, a face scan, a one-time code texted to a phone.
- Explain why "password + security question" is single-factor despite requiring two inputs.
- Rank SMS code, TOTP app, and hardware security key as possession factors, with a reason for the ordering.
- Interview-style: "Why is a biometric a poor choice as the sole authentication factor for a high-value account?" Hint: consider revocability and secrecy — what happens after a fingerprint database is breached?
Password Storage, Policies, and Cracking Resistance
Theory
Passwords remain the most common authentication factor and the most commonly compromised, so how a system stores them is one of the highest-stakes decisions in applied security. The cardinal rule is simple and absolute: never store passwords in a recoverable form. Store a one-way transformation that lets you verify a password without being able to reproduce it, so that a database breach does not hand the attacker everyone's credentials.
The naive version — a plain cryptographic hash like SHA-256 — is not enough, for two reasons. First, identical passwords produce identical hashes, so an attacker can precompute hashes of common passwords (a rainbow table) and match them wholesale. The fix is a salt: a unique random value stored alongside each hash and mixed into it, so identical passwords hash differently and precomputation is defeated. Second, general-purpose hashes are fast, and fast is exactly wrong here — a GPU can compute billions of SHA-256 hashes per second, making brute force cheap. The fix is a slow, memory-hard password hashing function designed to be expensive: bcrypt, scrypt, and especially Argon2 (the modern recommendation) take a tunable work factor so you can keep each verification cheap for you but ruinously expensive to attack at scale. A pepper (a secret added to all hashes, stored separately from the database) adds a further layer by requiring the attacker to breach two stores.
Policy has shifted with the evidence. Modern guidance (NIST SP 800-63B) drops forced periodic rotation and arbitrary composition rules ("must contain a symbol"), because they push users toward predictable patterns (Password1! → Password2!) without improving entropy. Instead it favors length over complexity, screening candidate passwords against breach/blocklists of known-compromised values, allowing long passphrases and password managers, and rate-limiting attempts. Cracking resistance, then, is a product of three things: a slow salted hash (raises per-guess cost), high password entropy (raises the number of guesses needed), and rate limiting plus breach screening (removes the easy wins).
Examples
# Correct password storage with Argon2: slow, salted, memory-hard, tunable.
from argon2 import PasswordHasher
ph = PasswordHasher(time_cost=3, memory_cost=65536, parallelism=4) # tunable work
stored = ph.hash("correct horse battery staple") # salt is generated and embedded
# stored -> "$argon2id$v=19$m=65536,t=3,p=4$<salt>$<hash>" (self-describing)
def verify(stored, attempt):
try:
ph.verify(stored, attempt) # constant-time; raises on mismatch
return True
except Exception:
return False
# NEVER: store = sha256(password) -> fast + unsalted = cracked en masse
Why salting defeats precomputation, and work factor defeats brute force:
Unsalted SHA-256: sha256("password") is ALWAYS the same
-> one rainbow table cracks every user who chose "password"
Salted: argon2(salt_A, "password") != argon2(salt_B, "password")
-> precomputation is useless; each hash must be attacked individually
Work factor: GPU does ~10^9 SHA-256/s but only ~10^3 Argon2/s (tuned)
-> brute force slows by ~1,000,000x for the SAME password
Key Takeaways
- Never store passwords recoverably; store a one-way transform that verifies without reproducing.
- Plain fast hashes fail twice: no salt enables rainbow tables, and speed enables brute force.
- Salt (unique, per-password) defeats precomputation; a slow, memory-hard, tunable function (Argon2, bcrypt, scrypt) defeats brute force; a pepper adds a separately-stored secret.
- Modern policy (NIST 800-63B) favors length over complexity, drops forced rotation and composition rules, and screens against breach/blocklists.
- Cracking resistance combines slow salted hashing, high entropy, and rate-limiting plus breach screening.
🧪 Practice
- Explain, with an example, how a salt defeats a rainbow table and why a per-user salt is required.
- Compare SHA-256, bcrypt, and Argon2 for password storage and justify which you would choose for a new system.
- Argue for or against forced 90-day password rotation using NIST SP 800-63B's reasoning.
- Interview-style: "A breached database used salted SHA-256. Is that adequate, and what would you change?" Hint: a salt fixes precomputation but not speed — think about what still makes GPU brute force cheap here.
Challenge-Response Protocols
Theory
Sending a password across a network — even a hashed one — has a fatal weakness: anyone who observes it can replay it to authenticate later. Challenge-response protocols exist to prove you know a secret without ever transmitting it, and to make each proof usable exactly once. The core idea is that the verifier sends a fresh, unpredictable challenge (a nonce), and the prover returns a response computed from both the challenge and the shared secret. The verifier, knowing the same secret, computes the expected response and compares. The secret never crosses the wire, and because the challenge changes every time, a captured response is worthless for the next login.
The essential ingredient is the nonce ("number used once") — a value that is fresh for every exchange. Its freshness is what provides replay protection: even if an attacker records a complete valid response, it was bound to a challenge that will never be issued again, so replaying it fails. This is the same principle that underlies TOTP (challenge = current time), CRAM/SCRAM in mail and databases, Kerberos (timestamps and tickets), and the WPA2 4-way handshake — all are challenge-response variants.
A subtlety that separates good designs from broken ones is who issues the challenge and whether both sides are authenticated. A one-way protocol (server challenges client) proves the client knows the secret but lets a fake server harvest responses; mutual challenge-response has each side challenge the other, defeating impersonation of the server too. Designs must also avoid letting the attacker choose the challenge in a way that enables precomputation, and should bind the response to session context to prevent relaying it to a different connection (a reflection or relay attack). The payoff of getting this right is large: the secret is never exposed, replay is prevented, and — unlike sending a password — a passive eavesdropper learns nothing reusable.
Examples
Basic challenge-response (secret never transmitted, replay defeated):
Client Server
| --- "I am alice" ------------------> |
| <-- challenge: nonce=0x9f3a2c ------ | (fresh, unpredictable)
| response = HMAC(secret, nonce) |
| --- response ----------------------> |
| server computes HMAC(secret, nonce)
| and compares -> grant/deny
Next login uses a NEW nonce, so a captured response cannot be replayed.
# One round of challenge-response with HMAC. The secret stays on each side.
import hmac, hashlib, os
def server_issue_challenge():
return os.urandom(16) # fresh nonce per attempt (replay defense)
def client_respond(secret, nonce):
return hmac.new(secret, nonce, hashlib.sha256).digest() # bind secret+nonce
def server_verify(secret, nonce, response):
expected = hmac.new(secret, nonce, hashlib.sha256).digest()
return hmac.compare_digest(expected, response) # constant-time compare
# Because `nonce` differs every time, a recorded `response` is useless later.
Key Takeaways
- Challenge-response proves knowledge of a secret without transmitting it, and makes each proof single-use.
- The verifier sends a fresh nonce; the prover returns a response derived from the nonce and the secret; the secret never crosses the wire.
- The nonce's freshness provides replay protection — a captured response is bound to a challenge that will never recur.
- Mutual challenge-response authenticates both parties, defeating server impersonation that one-way designs allow.
- The pattern underlies TOTP, CRAM/SCRAM, Kerberos, and the WPA2 handshake; bind responses to session context to prevent relay/reflection.
🧪 Practice
- Explain why sending a password hash over the network is still replayable, and how a nonce fixes it.
- Trace one round of HMAC challenge-response and identify exactly which value prevents replay.
- Describe an attack that one-way challenge-response allows but mutual challenge-response prevents.
- Interview-style: "In a challenge-response scheme, why must the challenge be unpredictable and not merely unique?" Hint: consider an attacker who can make the client respond to a challenge of the attacker's choosing ahead of time.
Multi-Factor Authentication Methods
Theory
Multi-factor authentication (MFA) exists because single-factor authentication — usually a password — fails constantly: passwords are phished, reused, guessed, and leaked in bulk. MFA's defense is layering: require evidence from more than one category (from the factors topic) so that compromising one factor is not enough. The attacker who phishes your password still cannot log in without your second factor, and the attacker who steals your phone still cannot log in without your password. This simple idea blocks the overwhelming majority of account-takeover attacks, which is why MFA is the single highest-leverage control most organizations can deploy.
Not all MFA is equal, and the differences are about phishing resistance and the strength of the possession factor. The methods form a clear hierarchy:
| Method | Category | Phishing resistant? | Notes |
|---|---|---|---|
| SMS one-time code | have (weak) | No | SIM-swappable, interceptable; better than nothing |
| TOTP app (authenticator) | have | No (replayable to a proxy) | shared-secret, offline; good baseline |
| Push approval | have | Partially | vulnerable to MFA fatigue/bombing |
| Push with number matching | have | Mostly | defeats blind approval |
| Hardware key / passkey (FIDO2) | have | Yes | origin-bound; phishing-proof by design |
The decisive concept is phishing resistance. SMS, TOTP, and plain push all share a fatal gap: a convincing fake login page can relay whatever the user enters or approves to the real site in real time (an adversary-in-the-middle proxy like Evilginx). The user's second factor is valid, and the attacker captures the resulting session. FIDO2/WebAuthn closes this gap by binding the authentication to the website's actual origin cryptographically — the hardware key simply will not produce a valid response for the wrong domain, so the phishing page gets nothing. This is why security guidance now distinguishes "MFA" from "phishing-resistant MFA" and pushes high-value accounts toward the latter. A second practical concern is MFA fatigue (or "push bombing"): spamming a user with approval prompts until they tap "approve" out of annoyance — mitigated by number matching and rate limits.
Examples
Why TOTP/push are phishable but FIDO2 is not (AiTM proxy):
TOTP/push: user -> [phish proxy] -> real site
user types code into phish; proxy forwards it live; site accepts;
proxy steals the session cookie. SECOND FACTOR DID NOT HELP.
FIDO2: the key signs a challenge BOUND TO THE ORIGIN it sees.
phish origin = "evil.example" != real origin "bank.example"
-> signature is for the wrong origin -> real site REJECTS it.
Phishing proxy cannot forge the origin. PHISHING FAILS.
# Step-up/adaptive MFA: require a stronger factor for riskier actions.
def required_factors(user, action, risk_score):
base = ["password"]
if action == "login" and risk_score < 30:
return base + ["totp"] # normal login: password + TOTP
if action in ("wire_transfer", "change_email") or risk_score >= 70:
return base + ["fido2"] # high value -> phishing-resistant
return base + ["push_number_match"] # middle ground: push w/ matching
Key Takeaways
- MFA requires evidence from more than one factor category, so compromising one factor is insufficient — blocking most account takeovers.
- Methods form a strength hierarchy: SMS (weak) < TOTP ≈ plain push < push with number matching < FIDO2/passkeys.
- Phishing resistance is the decisive property: SMS, TOTP, and plain push are all relayable through an adversary-in-the-middle proxy.
- FIDO2/WebAuthn binds authentication to the site's real origin, so phishing pages cannot obtain a usable response.
- Watch for MFA fatigue/push bombing; mitigate with number matching and rate limits, and step up to stronger factors for high-risk actions.
🧪 Practice
- Rank SMS, TOTP, push, and FIDO2 by phishing resistance and explain the reason for the top and bottom.
- Describe how an adversary-in-the-middle proxy defeats TOTP but fails against a hardware key.
- Explain MFA fatigue and two concrete mitigations.
- Interview-style: "Your users have TOTP MFA but are still being compromised via phishing. What changed in the attack, and what should you deploy?" Hint: the attacker is no longer stealing a password alone — think about real-time relaying and origin binding.
TOTP, HOTP, and Push Authentication
Theory
These are the mechanics behind the most common app-based second factors, and they are all elegant applications of challenge-response. HOTP (HMAC-based One-Time Password, RFC 4226) and TOTP (Time-based OTP, RFC 6238) both start from a secret shared once between the server and your authenticator app (delivered as the QR code you scan at setup). From that shared secret, each side independently computes a short code using HMAC, so the code can be generated offline and verified without any network round trip — the "challenge" is implicit.
The two differ only in what the HMAC is computed over. HOTP uses a counter that increments each time you generate a code; the server tracks the counter and accepts the next expected value (with a small look-ahead window for drift). TOTP uses the current time divided into fixed steps (typically 30 seconds) as the counter, which is why TOTP codes expire and refresh on a timer and why clock skew between phone and server must be tolerated with a small window of adjacent time steps. TOTP is far more common because there is nothing to desynchronize as long as clocks are roughly aligned. The security properties: the codes are one-time (replay-resistant within their window), the secret never leaves the device after setup, and generation is offline — but the shared secret is symmetric, so a server breach that leaks the secret lets an attacker generate codes, and the code is still phishable (a proxy can relay the 6 digits in real time), as the MFA topic warned.
Push authentication replaces typing a code with approving a prompt: the server sends a notification to a registered app, and you tap approve or deny. It is more usable and lets the server include rich context (location, app, time), but it introduced MFA fatigue — attackers spam approvals hoping for a reflexive tap. The fix is number matching: the login screen shows a number the user must enter into the app, proving they are actually looking at the genuine login attempt rather than blindly approving.
Examples
# TOTP generation (RFC 6238): time-stepped HMAC truncated to 6 digits.
import hmac, hashlib, struct, time, base64
def totp(secret_b32, step=30, digits=6, t=None):
key = base64.b32decode(secret_b32)
counter = int((t or time.time()) // step) # TIME is the counter
msg = struct.pack(">Q", counter) # 8-byte big-endian counter
h = hmac.new(key, msg, hashlib.sha1).digest() # HMAC-SHA1 (RFC default)
off = h[-1] & 0x0F # dynamic truncation offset
code = (struct.unpack(">I", h[off:off+4])[0] & 0x7FFFFFFF) % (10 ** digits)
return str(code).zfill(digits) # e.g. "492817"
# HOTP is identical but `counter` is an incrementing event count, not time.
Verification tolerates drift with a small window; number matching stops fatigue:
TOTP verify: accept code for step N-1, N, N+1 (clock skew tolerance)
HOTP verify: accept counters C .. C+look_ahead (missed presses tolerance)
Push WITHOUT number matching: "Approve login? [Approve] [Deny]" <- spammable
Push WITH number matching: "Enter 47 shown on your login screen"
attacker who triggered the push does NOT see 47 -> cannot approve
Key Takeaways
- HOTP and TOTP derive a short code from a shared secret via HMAC, computed offline on both sides — an implicit challenge-response.
- HOTP's counter is an incrementing event count; TOTP's is the current time in fixed steps (usually 30s), so TOTP codes expire and need clock-skew tolerance.
- Verification uses a small window (adjacent time steps or a counter look-ahead) to absorb drift and missed presses.
- The shared secret is symmetric: a server-side breach of it lets an attacker generate codes, and the code is still phishable via real-time relay.
- Push is more usable but enabled MFA fatigue; number matching defeats blind approval by proving the user sees the genuine attempt.
🧪 Practice
- State the single difference between HOTP and TOTP, and explain why TOTP needs a time window during verification.
- Explain why a TOTP secret leak is more damaging than a leaked single code.
- Describe MFA fatigue against push and exactly how number matching prevents it.
- Interview-style: "Both server and app compute the same TOTP without communicating. How, and what must stay synchronized?" Hint: they share a secret at setup and both derive the counter from the same external value.
FIDO2, WebAuthn, and Passkeys
Theory
FIDO2 is the answer to the phishing problem that defeats every shared-secret factor. Its central insight is to replace shared secrets with public-key cryptography and to bind every authentication to the website's origin, so that a credential created for bank.example is cryptographically useless on evil.example. This is what makes FIDO2 phishing-resistant by design rather than by user vigilance — the mechanism refuses to produce a valid signature for the wrong site, no matter how convincing the fake looks.
The pieces fit together as follows. WebAuthn is the browser/web API (a W3C standard) that web apps call; CTAP is the protocol between the browser and an authenticator (a hardware key like a YubiKey, or a platform authenticator built into your phone or laptop); together these form FIDO2. At registration, the authenticator generates a new key pair unique to that site, keeps the private key (never exported), and sends the public key to the server. At login, the server sends a challenge; the authenticator signs it with the private key along with the origin the browser reports, and typically requires a local user gesture (touch, biometric) to unlock. The server verifies the signature against the stored public key. Because the private key never leaves the device and the signature is origin-bound, there is no secret to phish, no password to reuse, and no database of shared secrets to breach.
Passkeys are FIDO2 credentials made consumer-friendly: a discoverable credential (the authenticator stores which accounts it holds, so you need no username) that is typically synced across your devices through a platform cloud (Apple iCloud Keychain, Google Password Manager). This solves FIDO2's historical usability problems — device loss and per-device enrollment — by making the credential portable, at the cost of trusting the sync provider. The trade-off is deliberate: device-bound passkeys (on a hardware key) are the strongest and never leave the device; synced passkeys trade a little of that assurance for recoverability and mass adoption. Either way, the phishing resistance and "no shared secret" properties remain.
Examples
Why FIDO2 is phishing-proof (origin binding at signing time):
Registration (per site): authenticator makes keypair for "bank.example"
private key stays on device; public key -> server stores it.
Login: server -> challenge
authenticator signs (challenge + ORIGIN the browser reports + ...)
on phish "evil.example": signed origin != "bank.example"
-> server's verification FAILS. Nothing reusable is captured.
user gesture (touch/biometric) unlocks the private key locally.
// WebAuthn login (simplified): the browser enforces origin binding for you.
const assertion = await navigator.credentials.get({
publicKey: {
challenge: serverChallenge, // fresh, server-generated (anti-replay)
allowCredentials: [{ id: credId, type: "public-key" }],
userVerification: "required", // require local gesture (touch/biometric)
},
});
// The authenticator signs over challenge + the REAL origin the browser saw.
// A phishing origin cannot be forged here, so the server's signature check fails.
sendToServer(assertion); // server verifies with the stored public key
Key Takeaways
- FIDO2 replaces shared secrets with public-key crypto and binds each authentication to the site's origin, making it phishing-resistant by design.
- WebAuthn is the web API, CTAP the browser-to-authenticator protocol; together they are FIDO2. The private key never leaves the authenticator.
- Registration creates a per-site key pair (public key to server); login signs a server challenge plus the origin, gated by a local user gesture.
- There is no shared secret to phish, reuse, or breach server-side — the strongest widely-deployed consumer authentication.
- Passkeys are discoverable, often synced FIDO2 credentials that trade some device-bound assurance for recoverability and usability; device-bound keys remain strongest.
🧪 Practice
- Explain precisely why a FIDO2 credential registered for one domain cannot be used by a phishing site.
- Contrast a device-bound passkey on a hardware key with a synced passkey, listing one advantage of each.
- Describe what the server stores after registration and what it verifies at login.
- Interview-style: "FIDO2 and TOTP both use a 'challenge.' Why is only FIDO2 phishing-resistant?" Hint: ask what the response is bound to in each — a time value the proxy can relay, versus the origin the proxy cannot forge.
Biometric Authentication and Error Rates
Theory
Biometrics authenticate by measuring a physical or behavioral trait — fingerprint, face, iris, voice — rather than a secret you know or a token you hold. Their appeal is usability: nothing to remember or carry, and the trait is always with you. But the same property that makes them convenient makes them fundamentally different from passwords in two ways that drive every security consideration: biometrics are probabilistic, not exact, and they are not revocable.
"Probabilistic" means a biometric system never gets an identical reading twice — lighting, angle, moisture, and aging all vary — so it cannot demand an exact match; it measures similarity against a threshold. That threshold creates two kinds of error, and they trade off against each other: the False Acceptance Rate (FAR) is how often an impostor is wrongly accepted (a security failure), and the False Rejection Rate (FRR) is how often the legitimate user is wrongly rejected (a usability failure). Tightening the threshold lowers FAR but raises FRR, and vice versa; the Crossover Error Rate (CER / EER), where the two are equal, is the standard single-number measure of a system's accuracy — lower is better. A fourth metric, the Failure to Enroll Rate, captures users whose trait cannot be captured at all.
The non-revocability point is the deeper security concern. If a password leaks you change it; if your fingerprint template leaks you cannot grow a new finger. This means biometric templates must be protected like the crown jewels (stored as irreversible transforms, ideally in secure hardware like a TEE/Secure Enclave, never as raw images), and it argues against biometrics as a sole factor for high-value access. Biometrics are also vulnerable to presentation (spoofing) attacks — lifted fingerprints, photos, masks, voice clones — which is why liveness detection (checking the trait comes from a live person) is essential. The mature design treats a biometric as a convenient local unlock for a stronger stored credential (as in FIDO2 platform authenticators and phone unlock), not as a secret transmitted across a network.
Examples
FAR/FRR trade-off as the threshold moves:
loose threshold ------------------ strict threshold
FAR high (impostors get in) FAR low (secure)
FRR low (users rarely rejected) FRR high (users frustrated)
\ /
CER (EER): FAR == FRR <- the accuracy benchmark
Security context -> accept higher FRR to drive FAR down.
Convenience context -> the reverse.
# A biometric match is a similarity comparison against a threshold, not equality.
def biometric_accept(live_template, stored_template, threshold):
score = similarity(live_template, stored_template) # 0..1, never exactly 1
# Raise threshold -> fewer impostors (lower FAR) but more false rejects (FRR)
return score >= threshold
# Store stored_template as an irreversible transform in secure hardware (TEE),
# NEVER the raw image: a leaked raw biometric cannot be revoked or reissued.
Key Takeaways
- Biometrics measure a trait, not a secret; matching is probabilistic (similarity vs. a threshold), never exact.
- FAR (impostor accepted) is a security error; FRR (legitimate user rejected) is a usability error; they trade off as the threshold moves.
- The Crossover/Equal Error Rate (where FAR = FRR) is the standard accuracy benchmark — lower is better.
- Biometrics are not revocable: a leaked template cannot be reissued, so templates must be stored as irreversible transforms in secure hardware.
- Guard against presentation/spoofing attacks with liveness detection; prefer biometrics as a local unlock for a stronger credential, not a sole or network-transmitted factor.
🧪 Practice
- Define FAR, FRR, and CER, and state which you would prioritize lowering for a high-security door.
- Explain why a leaked biometric template is worse than a leaked password, and two mitigations.
- Describe a presentation attack against face recognition and how liveness detection counters it.
- Interview-style: "Why do modern phones use your fingerprint to unlock a key rather than sending the fingerprint to the server?" Hint: think about non-revocability and keeping the trait local to secure hardware.
Certificate-Based and Token-Based Authentication
Theory
Passwords and OTPs authenticate a human at a login prompt, but a great deal of authentication is machine-to-machine or must persist across many requests without re-prompting. Two mechanisms dominate here: certificate-based authentication (proving identity with a private key backed by a trusted certificate) and token-based authentication (presenting a signed, short-lived credential issued after an initial login). Both avoid sending a reusable secret on every request, which is their shared security advantage.
Certificate-based authentication applies the public-key machinery of PKI (from the cryptography chapter) to identity. The entity holds a private key and an X.509 certificate in which a trusted Certificate Authority (CA) attests "this public key belongs to this identity." To authenticate, the entity proves possession of the private key (by signing a challenge), and the verifier trusts the binding because it trusts the CA that signed the certificate — the same trust-chain model as TLS server certificates, but used for client identity. This is the strongest common machine credential: there is no shared secret, the private key never travels, and it is the basis of mutual TLS (mTLS) between services, smart-card/PIV login, and device identity. Its costs are operational: issuing, distributing, rotating, and especially revoking certificates (CRLs/OCSP) is real work.
Token-based authentication solves a different problem: after a user authenticates once, how do subsequent requests prove it without re-sending credentials? The server issues a token — classically an opaque session ID stored server-side, or a self-contained JWT (JSON Web Token) that carries claims (who, what scope, when it expires) and is signed by the server so it cannot be forged or altered. The client presents the token on each request; the server validates the signature/expiry and trusts the claims. OAuth 2.0 standardizes how such tokens are obtained and delegated (letting an app act on a user's behalf without seeing their password). The key security properties and pitfalls: tokens should be short-lived (limiting the damage of theft) with refresh tokens for renewal; a stolen bearer token is usable by anyone who holds it (hence transport must be encrypted and storage protected); and JWTs must be validated carefully — verifying the signature, the algorithm (reject alg: none), the issuer, audience, and expiry.
| Certificate-based | Token-based | |
|---|---|---|
| Proof | possession of private key (signs challenge) | presentation of a signed token |
| Secret on wire | none (key never sent) | the token itself (bearer) |
| Typical use | mTLS, smart cards, device identity | web/API sessions, OAuth, SSO |
| Main risk | key compromise; revocation complexity | token theft; weak JWT validation |
Examples
Certificate-based (mTLS) vs token-based (JWT) authentication:
mTLS: client presents cert + signs challenge with private key
server verifies cert chains to a trusted CA, and the signature
-> identity proven WITHOUT any shared secret on the wire.
JWT: login once -> server issues header.payload.signature
header {"alg":"RS256","typ":"JWT"}
payload {"sub":"alice","scope":"read","exp":1735689600}
signature = Sign(server_key, header.payload) <- forgery-proof
client sends token each request; server verifies signature + exp.
# JWT validation: the checks that matter (skipping any of these is a CVE).
import jwt # PyJWT
def validate(token, public_key):
return jwt.decode(
token, public_key,
algorithms=["RS256"], # PIN the algorithm: never allow "none"
audience="api.example.com", # token was minted for THIS service
issuer="auth.example.com", # from the expected issuer
options={"require": ["exp", "iat"], "verify_signature": True},
) # raises on bad signature, wrong aud/iss, or expiry -> reject the request
Key Takeaways
- Certificate-based and token-based authentication both avoid sending a reusable secret on every request — the shared advantage over passwords.
- Certificate-based uses PKI: a CA-signed X.509 cert binds a public key to an identity; the holder proves possession of the private key. Strongest machine credential (mTLS, smart cards), but revocation is operationally hard.
- Token-based issues a credential after initial login: an opaque session ID or a self-contained, signed JWT carrying claims; OAuth 2.0 standardizes issuance and delegation.
- Bearer tokens are usable by anyone holding them — keep them short-lived, transport them over TLS, and protect storage.
- Validate JWTs rigorously: verify signature, pin the algorithm (reject
alg: none), and check issuer, audience, and expiry.
🧪 Practice
- Explain how certificate-based authentication proves identity without sending a secret, and the role of the CA.
- Decode a JWT's three parts and identify which fields you must validate and why.
- Describe the
alg: noneJWT attack and the single-line fix.- Interview-style: "Why are bearer tokens kept short-lived, and what role do refresh tokens play?" Hint: consider what an attacker gains from a stolen token and how expiry bounds the window while preserving usability.
Credential Stuffing and Password Spraying
Theory
These are the two dominant scaled password attacks, and they are effective precisely because they sidestep the defenses built for classic brute force. Both exploit human behavior rather than cryptographic weakness, which is why strong hashing alone does nothing to stop them — the attacker is not cracking hashes, they are trying real passwords at the login endpoint.
Credential stuffing weaponizes password reuse. Billions of username/password pairs have leaked from past breaches and are freely traded; attackers simply replay these pairs against other, unrelated services, betting that a fraction of users reused the same password. The hit rate per site is low (often under 1%), but at the scale of millions of leaked pairs that still yields many compromised accounts, automatically. Crucially, each attempt uses a correct password for some service, so from the target's view it looks like a lot of failed logins across many accounts — and any success is a genuine credential, not a guess.
Password spraying inverts the usual brute-force shape to evade lockouts. Standard brute force tries many passwords against one account, which trips account-lockout policies fast. Spraying instead tries one common password (e.g. Winter2025!) against many accounts, then waits and tries the next common password. Because each account sees only one or two attempts, lockout thresholds are never reached, and the attack stays under the radar. Both attacks share detection signatures — a surge of failed logins, many source IPs (botnets/proxies), distributed across accounts — and share defenses: MFA (the single most effective, since a correct password alone is then useless), breach-password screening (reject known-compromised passwords at signup), rate limiting and anomaly detection per IP and per account, CAPTCHA/bot management, and monitoring for impossible-travel and credential-reuse patterns. Lockout policies help against single-account brute force but are ineffective against spraying (too few attempts per account) and can even enable denial-of-service by locking out real users — a reason to prefer intelligent rate limiting over blunt lockouts.
Examples
The two attack shapes (and why lockout misses spraying):
Classic brute force: 1 account x many passwords -> trips lockout fast
Credential stuffing: many (user,pass) leaked pairs -> replayed as-is
Password spraying: 1 common password x many accounts, slowly
each account sees ~1 attempt -> UNDER lockout threshold
# Detection heuristic: spraying/stuffing shows as breadth, not depth.
from collections import defaultdict
def looks_like_spraying(failed_logins, window_min=60, account_threshold=50):
# failed_logins: list of (timestamp, account, source_ip, password_tried)
per_password = defaultdict(set)
for ts, account, ip, pw in failed_logins:
per_password[pw].add(account) # how many DISTINCT accounts per pw?
# One password attempted against many accounts = spraying signature.
return any(len(accts) >= account_threshold for accts in per_password.values())
# Defenses that actually work: MFA, breach-password screening, per-IP +
# per-account rate limiting, bot management -- NOT just account lockout.
Key Takeaways
- Credential stuffing replays leaked username/password pairs across other sites, exploiting password reuse; hit rates are low but scale makes it profitable.
- Password spraying tries one common password against many accounts to stay under per-account lockout thresholds.
- Both exploit human behavior, not crypto, so strong hashing is irrelevant to stopping them — the attacker uses real passwords at the login endpoint.
- MFA is the single most effective defense (a correct password alone becomes useless); add breach-password screening, rate limiting, anomaly detection, and bot management.
- Account lockout stops single-account brute force but misses spraying and can itself cause denial-of-service — prefer intelligent rate limiting.
🧪 Practice
- Explain the structural difference between credential stuffing and password spraying and why each evades classic brute-force defenses.
- Describe why account lockout is ineffective against spraying and how it can backfire.
- List four defenses and rank them by effectiveness against credential stuffing.
- Interview-style: "Your logs show thousands of failed logins, mostly one attempt per account, from hundreds of IPs. Which attack is this and what is your first mitigation?" Hint: the 'one attempt per account' detail names the attack, and the most decisive fix makes a correct password insufficient.
Kerberos Authentication Flow
Theory
Kerberos is the authentication protocol at the heart of Windows Active Directory and many Unix realms, and it solves a hard problem: letting a user authenticate once and then access many services across a network without sending their password to any of them. Its design is a sophisticated application of the challenge-response and symmetric-crypto ideas already covered, built around a trusted third party and time-stamped tickets. The guiding metaphor is a theme park: you prove your identity once at the entrance, get a wristband, and then show the wristband at each ride instead of re-proving who you are.
The trusted third party is the Key Distribution Center (KDC), which has two parts: the Authentication Service (AS) and the Ticket-Granting Service (TGS). The flow has three exchanges. First, the user authenticates to the AS (proving knowledge of their password-derived key) and receives a Ticket-Granting Ticket (TGT) — the wristband — encrypted with the KDC's secret so the user cannot read or forge it. Second, to reach a specific service, the user presents the TGT to the TGS and receives a service ticket for that service. Third, the user presents the service ticket to the actual service, which decrypts it with its own key and grants access. The user's password is used only once, locally, to derive a key — it never crosses the network, and neither does any reusable secret. Timestamps in the tickets provide replay protection (tickets expire), which is why Kerberos requires reasonably synchronized clocks across the realm.
Kerberos is also a rich attack surface precisely because tickets are long-lived, offline-crackable artifacts. Kerberoasting requests service tickets for accounts and cracks them offline to recover service-account passwords (service tickets are encrypted with the service account's key, so a weak key cracks). AS-REP roasting targets accounts with pre-authentication disabled. Golden tickets forge TGTs after compromising the KDC's master key (krbtgt hash), granting near-unlimited, long-lived access; silver tickets forge service tickets for a single service. These attacks define much of Active Directory offense and are why protecting the krbtgt key and using strong service-account passwords are critical.
Examples
The three Kerberos exchanges (password never sent; tickets are the currency):
1. AS-REQ/REP: user --(proof from password-derived key)--> AS
AS --> TGT (encrypted with KDC key; user can't forge it)
2. TGS-REQ/REP: user --(TGT + "I want service HTTP/web")--> TGS
TGS --> service ticket for that service
3. AP-REQ: user --(service ticket)--> the service
service decrypts with ITS key -> grants access
Timestamps inside tickets => expiry => replay protection (clocks must sync).
Why tickets are an attack surface:
Kerberoasting : request service tickets -> crack offline -> service password
(service ticket is encrypted with service account's key)
AS-REP roast : accounts w/ pre-auth OFF -> crackable material without creds
Golden ticket : steal krbtgt hash -> FORGE any TGT -> domain-wide, long-lived
Silver ticket : steal one service key -> forge tickets for that one service
Defense: strong service-account passwords; guard the krbtgt key; rotate it.
Key Takeaways
- Kerberos provides single sign-on across a network without sending the user's password to any service, using a trusted KDC and time-stamped tickets.
- The KDC has an Authentication Service (issues the Ticket-Granting Ticket) and a Ticket-Granting Service (issues per-service tickets).
- Flow: authenticate once to the AS → get a TGT → exchange the TGT at the TGS for a service ticket → present it to the service.
- Timestamps give replay protection and ticket expiry, which is why Kerberos requires synchronized clocks.
- Tickets are offline-crackable artifacts: Kerberoasting and AS-REP roasting recover account passwords; golden/silver tickets forge tickets after key compromise — protect the
krbtgtkey and use strong service-account passwords.
🧪 Practice
- List the three Kerberos exchanges in order and state what the user receives from each.
- Explain why the user's password never traverses the network and what replaces it.
- Describe Kerberoasting and why strong service-account passwords defeat it.
- Interview-style: "Why does a compromised
krbtgthash lead to a 'golden ticket' and near-total domain compromise?" Hint: recall which key encrypts the TGT and what forging a TGT lets an attacker claim.
RADIUS, LDAP, and Directory Services
Theory
In any organization larger than a handful of users, authentication must be centralized — you cannot manage credentials separately on every switch, VPN, and server. Directory services and AAA protocols provide that central source of truth and the means for devices to query it. Understanding them means understanding the difference between where identity data lives (the directory) and how a device asks whether a login should succeed (the AAA protocol).
LDAP (Lightweight Directory Access Protocol) is the standard protocol for querying and modifying a directory — a hierarchical database of users, groups, computers, and their attributes, organized as a tree of entries identified by Distinguished Names (e.g. cn=alice,ou=staff,dc=example,dc=com). Microsoft Active Directory is the dominant implementation (it speaks LDAP and layers Kerberos on top). Applications authenticate a user against LDAP by a bind operation — attempting to connect as that user with their password; a successful bind means the password is correct. The critical security point: plain LDAP is cleartext, so bind credentials must be protected with LDAPS (LDAP over TLS, port 636) or StartTLS, and application code that builds LDAP queries from user input is vulnerable to LDAP injection (the same class as SQL injection).
RADIUS (Remote Authentication Dial-In User Service) is the classic AAA protocol — Authentication (who are you?), Authorization (what may you do?), and Accounting (what did you do, for logging/billing?). It is what a VPN concentrator, Wi-Fi access point (via 802.1X), or network switch uses to ask a central server "should this login succeed, and what access should it get?" rather than holding credentials itself. RADIUS has known weaknesses — it only encrypts the password field (not the whole packet) and runs over UDP — so modern deployments often use RADIUS over TLS (RadSec) or its successor Diameter. The division of labor is the key mental model: the directory (LDAP/AD) stores identities and policy; RADIUS mediates a device's real-time access question, usually by checking against that same directory behind the scenes. Centralization is a double-edged sword: it makes management and revocation instant and consistent, but it also makes the directory the crown jewel — compromise of Active Directory is effectively compromise of the entire organization, which is why directory security dominates enterprise defense.
Examples
Who does what (store vs. mediate):
[ Switch / VPN / Wi-Fi AP ] --RADIUS--> [ RADIUS server ] --LDAP--> [ AD / directory ]
"can bob log in here?" (AAA) "check bob" (stores users/groups/policy)
802.1X / VPN login auth+authz+acct source of truth
LDAP DN names an entry in the tree:
cn=alice,ou=staff,dc=example,dc=com
\__ common name \__ org unit \__ domain components
# LDAP bind authentication -- and the injection pitfall to avoid.
import ldap3
def ldap_authenticate(username, password):
server = ldap3.Server("ldaps://dc.example.com:636", use_ssl=True) # TLS!
# SAFE: username is used as a DN component via the library, parameters escaped.
user_dn = f"cn={ldap3.utils.conv.escape_filter_chars(username)},ou=staff,dc=example,dc=com"
conn = ldap3.Connection(server, user=user_dn, password=password)
return conn.bind() # a successful bind == correct password
# VULNERABLE search filter (LDAP injection) -- NEVER build filters by concat:
# f"(uid={username})" with username = "*)(uid=*))(|(uid=*" -> auth bypass
Key Takeaways
- Centralized identity is essential at scale; separate "where identity lives" (the directory) from "how a device asks about a login" (the AAA protocol).
- LDAP queries/modifies a hierarchical directory of entries named by Distinguished Names; Active Directory is the dominant implementation and adds Kerberos.
- LDAP authentication is a bind (connect as the user with their password); plain LDAP is cleartext — use LDAPS/StartTLS and guard against LDAP injection.
- RADIUS is the AAA protocol (Authentication, Authorization, Accounting) devices use for VPN/Wi-Fi/802.1X; it has weaknesses (partial encryption, UDP), improved by RadSec/Diameter.
- Centralization makes management and revocation instant but makes the directory the crown jewel — Active Directory compromise equals organizational compromise.
🧪 Practice
- Explain the division of labor between RADIUS and LDAP when a user connects to enterprise Wi-Fi.
- Describe how LDAP bind authentication confirms a password, and why LDAPS matters.
- Give an LDAP injection payload against
(uid=INPUT)that bypasses authentication and the fix.- Interview-style: "What do the three A's in RADIUS stand for, and which one produces the logs you would use in an incident investigation?" Hint: authentication proves identity, authorization grants access — the third A records what was done.
<a id="63-access-control"></a>
6.3 Access Control
Once a subject is authenticated, access control decides what it may do — the enforcement of authorization policy. This section builds from the abstract models (who may access what, and how that is represented) to the concrete mechanisms on Unix and Windows, and the misconfigurations that let attackers escalate.
Reference Monitor and Security Kernel
Theory
Before any particular access-control mechanism, there is a foundational idea about how enforcement must be structured to be trustworthy: the reference monitor. It is an abstract concept — the component that mediates every access by a subject (user, process) to an object (file, device, memory) and checks it against policy. The reason it matters is that a control you can bypass is no control at all; the reference monitor concept pins down exactly the three properties enforcement must have to be sound.
Those three properties, often remembered as the acronym NEAT or by their classic names, are: it must be always invoked (complete mediation — there is no path to an object that skips the check), tamper-proof (an attacker cannot modify or disable the monitor itself), and verifiable/small enough to be analyzed (simple enough that you can convince yourself it is correct, ideally through formal evaluation). A check that can be gone around (not always invoked), switched off (not tamper-proof), or too complex to audit (not verifiable) fails to deliver security no matter how clever its policy logic.
The security kernel is the concrete implementation of the reference monitor — the hardware, firmware, and software that together enforce it — and it is the core of the broader Trusted Computing Base (TCB), the set of all components whose correctness is essential to security. The design imperative that follows is minimize the TCB: the smaller the trusted core, the smaller the attack surface and the easier it is to verify. This principle echoes throughout systems security — it is why microkernels, hypervisor isolation, and SELinux's in-kernel enforcement are all argued for in these terms, and why adding complexity to a trusted component is always suspect.
Examples
The reference monitor mediates EVERY access; the TCB is what must be trusted:
subject (process)
| requests access to object
v
+--------------------------+ policy
| REFERENCE MONITOR |<--- (rules)
| - always invoked | grant / deny every time
| - tamper-proof |
| - small & verifiable |
+--------------------------+
|
v
object (file, socket, memory)
Security kernel = the implementation. TCB = everything we must trust.
Minimize the TCB: less to attack, less to verify.
How each property fails in practice:
NOT always invoked: a direct syscall path skips the LSM hook -> bypass
NOT tamper-proof: attacker with kernel write disables the check -> bypass
NOT verifiable: 10M-line "trusted" blob nobody can audit -> hidden flaw
Key Takeaways
- The reference monitor is the abstract component that mediates every subject-to-object access against policy.
- It must be always invoked (complete mediation), tamper-proof, and small/verifiable — a control that can be bypassed, disabled, or not audited is not a control.
- The security kernel is the concrete implementation of the reference monitor.
- The Trusted Computing Base (TCB) is everything whose correctness is essential to security; the kernel is its core.
- Minimize the TCB — a smaller trusted core means less attack surface and easier verification; this principle recurs across systems security.
🧪 Practice
- State the three required properties of a reference monitor and give a failure example for each.
- Define the Trusted Computing Base and explain why minimizing it improves security.
- Explain why "complete mediation" means a single bypassable code path invalidates the whole control.
- Interview-style: "Why is a smaller security kernel considered more secure than a larger, more featureful one?" Hint: relate size to both attack surface and the feasibility of verifying correctness.
Access Control Matrix, ACLs, and Capabilities
Theory
If the reference monitor must check every access against policy, we need a way to represent that policy — "which subjects may perform which operations on which objects." The clean theoretical model is the access control matrix: a giant table with subjects as rows, objects as columns, and the allowed operations in each cell. It is a perfect conceptual model but hopelessly impractical to store directly — with thousands of users and millions of files it is enormous and almost entirely empty. So real systems store it one of two ways, and the choice has deep consequences.
Storing the matrix by column gives Access Control Lists (ACLs): each object carries a list of which subjects may do what to it ("this file: alice=read/write, bob=read"). Storing it by row gives capabilities: each subject holds a set of unforgeable tokens ("alice holds: read/write on file X, read on file Y"), and possessing the token is the permission. Most familiar systems (Unix file permissions, Windows ACLs) are ACL-based; capability systems are less common but influential (object capabilities, some microkernels, and conceptually, bearer tokens).
| ACLs (per object) | Capabilities (per subject) | |
|---|---|---|
| "Who can access this file?" | easy — read the object's list | hard — must scan all subjects |
| "What can this subject access?" | hard — must scan all objects | easy — read the subject's set |
| Revocation | easy (edit the object's list) | hard (tokens are held and delegated) |
| Delegation | awkward | natural (hand over the token) |
| Confused deputy problem | susceptible | resistant (authority travels with the request) |
The practical trade-offs flow from this duality. ACLs make it easy to answer "who can touch this object?" and to revoke access, which is why they dominate file systems and resource-centric policy. Capabilities make delegation natural (you pass the token) and resist the confused deputy problem — where a privileged program is tricked into misusing its authority on behalf of a less-privileged caller — because authority travels with the request rather than being ambiently available. Understanding which model a system uses tells you how to reason about its revocation, delegation, and failure modes.
Examples
Same policy, two representations of the access control matrix:
file1 file2
alice rw r
bob r -
carol - rw
ACLs (store by COLUMN, with the object):
file1 -> { alice:rw, bob:r }
file2 -> { alice:r, carol:rw }
Capabilities (store by ROW, held by the subject):
alice holds -> { file1:rw, file2:r }
bob holds -> { file1:r }
carol holds -> { file2:rw }
Why the model matters for two common questions:
"Who can write file1?" ACL: read file1's list (easy)
Cap: scan every subject's tokens (hard)
"Revoke bob's access to file1" ACL: delete bob from file1's list (easy)
Cap: find & invalidate bob's token (hard)
Confused deputy: a server with broad rights acts for a weak client.
ACL/ambient authority -> can be tricked into using its OWN rights.
Capability -> the client must HAND the deputy a token, so no over-reach.
Key Takeaways
- The access control matrix (subjects × objects → operations) is the complete conceptual model but too large and sparse to store directly.
- ACLs store the matrix by column (per object: who may do what) — easy to answer "who can access this?" and to revoke.
- Capabilities store it by row (per subject: unforgeable tokens) — delegation is natural and they resist the confused deputy problem.
- Most familiar systems (Unix, Windows) are ACL-based; capabilities underpin object-capability systems and bearer tokens.
- Choosing the representation determines how easily you reason about revocation, delegation, and misuse of authority.
🧪 Practice
- Draw a small access control matrix and write out both its ACL and capability representations.
- Explain which representation makes "list everything Alice can access" cheap, and which makes revocation cheap.
- Describe the confused deputy problem and why capabilities resist it.
- Interview-style: "A bearer token in a web API — is that closer to an ACL or a capability, and what does that imply about revocation?" Hint: possession of the token is the permission; relate that to how capabilities are revoked.
Discretionary Access Control (DAC)
Theory
DAC is the access-control model most people have used their whole lives without naming it: the model where the owner of a resource controls who may access it, at their own discretion. When you right-click a file and change its sharing, or run chmod on your own file, you are exercising DAC. The defining property — and the source of both its ubiquity and its weakness — is that access decisions are delegated to users, not dictated centrally.
Mechanically, DAC means every object has an owner, and the owner can grant or revoke permissions to others (typically via ACLs or Unix permission bits). This is flexible, intuitive, and exactly right for personal and collaborative computing where users legitimately decide who sees their own data. It is why Unix, Windows, and macOS file systems are fundamentally DAC: the system trusts owners to make sensible sharing choices.
The security weaknesses are structural, not incidental. First, DAC cannot enforce an organization-wide policy, because any owner can override intent — if policy says "secret data must never leave the secret enclave," DAC cannot stop an authorized reader from copying it to a world-readable file. Second, and more seriously, DAC is vulnerable to the transitivity / Trojan horse problem: permissions flow with programs. If Alice runs a program (perhaps malicious) that she trusts, that program runs with Alice's rights and can grant away or copy anything Alice can access, without Alice's knowledge. Because authority is ambient (a process inherits all of its user's permissions) and users can propagate access freely, DAC cannot contain malware or enforce confidentiality against a motivated insider. These exact gaps are what Mandatory Access Control (the next topic) was invented to close — DAC and MAC are best understood as a pair, DAC being flexible but uncontainable, MAC being rigid but enforceable.
Examples
# DAC in action: the OWNER decides, at their discretion.
chmod 640 report.txt # owner: rw, group: r, others: none -- owner's choice
chown alice:staff report.txt # ownership itself is a DAC concept
setfacl -m u:bob:rw report.txt # owner grants bob rw via an ACL entry
# Nothing here consults a central policy: Alice alone decides. That's "discretionary".
The Trojan horse / transitivity weakness of DAC:
Alice can read secret.txt (owner granted her).
Alice runs evil_tool (looks useful; actually malicious).
evil_tool runs WITH ALICE'S RIGHTS (ambient authority), so it can:
cp secret.txt /tmp/public.txt && chmod 644 /tmp/public.txt
-> secret leaked, and DAC permitted every step. Alice never intended it.
MAC fixes this: a label on secret.txt would forbid the copy regardless of owner.
Key Takeaways
- DAC lets the owner of a resource decide who may access it, at their discretion — the model behind Unix, Windows, and macOS file permissions.
- It is flexible and intuitive, ideal for personal and collaborative sharing where users legitimately control their own data.
- DAC cannot enforce an organization-wide policy because any owner can override it.
- It is vulnerable to the Trojan horse/transitivity problem: programs run with the user's ambient authority and can propagate or leak access without the user's knowledge.
- These weaknesses motivate Mandatory Access Control — DAC is flexible but uncontainable; MAC is rigid but enforceable.
🧪 Practice
- Give two everyday examples of DAC and identify who makes the access decision in each.
- Explain the Trojan horse problem in DAC and why the user's intent is irrelevant to the outcome.
- Argue why DAC alone cannot enforce "this classified file must never become world-readable."
- Interview-style: "Why can DAC not contain malware, and what model addresses this?" Hint: consider what rights a program inherits when a user runs it, and what a non-discretionary label would add.
Mandatory Access Control (MAC)
Theory
MAC exists to close exactly the gaps DAC leaves open. Its defining property is in the name: access rules are mandatory — set centrally by a policy and enforced by the system, and users cannot override them, not even for resources they "own." Where DAC trusts owners, MAC trusts only the policy. This is the model for environments where confidentiality or integrity must be guaranteed regardless of user behavior: military/government classification, and, in modern form, OS confinement like SELinux and AppArmor.
The classic MAC mechanism is labels and clearances. Every object gets a security label (e.g. Unclassified, Confidential, Secret, Top Secret) and every subject gets a clearance. The system — not the user — decides each access by comparing label and clearance according to fixed rules. Because the owner cannot change an object's label or grant access outside policy, the Trojan horse problem is defeated: a malicious program running with Alice's rights still cannot copy Secret data into an Unclassified file, because the system forbids the write based on labels, no matter what Alice or her programs want. Modern "type enforcement" MAC (SELinux) generalizes labels into types/domains and writes policy as explicit allow rules between them, but the principle is identical: a central, non-discretionary, system-enforced policy.
The trade-off is rigidity and administrative cost. MAC is powerful but inflexible — it requires careful, centralized policy authoring, and a too-strict policy breaks legitimate work while a mislabeled object silently blocks access. In practice, modern systems combine both: DAC and MAC together, where DAC handles everyday user discretion and MAC provides an inviolable backstop that no user or compromised process can escape. SELinux, for example, enforces its MAC policy on top of ordinary Unix DAC permissions — both must allow an access for it to proceed, which is why a compromised web server confined by SELinux cannot read /etc/shadow even if a DAC misconfiguration would have let it.
| DAC | MAC | |
|---|---|---|
| Who decides | the resource owner | central policy, system-enforced |
| User override | yes (discretionary) | no (mandatory) |
| Trojan horse | vulnerable | resistant |
| Flexibility | high | low (rigid, high admin cost) |
| Typical use | personal/collaborative files | classification, OS confinement (SELinux) |
Examples
MAC labels defeat the Trojan horse that DAC permitted:
secret.txt : label = SECRET
public.txt : label = UNCLASSIFIED
Alice: clearance SECRET, runs a malicious tool with her rights.
tool tries: cp secret.txt public.txt (write SECRET data into UNCLASSIFIED)
DAC alone: allowed (Alice owns both) -> LEAK
MAC: DENIED by the system -- "no write down" policy on labels,
regardless of Alice's wishes or her program's rights.
# SELinux: MAC labels (contexts) layered ON TOP of Unix DAC.
ls -Z /var/www/html/index.html
# -rw-r--r--. apache apache unconfined_u:object_r:httpd_sys_content_t:s0
# ^^^^^^^^^^^^^^^^^^^^^ the MAC TYPE
getenforce # Enforcing = MAC is active and blocking violations
# Even if DAC perms were loosened, the httpd domain can only touch httpd_* types,
# so a compromised Apache cannot read shadow_t (/etc/shadow). Both DAC AND MAC must allow.
Key Takeaways
- MAC enforces centrally-set, system-enforced access rules that users cannot override — the opposite of DAC's owner discretion.
- Classic MAC uses labels on objects and clearances on subjects; the system compares them by fixed rules to decide access.
- Because owners cannot change labels or grant outside policy, MAC defeats the Trojan horse/transitivity problem that breaks DAC.
- The cost is rigidity and administrative effort; a mislabeled object silently blocks legitimate access.
- Modern systems combine DAC and MAC (e.g. SELinux over Unix permissions): both must allow an access, giving an inviolable backstop against compromise.
🧪 Practice
- Explain, with labels and clearances, how MAC blocks the exact Trojan horse scenario DAC permits.
- Contrast "who decides" and "can the user override" between DAC and MAC.
- Explain why SELinux enforcing on top of DAC means a compromised service is still confined.
- Interview-style: "Why do real systems use both DAC and MAC rather than replacing one with the other?" Hint: think about everyday usability versus a guaranteed, non-bypassable policy floor.
Bell-LaPadula and Biba Models
Theory
Bell-LaPadula and Biba are the two foundational formal MAC models, and they are best understood as mirror images that protect opposite properties. Bell-LaPadula protects confidentiality (keeping secrets secret); Biba protects integrity (keeping trusted data trustworthy). Both use labels and both state their rules as constraints on reading and writing across levels — and the rules point in opposite directions precisely because the goals are opposite.
Bell-LaPadula (confidentiality) is captured by two rules, memorable as "no read up, no write down." The Simple Security Property is no read up: a subject cannot read data above its clearance (a Confidential user cannot read Top Secret). Intuitive. The *-property (star property) is no write down: a subject cannot write to a level below its own. This second rule surprises people, but it is the crucial one — it prevents a cleared subject (or a Trojan horse running as them) from copying secret data down into a less-classified container where unauthorized readers could see it. Together they ensure information flows only upward in classification, never leaking down.
Biba (integrity) inverts both: "no read down, no write up." The Simple Integrity Property is no read down: a high-integrity subject cannot read low-integrity (untrusted) data, lest it be corrupted or misled by it. The *-integrity Property is no write up: a low-integrity subject cannot write to a high-integrity object, preventing untrusted data from contaminating trusted data. Information flows only downward in integrity. A concrete Biba intuition: a system administrator's trusted configuration must not be writable by an untrusted process, and a trusted process should not ingest untrusted input as if it were authoritative.
| Bell-LaPadula (confidentiality) | Biba (integrity) | |
|---|---|---|
| Goal | secrets stay secret | trusted data stays trustworthy |
| Read rule | no read UP | no read DOWN |
| Write rule | no write DOWN (*-property) | no write UP |
| Information flows | upward (toward secret) | downward (toward low integrity) |
| Mnemonic | "no read up, no write down" | "no read down, no write up" |
The reason both exist is that confidentiality and integrity are genuinely different and sometimes conflicting goals — you cannot always satisfy both with one lattice, which is why real systems pick the property that matters most for the context (classified data → Bell-LaPadula; critical system integrity → Biba) or combine ideas. These models are also the theoretical ancestors of modern mechanisms: Windows Mandatory Integrity Control (integrity levels on processes) is essentially Biba, and classification systems are Bell-LaPadula.
Examples
Mirror-image rules (levels high at top):
Bell-LaPadula (CONFIDENTIALITY) Biba (INTEGRITY)
TOP SECRET HIGH integrity
^ write OK (up) | read OK (down)
| read X (no read up) v write X (no write up)
SECRET <subject> <subject>
| read OK (down) ^ read X (no read down)
v write X (no write down, *-prop) | write OK (up? NO) -> down only
UNCLASSIFIED LOW integrity
BLP: info flows UP (can't leak down). Biba: info flows DOWN (can't corrupt up).
Concrete intuition:
BLP *-property (no write down) stops the Trojan horse:
a SECRET-cleared process cannot write secrets into an UNCLASSIFIED file.
Biba no-write-up stops contamination:
an untrusted (LOW) web process cannot overwrite a HIGH-integrity system binary.
Windows Mandatory Integrity Control implements this: Low-integrity IE/Edge
processes cannot write to Medium/High-integrity locations.
Key Takeaways
- Bell-LaPadula protects confidentiality; Biba protects integrity — mirror-image models with opposite rules.
- Bell-LaPadula: "no read up, no write down" — information flows only upward, preventing secrets from leaking down (the *-property is the key anti-Trojan-horse rule).
- Biba: "no read down, no write up" — information flows only downward, preventing untrusted data from corrupting trusted data.
- The two goals can conflict, so systems choose the property that matters most, or combine ideas.
- They are the ancestors of real mechanisms: classification systems (Bell-LaPadula) and Windows Mandatory Integrity Control (Biba).
🧪 Practice
- State both Bell-LaPadula rules and explain why "no write down" is the one that prevents leaks.
- State both Biba rules and give an integrity scenario each one prevents.
- Explain why confidentiality and integrity models point in opposite directions.
- Interview-style: "Windows prevents a low-integrity browser process from writing to system folders. Which classic model is this, and which specific rule?" Hint: the goal is integrity, and the rule forbids writing toward higher trust.
Role-Based Access Control (RBAC)
Theory
RBAC is the access-control model that dominates real organizations, because it solves the management problem that per-user permissions create. Assigning permissions directly to individuals does not scale: with thousands of employees and tens of thousands of permissions, the assignment becomes an unmanageable, error-prone mess, and nobody can answer "who can do what?" RBAC inserts a layer of indirection — the role — between users and permissions, and that single idea transforms administration.
The structure is: users are assigned to roles, roles are granted permissions, and users get permissions only through their roles. Instead of granting Alice 50 individual permissions, you assign her the "Accountant" role, and the role carries those permissions. When Bob joins accounting, he gets the role; when Alice moves to a new team, you change her role, not 50 separate grants. This maps naturally onto how organizations actually think (people have jobs), makes onboarding/offboarding a single operation, and makes the policy auditable — you can list a role's permissions and its members and reason about them. RBAC also supports role hierarchies (senior roles inherit junior roles' permissions) and constraints, most importantly Separation of Duties (defining that certain roles are mutually exclusive — the person who requests a payment cannot also approve it, enforced as a rule that no user may hold both roles).
RBAC's great strength — stability and manageability — is also its limitation: it is coarse-grained and context-blind. A role grants the same permissions to everyone who holds it, regardless of when, where, or which specific record is involved. "Accountant" can see accounting data, but RBAC alone cannot naturally express "only during business hours," "only for their own region," or "only records they created." When policy needs that contextual nuance, systems extend RBAC or move to Attribute-Based Access Control (the next topic). The common real-world pattern is RBAC as the backbone for broad access, with attribute checks layered on for fine-grained conditions. A persistent operational risk is role explosion — creating ever more narrow roles to approximate fine-grained needs until the role set itself becomes unmanageable, which is a signal that ABAC is the better tool.
Examples
The indirection that makes RBAC scale:
WITHOUT roles: user --(50 direct grants each)--> permissions (unmanageable)
WITH RBAC: users --> ROLES --> permissions
alice -----> Accountant --> {read ledger, post journal, run reports}
bob -------> Accountant --> (same set, automatically)
carol -----> Auditor --> {read ledger, read reports} (read-only)
Hierarchy: Manager inherits Accountant (+ approve_payment)
SoD constraint: no user may hold BOTH Requester AND Approver.
# RBAC with a role hierarchy and a separation-of-duties constraint.
ROLE_PERMS = {
"accountant": {"ledger:read", "journal:post", "report:run"},
"auditor": {"ledger:read", "report:read"},
"manager": {"payment:approve"}, # plus inherits accountant
}
INHERITS = {"manager": ["accountant"]}
MUTUALLY_EXCLUSIVE = [{"requester", "approver"}] # separation of duties
def effective_perms(roles):
perms, seen = set(), set()
stack = list(roles)
while stack:
r = stack.pop()
if r in seen: continue
seen.add(r)
perms |= ROLE_PERMS.get(r, set())
stack += INHERITS.get(r, []) # pull in inherited roles
return perms
def assign_ok(user_roles): # enforce SoD: reject conflicting role combinations
return not any(pair <= set(user_roles) for pair in MUTUALLY_EXCLUSIVE)
Key Takeaways
- RBAC inserts roles between users and permissions: users get permissions only through assigned roles, solving the scaling problem of per-user grants.
- It maps to how organizations think (jobs), makes onboarding/offboarding a single operation, and makes policy auditable.
- Role hierarchies let senior roles inherit junior permissions; Separation of Duties constraints make conflicting roles mutually exclusive.
- RBAC is coarse-grained and context-blind — it cannot natively express time, location, or per-record conditions.
- Watch for role explosion (too many narrow roles); that signal usually means ABAC or a hybrid is the right next step.
🧪 Practice
- Explain the indirection RBAC adds and why it makes onboarding and auditing easier.
- Model a role hierarchy where "manager" inherits "employee" and add one separation-of-duties constraint.
- Give a policy requirement RBAC cannot express cleanly and explain why.
- Interview-style: "Your RBAC system has grown to 4,000 roles for 5,000 users. What has gone wrong and what would you consider instead?" Hint: name the anti-pattern and the model that handles contextual, fine-grained rules without a role per case.
Attribute-Based Access Control (ABAC)
Theory
ABAC is the most expressive mainstream access-control model, and it exists to handle exactly the context-dependent decisions RBAC cannot. Instead of deciding access from a static role, ABAC evaluates attributes — properties of the subject, the resource, the action, and the environment — against policy rules at the moment of each request. The access decision becomes a function: permit?(subject attrs, resource attrs, action, environment attrs). This lets policy express nuanced, dynamic conditions that would require an explosion of roles to approximate.
The four attribute categories are the key to thinking in ABAC: subject attributes (department, clearance, location, role — ABAC can include role as just one attribute), resource/object attributes (classification, owner, project, data type), action attributes (read, write, delete, approve), and environment/contextual attributes (time of day, source IP, device posture, threat level). A single policy can then say "permit if subject.department == resource.department AND action == read AND environment.time in business_hours AND subject.device == managed" — a rule that is impossible to express as a role but trivial as attributes. This is why ABAC is the natural fit for fine-grained, dynamic, and risk-adaptive access, and why it is the model behind modern policy engines and much of Zero Trust (later in the course), where every request is evaluated against current context.
The trade-off is the inverse of RBAC's. ABAC's power comes with complexity: policies can be hard to author correctly, hard to audit ("who can access this?" requires evaluating rules against all possible attribute combinations rather than reading a list), and hard to reason about for unintended interactions. Performance and the integrity of attribute sources also matter — a decision is only as trustworthy as the attributes feeding it (if an attacker can spoof device == managed, the policy is subverted). In practice, ABAC and RBAC are complementary, not rival: a common robust pattern uses roles for coarse structure and attributes for fine-grained conditions on top, getting RBAC's auditability where broad access suffices and ABAC's precision where context matters. The industry-standard way to express ABAC policy is externalized decision-making (a Policy Decision Point evaluating rules, e.g. in the XACML model or engines like OPA/Rego), separating policy from application code.
| RBAC | ABAC | |
|---|---|---|
| Decision basis | static role membership | attributes evaluated per request |
| Context-aware | no | yes (time, location, device, etc.) |
| Expressiveness | coarse | fine-grained, dynamic |
| Auditability | easy (read the role) | hard (evaluate rules over combinations) |
| Failure mode | role explosion | policy complexity, attribute trust |
Examples
An ABAC decision is a function of four attribute categories:
PERMIT read on resource R by subject S in environment E IF
S.department == R.department (subject + resource attributes)
AND action == "read" (action attribute)
AND E.time in 09:00-17:00 (environment attribute)
AND S.device_posture == "managed" (environment/subject attribute)
-> impossible as a single ROLE, trivial as attributes.
# ABAC policy evaluated per request (the Policy Decision Point).
def abac_permit(subject, resource, action, env):
# subject/resource/env are dicts of attributes; policy is explicit and dynamic.
if action == "read" and subject["dept"] == resource["dept"] \
and env["hour"] in range(9, 18) \
and subject["device"] == "managed": # device posture (Zero Trust-ish)
return True
if action == "approve" and subject["role"] == "manager" \
and resource["amount"] <= subject["approval_limit"]: # role AS an attribute
return True
return False # default deny
# Trust note: the decision is only as sound as the attribute sources feeding it.
Key Takeaways
- ABAC decides access by evaluating attributes of the subject, resource, action, and environment against policy at request time — a function, not a static lookup.
- The four attribute categories enable fine-grained, dynamic, context-aware rules (time, location, device posture) that RBAC cannot express.
- It is the model behind modern policy engines and Zero Trust's per-request evaluation.
- The cost is complexity: policies are harder to author, audit, and reason about, and decisions are only as trustworthy as the attribute sources.
- RBAC and ABAC are complementary — roles for coarse structure, attributes for fine-grained conditions; externalize policy (PDP/XACML/OPA) from application code.
🧪 Practice
- Name the four ABAC attribute categories and give one example attribute for each.
- Write an ABAC rule that enforces "doctors may read records only for patients in their own ward during their shift."
- Explain why "who can access this resource?" is harder to answer under ABAC than RBAC.
- Interview-style: "Why is ABAC a natural fit for Zero Trust, and what new risk does basing decisions on attributes introduce?" Hint: Zero Trust evaluates every request in context; consider what happens if an attribute like device posture can be spoofed.
Unix Permissions, setuid, and Sudo
Theory
Unix permissions are the most widely deployed concrete access-control mechanism in the world, and they are a DAC model built on a deliberately simple scheme. Every file has an owner (user) and a group, and three permission triads — for owner, group, and others — each granting read (r), write (w), and execute (x). That is the entire core model, usually written as a 9-bit mask and expressed in octal (rwxr-x--- = 750). Its simplicity is its strength (easy to reason about) and its limitation (only one owner and one group per file, which is why POSIX ACLs exist for finer control).
The meaning of the bits differs subtly but importantly between files and directories, and getting this wrong causes real security bugs. On a file, r reads contents, w modifies contents, x runs it. On a directory, r lists names, w creates and deletes entries (so write on a directory lets you delete files you cannot even read — the classic trap), and x traverses into it to access its contents. Three special bits extend the model: setuid (a program runs with the file owner's privileges, not the caller's), setgid (runs with the file's group, or on a directory makes new files inherit the group), and the sticky bit (on a directory like /tmp, only the owner of a file may delete it — the fix for the directory-write deletion trap).
setuid is the most security-critical and the most dangerous. It is the mechanism that lets an unprivileged user run a program that performs a privileged action — passwd is setuid-root so you can change your own password (which must write to root-owned /etc/shadow) without being root. But a setuid-root program is a privilege boundary: any bug in it (an overflow, a command injection, an unsafe PATH) becomes a root compromise, because the program is already running as root. This is why setuid binaries are a top target for privilege escalation and why minimizing them is a hardening priority. sudo is the modern, auditable alternative to broad setuid: instead of marking binaries, sudo consults a central policy (/etc/sudoers) to grant specific users the right to run specific commands as another user (usually root), logging each use. But sudo misconfiguration is itself a leading escalation path — granting sudo to a program that can spawn a shell or write arbitrary files (vim, find, less, tee) effectively grants root, as the GTFOBins project catalogs exhaustively.
Examples
# Reading and setting the model; note the special bits.
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root ... the 's' in the owner triad = SETUID-root
# ^ runs as root no matter who calls it -> a privilege boundary.
chmod 750 script.sh # rwx for owner, r-x for group, nothing for others
chmod u+s tool # set setuid (dangerous; audit every such binary)
ls -ld /tmp
# drwxrwxrwt the trailing 't' = STICKY: anyone can create, only owners delete.
# Find every setuid/setgid binary -- a core attack-surface audit:
find / -perm -4000 -o -perm -2000 2>/dev/null # 4000=setuid, 2000=setgid
# sudo: auditable, policy-driven privilege -- and its misconfiguration traps.
sudo -l # what MAY the current user run as root? (recon step)
# /etc/sudoers DANGER: these grant effective root because they can spawn shells:
# alice ALL=(root) NOPASSWD: /usr/bin/vim -> :!sh => root shell
# bob ALL=(root) NOPASSWD: /usr/bin/find -> find . -exec sh \; => root
# carol ALL=(root) NOPASSWD: /usr/bin/tee -> write any root-owned file
# Principle: grant the narrowest command, never an interpreter or file-writer.
Key Takeaways
- Unix permissions are DAC: owner/group/others each with read/write/execute (a 9-bit octal mask like
750); simple but limited to one owner and one group (POSIX ACLs extend it). - Directory bits differ from file bits: write on a directory lets you delete files you cannot read — the sticky bit (as on
/tmp) fixes this. - setuid/setgid run a program with the file owner's/group's privileges, not the caller's; the sticky bit restricts deletion to file owners.
- setuid-root binaries are privilege boundaries — any bug becomes root compromise — so auditing and minimizing them is a hardening priority.
- sudo is the auditable, policy-driven alternative, but misconfigured sudo rules (granting interpreters or file-writers) are a leading privilege-escalation path (see GTFOBins).
🧪 Practice
- Convert
rwxr-x--xto octal and explain what each triad permits.- Explain the directory-write deletion trap and how the sticky bit prevents it.
- Find all setuid binaries on a system and explain why each is a potential escalation target.
- Interview-style: "A user has
sudorights to run only/usr/bin/find. Can they get a root shell?" Hint: recallfind's-execoption and why granting any program that can execute other commands is equivalent to granting a shell.
Windows Security Descriptors and Tokens
Theory
Windows implements access control with a richer, more granular ACL model than Unix, and understanding its two core structures — the access token (what a process carries) and the security descriptor (what an object is protected by) — is essential for both administering and attacking Windows. The mental model is: when you log in, Windows builds a token describing you; every securable object carries a descriptor describing who may do what to it; and each access is decided by comparing the token against the object's descriptor.
The access token is attached to every process and thread and represents the security context of the account it runs as. It contains the user's SID (Security Identifier) — the immutable unique ID Windows actually uses (names are just labels over SIDs) — the SIDs of all groups the user belongs to, the user's privileges (special rights like SeDebugPrivilege or SeBackupPrivilege that transcend object permissions), and an integrity level (Windows' Biba-style Mandatory Integrity Control: Low/Medium/High/System). Because the token is the process's identity, token theft and impersonation are central to Windows attacks: steal or duplicate a privileged token and your process inherits that identity — the basis of techniques like "pass-the-token" and much of post-exploitation lateral movement.
Every securable object (file, registry key, service, process) has a security descriptor containing the owner SID and two ACLs. The DACL (Discretionary ACL) is the access-control list proper — an ordered list of ACEs (Access Control Entries), each allowing or denying specific rights to a specific SID; this is what grants or refuses access. The SACL (System ACL) is separate and governs auditing — which accesses are logged. Two subtleties matter greatly: ACE order is significant (deny ACEs are typically evaluated first, and access is determined by the first matching ACE, so misordering can silently grant access), and the special meaning of privileges — certain token privileges (like SeDebugPrivilege, which allows opening any process, or SeBackupPrivilege, which bypasses file DACLs entirely for backup) override normal ACL checks, making their assignment a critical and frequently-abused escalation vector. The practical upshot: Windows privilege escalation is often less about file permissions and more about token privileges, integrity levels, and misconfigured service DACLs.
Examples
The two structures and how a decision is made:
PROCESS OBJECT (file/service/registry key)
+------ access token -------+ +---- security descriptor --------+
| user SID: S-1-5-21-..-1001| | owner SID |
| group SIDs: [Admins, ...] | | DACL (who may do what): |
| privileges: SeDebug, ... | | ACE deny Guests write |
| integrity: Medium | | ACE allow Alice read/write |
+---------------------------+ | ACE allow Admins full |
| | SACL (what to audit) |
| access request +---------------------------------+
+--> compare token SIDs/privileges against DACL ACEs
first matching ACE decides (deny usually first) -> grant/deny
BUT: SeBackupPrivilege etc. can bypass the DACL entirely.
Why tokens and privileges dominate Windows attacks:
Token theft: duplicate a SYSTEM/admin process's token -> run as SYSTEM.
SeDebugPrivilege: open ANY process -> inject/steal its token.
SeBackupPrivilege: read ANY file ignoring its DACL (e.g. the SAM, ntds.dit).
SeImpersonatePrivilege: "potato" attacks coerce a SYSTEM token -> escalate.
Misordered DACL ACEs: an allow before an intended deny -> unintended access.
Key Takeaways
- Windows decides access by comparing a process's access token against an object's security descriptor.
- The access token carries the user SID, group SIDs, privileges, and an integrity level (Mandatory Integrity Control, a Biba-style model); the token is the process's identity, so token theft/impersonation is central to Windows attacks.
- SIDs are the immutable identifiers Windows actually uses; names are labels over them.
- A security descriptor holds the owner, a DACL (ordered allow/deny ACEs that grant access), and a SACL (auditing); ACE order is significant.
- Certain token privileges (SeDebug, SeBackup, SeImpersonate) override normal ACL checks, making them prime escalation vectors — Windows escalation is often about privileges and tokens, not just file permissions.
🧪 Practice
- Explain the roles of the access token and the security descriptor in a Windows access decision.
- Describe the difference between a DACL and a SACL and why ACE order matters.
- Explain how
SeBackupPrivilegecan let a user read a file whose DACL denies them.- Interview-style: "Why is stealing a process's access token a powerful attack on Windows, and what privilege commonly enables it?" Hint: the token is the process's whole identity; recall which privilege lets you open arbitrary processes to duplicate theirs.
SELinux and AppArmor Policies
Theory
SELinux and AppArmor are the two mainstream Linux implementations of Mandatory Access Control, and they exist to do what Unix DAC cannot: confine a process to only the resources it legitimately needs, so that compromising it does not grant the attacker everything the process's user could reach. They are the practical answer to "my web server runs as www-data, but if it is exploited, a DAC-only system lets the attacker do anything www-data can — read other sites, connect outbound, probe the network." MAC confinement shrinks that blast radius to near nothing.
SELinux uses type enforcement with labels. Every process runs in a domain and every object has a type (together, the context you saw as httpd_sys_content_t), and policy is a large set of explicit allow rules stating which domains may perform which operations on which types. The default is deny: anything not explicitly allowed is forbidden. This is powerful and extremely fine-grained but notoriously complex to author — hence the common anti-pattern of disabling SELinux (setenforce 0) when something breaks, which throws away the protection entirely. The correct workflow is to run in permissive mode (log violations without blocking), observe the denials (AVC messages in the audit log), and generate policy to allow the legitimate ones (audit2allow) before switching to enforcing. SELinux also supports Boolean toggles for common policy choices and multi-level security for classification environments.
AppArmor takes a deliberately simpler, more approachable approach: path-based profiles. Instead of labeling objects, an AppArmor profile lists the file paths and capabilities a specific program is allowed to use (e.g. "nginx may read /var/www/**, may bind port 80, may not execute shells"). Profiles are per-executable and much easier to read and write than SELinux policy, which is why Ubuntu/SUSE favor AppArmor while RHEL/Fedora/Android favor SELinux. The trade-off is in the models: SELinux's label-based approach is more robust (it follows the object regardless of path, so it is not fooled by hard links, bind mounts, or renaming), while AppArmor's path-based approach can in principle be evaded by path manipulation but is far more usable. Both share the same essential value proposition and the same workflow lesson: confine services to least privilege, and tune policy with logging rather than disabling it.
| SELinux | AppArmor | |
|---|---|---|
| Model | type enforcement (labels on everything) | path-based profiles per program |
| Granularity | very fine | coarser, per-executable |
| Robustness | follows the object (label) — hardlink/rename safe | path-based — can be path-tricked |
| Usability | complex to author | much easier to read/write |
| Common on | RHEL, Fedora, Android | Ubuntu, SUSE, Debian |
Examples
# SELinux: inspect labels, use permissive-mode logging to BUILD policy (not disable).
ls -Z /var/www/html # see object types (httpd_sys_content_t, ...)
ps -eZ | grep httpd # see the domain a process runs in (httpd_t)
setenforce 0 # PERMISSIVE: log violations but don't block (tuning)
ausearch -m avc -ts recent # read the denials (AVC = Access Vector Cache msgs)
ausearch -m avc -ts recent | audit2allow -M mypol # generate an allow policy
setenforce 1 # back to ENFORCING once policy is correct
# Anti-pattern: leaving it disabled "because it broke something" = no MAC at all.
AppArmor profile (path-based) for a service -- readable least privilege:
/usr/sbin/nginx {
#include <abstractions/base>
capability net_bind_service, # may bind low ports (80/443)
/var/www/** r, # read web content only
/var/log/nginx/*.log w, # write its own logs
/etc/nginx/** r, # read its config
deny /bin/** x, # explicitly: no executing shells/binaries
}
# If nginx is exploited, it still cannot read /etc/shadow or spawn /bin/sh.
Key Takeaways
- SELinux and AppArmor are Linux MAC systems that confine a process to only what it needs, shrinking the blast radius of a compromise far below what the process's DAC user could reach.
- SELinux uses label-based type enforcement (domains and types, explicit allow rules, default deny) — very fine-grained but complex to author.
- AppArmor uses path-based per-program profiles — coarser but much easier to read and write.
- SELinux's labels are robust against hard links/renames; AppArmor's paths are more usable but path-trickable; distros differ (RHEL→SELinux, Ubuntu→AppArmor).
- The key operational lesson: tune policy with permissive-mode logging and tools like
audit2allow, never disable MAC because something broke.
🧪 Practice
- Explain how MAC confinement limits the damage of an exploited web server compared to DAC alone.
- Contrast SELinux's label-based model with AppArmor's path-based model, naming one advantage of each.
- Describe the correct SELinux workflow for fixing a legitimate access that is being denied, without disabling enforcement.
- Interview-style: "Why is label-based enforcement (SELinux) harder to evade than path-based (AppArmor)?" Hint: think about hard links, bind mounts, and renaming — does the policy follow the name or the object?
Privilege Escalation via Misconfiguration
Theory
Privilege escalation is the step that turns a foothold into control: an attacker who gains access as an unprivileged user seeks to become root/SYSTEM or another more-powerful account. While some escalation uses memory-corruption exploits (the previous chapter), the overwhelming majority in practice comes from misconfiguration — permissions, ownership, and trust relationships set up wrongly, which require no exploit code at all, just knowing where to look. This is why escalation is as much an enumeration skill as an exploitation one.
There are two directions. Vertical escalation gains higher privileges (user → root); horizontal escalation gains the privileges of another same-level account (one user → another user, often a stepping stone). The misconfigurations that enable them cluster into recognizable categories, and knowing the categories is what makes systematic enumeration possible:
| Category | Example | Why it escalates |
|---|---|---|
| Sudo misconfig | sudo to vim/find/less | spawn a root shell (GTFOBins) |
| Dangerous setuid | custom setuid-root binary with a bug | bug runs as root |
| Weak file permissions | world-writable /etc/passwd, cron script, service binary | overwrite to run code as its owner |
Writable PATH / $PATH abuse | setuid program calls a bare ls | plant a malicious ls earlier in PATH |
| Service/scheduled task flaws | writable Windows service binary, cron run as root | your code runs as the service account |
| Credential exposure | passwords in config files, histories, env vars | reuse to become another account |
| Kernel/sudo CVEs | unpatched pkexec, Dirty COW, sudo bugs | known exploit for a known hole |
The unifying principle is trust misplaced: something privileged trusts something an unprivileged user controls — a writable file it reads, a relative command it executes, a PATH it inherits, a credential it left lying around. The defender's job is the inverse: enforce least privilege, remove unnecessary setuid binaries and sudo grants, set correct ownership/permissions on anything privileged code touches, never store credentials in readable files, and patch promptly. Enumeration tools (LinPEAS, WinPEAS, linux-smart-enumeration) automate the search for these exact patterns, which is a double-edged reminder: whatever the attacker's tool finds, the defender's hardening should have already removed.
Examples
# A Linux privilege-escalation enumeration sweep (what attacker and defender both run):
sudo -l 2>/dev/null # exploitable sudo rules?
find / -perm -4000 -type f 2>/dev/null # setuid binaries (bug = root)
find / -writable -type f 2>/dev/null | grep -vE '^/proc|^/sys' # writable files
getcap -r / 2>/dev/null # Linux capabilities (cap_setuid etc.)
cat /etc/crontab; ls -la /etc/cron.* # root cron jobs you can modify?
grep -riE 'password|secret|api_key' /etc /home 2>/dev/null # leaked credentials
uname -a # kernel version -> known CVEs?
# A concrete chain: a world-writable script run by root's cron = instant root.
ls -l /opt/backup.sh
# -rwxrwxrwx 1 root root ... <- world-writable AND run by root via cron
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /opt/backup.sh
# wait for cron to run it as root, then:
/tmp/rootbash -p # -p keeps the setuid privileges -> euid 0 (root)
# Fix: chmod 700, chown root:root, and never run writable scripts as root.
Key Takeaways
- Most real privilege escalation comes from misconfiguration, not exploits — it is primarily an enumeration skill.
- Vertical escalation gains higher privileges (user → root/SYSTEM); horizontal escalation gains another same-level account's access.
- Common categories: sudo misconfig, dangerous setuid, weak permissions on files/scripts/services, PATH abuse, scheduled-task flaws, exposed credentials, and unpatched CVEs.
- The unifying flaw is misplaced trust — privileged code trusting a file, command, PATH, or credential that an unprivileged user controls.
- Defend by least privilege: remove unneeded setuid/sudo, fix ownership/permissions on anything privileged code touches, never leave credentials in readable files, and patch promptly.
🧪 Practice
- Explain the difference between vertical and horizontal privilege escalation with an example of each.
- Describe how a world-writable script executed by root's cron leads to root, and the fix.
- Explain
$PATHabuse against a setuid binary that calls a command without an absolute path.- Interview-style: "An attacker finds a setuid-root binary that runs
system("ls"). How is this exploited, and what is the secure way to write such a call?" Hint:systemuses the shell's PATH — think about planting a maliciouslsand why absolute paths plus a sanitized environment fix it.
Privileged Access Management and Access Reviews
Theory
The models and mechanisms so far decide whether an access is allowed; PAM and access reviews address the organizational reality that privilege accumulates and goes stale over time. People change roles, projects end, contractors leave, and emergency access is granted and forgotten — so without active management, the set of who-can-do-what drifts steadily toward over-entitlement, which is exactly the condition attackers exploit. These practices are the governance layer that keeps privilege matched to actual need.
Privileged Access Management (PAM) is the discipline and tooling for controlling the most dangerous accounts — root, domain admin, service accounts, cloud root. Its core techniques all serve least privilege and accountability for high-value access: credential vaulting (privileged passwords/keys are stored in a vault, not known to humans, and checked out when needed), session brokering and recording (admins connect through the PAM system, which proxies and records the session for audit), just-in-time (JIT) access (privileges are granted for a specific task and time window, then automatically revoked, rather than standing permanently), and credential rotation (vaulted secrets are rotated automatically, so a leaked one expires fast). The guiding goal is to eliminate standing privilege — the permanent admin rights that an attacker inherits the moment they compromise an account. JIT access means that even a compromised admin account is usually not currently privileged.
Access reviews (also called access recertification or attestation) are the periodic, systematic re-validation of who has what access, asking of each grant: is this still needed? They directly counter privilege creep — the slow accumulation of entitlements as people move around without old access being removed. A review has managers or resource owners confirm or revoke each person's access on a schedule (often quarterly for sensitive systems), and is a core compliance requirement (SOX, ISO 27001, SOC 2). Closely related is the joiner-mover-leaver lifecycle: access should be provisioned on joining, adjusted on moving (the step most often skipped, which causes creep), and fully deprovisioned on leaving (orphaned accounts of departed staff are a classic breach vector). Together, PAM and access reviews operationalize least privilege as an ongoing process rather than a one-time setup — because the default trajectory of any access system, left alone, is toward too much access held by too many for too long.
Examples
Standing privilege vs. just-in-time (the core PAM idea):
STANDING: admin account has root 24/7
-> compromise the account ANY time = instant root. Large window.
JUST-IN-TIME: admin requests root for a task -> approved for 1 hour -> auto-revoked
-> compromise outside that hour = NO privilege. Tiny window.
+ session is brokered & recorded, credential is vaulted & rotated.
Privilege creep across the joiner-mover-leaver lifecycle:
JOIN: Alice (Support) -> {helpdesk, ticketing}
MOVE: Alice -> Finance -> +{ledger, payments} but helpdesk NOT removed <-- creep
MOVE: Alice -> Management -> +{approvals} finance NOT removed <-- creep
now Alice holds helpdesk + ledger + payments + approvals (toxic combination!)
LEAVE: if offboarding misses her account -> orphaned privileged account = breach path.
Access review catches this: quarterly, the owner re-attests each grant -> revoke stale.
Key Takeaways
- Privilege accumulates and goes stale over time; PAM and access reviews are the governance that keeps access matched to need.
- PAM controls high-value accounts via credential vaulting, session brokering/recording, just-in-time access, and automatic rotation — the goal is to eliminate standing privilege.
- JIT access means even a compromised admin account is usually not currently privileged, shrinking the attack window dramatically.
- Access reviews periodically re-validate every grant ("is this still needed?"), countering privilege creep and satisfying compliance (SOX, ISO 27001, SOC 2).
- The joiner-mover-leaver lifecycle must adjust access on moves (the commonly skipped step) and fully deprovision on departure (orphaned accounts are a classic breach vector).
🧪 Practice
- Explain how just-in-time access reduces the risk of a compromised admin account versus standing privilege.
- Define privilege creep and describe how access reviews counter it.
- Identify which stage of joiner-mover-leaver is most often skipped and the risk it creates.
- Interview-style: "What is 'standing privilege' and why do PAM programs try to eliminate it?" Hint: think about the size of the window during which compromising an account yields active admin rights.
<a id="64-firewalls-and-perimeter-defense"></a>
6.4 Firewalls and Perimeter Defense
Firewalls and related controls enforce a boundary between networks of differing trust, deciding what traffic may cross. This section covers how firewalls inspect traffic (from simple packet filtering to deep application analysis), how to design and write their rules, how to segment networks, and the detection, evasion, and deception that surround the perimeter.
Packet Filtering Fundamentals
Theory
A firewall's most basic job is to look at each packet and decide, based on rules, whether to let it through. Packet filtering is that decision made from the information in packet headers — primarily the Layer 3/4 fields: source and destination IP address, protocol (TCP/UDP/ICMP), and source and destination port. The firewall holds an ordered list of rules, each matching some combination of these fields and specifying an action (accept, drop, or reject), and the packet is tested against the rules until one matches. This is the foundation on which every more sophisticated firewall builds.
The "why" is that the header fields identify who is talking to whom and how, which is enough to express a large fraction of useful policy without touching the packet's contents: "allow anyone to reach the web server on port 443," "block all inbound traffic to the database port," "drop packets from this known-bad network." Because it only reads headers, packet filtering is fast and cheap, which is why it runs at line rate on routers and forms the base layer of defense.
Two distinctions matter immediately. First, drop versus reject: drop silently discards the packet (the sender sees a timeout, learning nothing — stealthier, and the default for internet-facing rules), while reject sends back an error (ICMP unreachable or TCP RST — faster failure for legitimate internal clients, but it confirms the host exists). Second, the inherent limitation of pure packet filtering: because it judges each packet by its headers alone, it cannot understand context (is this packet part of a connection I allowed?) or content (is this allowed port 443 traffic actually malicious?). The first gap is what stateful inspection fixes; the second is what application-layer inspection fixes — making packet filtering the essential but incomplete first layer.
Examples
Packet filtering: match header fields, apply the first matching rule's action.
rule action proto src dst dport
1 ACCEPT tcp any 10.0.0.10 443 (web server)
2 ACCEPT tcp 10.0.0.0/24 10.0.0.20 5432 (internal DB only)
3 DROP any any any any (default deny)
packet: tcp 203.0.113.5 -> 10.0.0.10 : 443 => matches rule 1 => ACCEPT
packet: tcp 203.0.113.5 -> 10.0.0.20 : 5432 => rule 2 needs internal src
=> falls to rule 3 => DROP
# A minimal packet filter with nftables: default deny, allow specific services.
nft add table inet filter
nft 'add chain inet filter input { type filter hook input priority 0; policy drop; }'
nft add rule inet filter input tcp dport 443 accept # match dst port 443 -> accept
nft add rule inet filter input ip saddr 203.0.113.66 drop # block a bad source IP
# DROP (silent, stealthy) vs REJECT (sends an error, confirms host exists):
nft add rule inet filter input tcp dport 23 reject with tcp reset # fast-fail telnet
Key Takeaways
- Packet filtering decides per-packet accept/drop/reject from header fields: source/destination IP, protocol, and source/destination port.
- It is fast and cheap because it reads only headers, making it the base layer of firewalling (runs at line rate on routers).
- Drop silently discards (stealthy, timeout) while reject sends an error (faster failure but confirms the host exists).
- Header-only judgment cannot understand connection context or packet content — its two fundamental limitations.
- Those gaps motivate stateful inspection (context) and application-layer inspection (content).
🧪 Practice
- Write three packet-filter rules to allow inbound HTTPS, allow SSH only from one subnet, and deny everything else.
- Explain when you would use drop versus reject for an internet-facing rule and for an internal one.
- Explain why packet filtering alone cannot tell whether an allowed port-443 packet is legitimate.
- Interview-style: "Given only Layer 3/4 header filtering, why can you block a port but not a specific URL?" Hint: recall which layer carries the URL and whether the firewall is reading that far into the packet.
Stateless vs. Stateful Inspection
Theory
The single most important evolution in firewalling was adding memory. A stateless firewall examines each packet in complete isolation, with no recollection of what came before; a stateful firewall maintains a connection state table and judges each packet in the context of the conversation it belongs to. This difference sounds small but transforms both security and usability, and understanding it explains most modern firewall behavior.
The problem with stateless filtering is the return traffic dilemma. When an internal client connects out to a web server, the reply comes back from the server on an ephemeral high port. A stateless firewall has no memory that the client initiated the connection, so to allow replies it must open a broad rule like "allow all inbound TCP to high ports" — a huge hole an attacker can exploit to reach internal services directly. A stateful firewall solves this cleanly: when it sees the outbound SYN, it records the connection (source/dest IP and port, protocol, state) in its table; when the reply arrives, it recognizes it as part of an established connection and allows it automatically — no broad inbound rule needed. This is why the classic stateful policy is simply "allow established/related, allow specific new inbound, deny the rest."
Statefulness also improves security beyond convenience. Because the firewall tracks the TCP state machine, it can reject packets that violate protocol state — an ACK or data packet for a connection that was never established (a signature of scans and spoofing), or out-of-sequence packets. It can also recognize related connections (like an FTP data channel associated with an allowed FTP control channel). The trade-offs: the state table consumes memory and is itself a target (a SYN/connection flood aims to exhaust it), and stateful inspection still only tracks connection context, not content — it knows a packet belongs to an allowed connection but not whether its payload is malicious. The defensive baseline today is stateful, with stateless filtering reserved for simple, high-throughput, or explicitly bidirectional cases.
| Stateless | Stateful | |
|---|---|---|
| Memory | none (per-packet) | connection state table |
| Return traffic | needs broad inbound rule (risky) | auto-allowed as "established" |
| Protocol-state checks | no | yes (rejects invalid-state packets) |
| Resource cost | minimal | state table (floodable) |
| Typical use | simple/high-speed ACLs | the modern default |
Examples
The return-traffic problem and how state solves it:
Client 10.0.0.5:51000 --SYN--> web 93.184.216.34:443 (outbound allowed)
reply: 93.184.216.34:443 --SYN/ACK--> 10.0.0.5:51000 (inbound!)
STATELESS: must add "allow inbound tcp to ports 49152-65535" = big hole.
STATEFUL: SYN recorded in state table -> the SYN/ACK matches an EXISTING
entry -> allowed automatically. No broad inbound rule needed.
# Stateful policy with nftables: one line handles ALL return traffic safely.
nft 'add chain inet filter input { type filter hook input priority 0; policy drop; }'
nft add rule inet filter input ct state established,related accept # the key line
nft add rule inet filter input ct state invalid drop # bogus-state pkts
nft add rule inet filter input tcp dport {22,443} ct state new accept # new inbound
# "established,related" replaces dozens of fragile stateless return-traffic rules.
Key Takeaways
- Stateless firewalls judge each packet in isolation; stateful firewalls track connections in a state table and judge packets in that context.
- Statefulness solves the return-traffic problem elegantly — reply packets are auto-allowed as "established," avoiding the broad inbound holes stateless filtering requires.
- Stateful inspection also rejects protocol-state violations (e.g. an ACK with no prior handshake) and recognizes related connections.
- The state table costs memory and is a target for connection-flood attacks; stateful inspection still sees context, not content.
- The modern default is stateful ("allow established/related, allow specific new, deny the rest"); stateless is reserved for simple high-speed cases.
🧪 Practice
- Explain the return-traffic problem and how a stateful firewall avoids opening a broad inbound rule.
- Give two security checks a stateful firewall can perform that a stateless one cannot.
- Write the single stateful rule that safely permits all legitimate reply traffic.
- Interview-style: "What resource does a stateful firewall rely on that a stateless one does not, and how can an attacker weaponize that?" Hint: think about what grows with each tracked connection and an attack that creates many half-open ones.
Application-Layer Gateways and Proxies
Theory
Packet and stateful filtering understand addresses, ports, and connections — but not what the traffic actually says. An application-layer gateway (ALG), or proxy firewall, operates at Layer 7: it understands the application protocol (HTTP, SMTP, FTP, DNS) and can inspect, validate, and filter based on the protocol's actual content and semantics. This is a fundamentally different and deeper form of control, and the key architectural idea is that a proxy terminates the connection: the client connects to the proxy, the proxy makes a separate connection to the real server, and nothing flows end-to-end. The client never talks directly to the server at all.
That termination is what gives proxies their power. Because the proxy fully parses the application protocol, it can enforce protocol correctness (reject malformed or smuggled requests), filter on content (block a specific URL, strip dangerous attachments, enforce "only GET and POST"), authenticate users before allowing access, and log the full application-level transaction. It also provides strong isolation: the internal server is never exposed to the client's packets directly, so many lower-layer attacks simply cannot reach it. Proxies come in two orientations: a forward proxy sits in front of clients controlling their outbound access (corporate web filtering, egress control), while a reverse proxy sits in front of servers protecting and load-balancing them (and is the deployment model for most WAFs and CDNs).
The trade-offs are inherent to doing more work. Proxies are slower and more resource-intensive than packet filters because they parse entire protocols and maintain two connections per session, and each proxy is protocol-specific (an HTTP proxy does not understand SMTP), so a proxy firewall needs a module per protocol it handles. The most significant modern tension is encryption: to inspect HTTPS content, a proxy must perform TLS interception (terminating TLS, decrypting, inspecting, re-encrypting) — which requires installing the proxy's CA certificate on clients and raises real privacy and security concerns (it breaks end-to-end encryption and the proxy becomes a high-value target holding plaintext). Despite the cost, application-layer inspection is indispensable precisely because so many attacks now ride inside otherwise-allowed protocols.
Examples
A proxy TERMINATES the connection (no end-to-end path):
client --connection A--> [ PROXY ] --connection B--> server
parses HTTP, applies policy, then relays
Forward proxy: controls CLIENTS' outbound access (web filtering, egress)
Reverse proxy: protects SERVERS (WAF, load balancing, TLS termination)
Because the proxy sees full Layer 7, it can:
- block specific URLs/methods, strip attachments, enforce protocol correctness
- authenticate the user, log the full transaction
Cost: slower, protocol-specific, and needs TLS interception to see HTTPS content.
Packet filter vs proxy, same HTTPS request:
Packet filter: sees tcp 10.0.0.5 -> 93.184.216.34:443 (allow/deny only)
Proxy (with TLS interception):
GET /admin/delete?id=5 HTTP/1.1
Host: app.example.com
-> can block the /admin path, the DELETE semantics, a bad User-Agent, etc.
but requires terminating TLS -> client must trust the proxy's CA.
Key Takeaways
- Application-layer gateways/proxies operate at Layer 7, understanding and filtering on the actual application protocol and content.
- A proxy terminates the connection (client→proxy, proxy→server), so traffic is never end-to-end — giving deep inspection and strong isolation of the real server.
- Forward proxies control clients' outbound access; reverse proxies protect and load-balance servers (the model for WAFs and CDNs).
- They are slower, resource-intensive, and protocol-specific (a module per protocol) compared to packet filters.
- Inspecting HTTPS requires TLS interception, which breaks end-to-end encryption, needs a trusted CA on clients, and makes the proxy a high-value plaintext target.
🧪 Practice
- Explain what "terminating the connection" means for a proxy and why it enables deeper inspection.
- Contrast a forward proxy and a reverse proxy by what each protects.
- Describe why and how a proxy must intercept TLS to filter HTTPS content, and one risk this creates.
- Interview-style: "Why is an application-layer proxy slower than a packet filter, and what does it gain for that cost?" Hint: compare reading a few header fields to parsing an entire protocol and bridging two connections.
Next-Generation Firewalls and WAFs
Theory
Two modern firewall categories answer the reality that attacks hide inside allowed traffic: the Next-Generation Firewall (NGFW) generalizes the firewall into a multi-function Layer 7 platform, and the Web Application Firewall (WAF) specializes entirely in protecting web applications. They are not competitors — they sit at different points and solve different problems — but both represent the shift from "filter by port" to "understand the traffic."
A NGFW combines traditional stateful filtering with capabilities that used to be separate appliances: deep packet inspection (DPI) and application awareness (identifying the actual application regardless of port — recognizing that traffic on port 443 is BitTorrent or a specific SaaS app, not just "HTTPS"), integrated intrusion prevention (IPS), user-identity integration (rules by user/group via directory integration, not just IP), TLS inspection, and often threat-intelligence feeds and malware sandboxing. The core value is policy expressed in meaningful terms — "block the file-sharing application for the marketing group" — rather than brittle port rules that applications evade by port-hopping onto 443. The cost is complexity, performance impact (especially with TLS inspection), and the fact that it is a single, feature-rich appliance that is itself a critical dependency and attack surface.
A WAF is a reverse proxy dedicated to HTTP/HTTPS, inspecting requests and responses to block web-application attacks — SQL injection, cross-site scripting, path traversal, and the rest of the web-vulnerability catalog covered in later chapters. It understands HTTP deeply: parameters, headers, cookies, bodies. WAFs operate in two philosophies mirroring the allowlist/blocklist distinction: a negative (blocklist) model blocks known-malicious patterns (signatures, like the OWASP Core Rule Set) — easy to deploy but defeatable by novel payloads and prone to false positives; a positive (allowlist) model permits only known-good request shapes — far stronger but requiring per-application tuning. The critical framing for a WAF is that it is a mitigation, not a cure: it reduces exposure and buys time (virtual patching of a known vuln until code is fixed) but can be bypassed through encoding tricks and should never replace secure coding. The clean way to hold all of this together: a NGFW governs which applications and users communicate across the network; a WAF scrutinizes the content of web requests to one application; defense in depth uses both.
| NGFW | WAF | |
|---|---|---|
| Scope | all network traffic, many protocols | HTTP/HTTPS to web apps only |
| Position | network boundary/segment | reverse proxy in front of web apps |
| Blocks | apps, users, intrusions, malware | SQLi, XSS, traversal, web attacks |
| Model | application/identity-aware policy | signature (negative) or allowlist (positive) |
| Role | broad network policy enforcement | web-app mitigation (not a cure) |
Examples
NGFW vs WAF: different jobs, often deployed together.
Internet
|
[ NGFW ] -- app & user aware: "marketing group: no file-sharing app on any port;
| IPS on; TLS inspection; block known-bad IPs"
[ WAF (reverse proxy) ] -- HTTP-aware: inspects each request for SQLi/XSS/traversal
|
[ Web app ] <- WAF virtually patches a known vuln until code is fixed.
WAF models (the allowlist/blocklist distinction applied to HTTP):
NEGATIVE (blocklist): block requests matching bad patterns (OWASP CRS signatures)
+ quick to deploy - bypassable by novel/encoded payloads, false positives
e.g. block param =~ /union\s+select/i
POSITIVE (allowlist): permit only known-good shapes
e.g. /search?q=[a-z0-9 ]{1,64} everything else rejected
+ far stronger - must be tuned per application
Key Takeaways
- NGFWs add deep packet inspection, application and user-identity awareness, integrated IPS, and TLS inspection to stateful filtering — enabling policy in meaningful terms rather than brittle port rules.
- NGFWs identify the real application regardless of port, defeating the port-hopping that evades classic firewalls.
- WAFs are HTTP/HTTPS-specialized reverse proxies that block web-application attacks (SQLi, XSS, traversal) by deeply parsing requests.
- WAFs use a negative (signature/blocklist) model — easy but bypassable — or a positive (allowlist) model — stronger but needing per-app tuning.
- A WAF is a mitigation and virtual-patching tool, not a replacement for secure coding; NGFW governs which apps/users communicate, WAF scrutinizes web-request content — use both.
🧪 Practice
- List three capabilities a NGFW adds over a traditional stateful firewall.
- Explain how application awareness defeats an app that hops onto port 443 to evade port rules.
- Contrast a WAF's negative and positive security models and when you would choose each.
- Interview-style: "Why is a WAF described as a mitigation rather than a fix for SQL injection?" Hint: consider what the underlying vulnerability still is, and how encoding tricks relate to signature-based blocking.
Rule Design, Ordering, and Default Deny
Theory
A firewall is only as good as its ruleset, and rulesets fail far more often from design mistakes than from the firewall's technology. Two principles govern sound rule design, and both trace back to the foundational security ideas from Chapter 1: default deny (the baseline must reject everything not explicitly permitted) and correct ordering (rules are evaluated top-to-bottom and the first match usually wins, so order is policy).
Default deny (also "deny by default" or "whitelisting") means the final, catch-all rule drops everything, and you add explicit allow rules only for traffic you have decided to permit. The alternative — default allow with a blocklist of bad things — is the whack-a-mole failure described in Chapter 1: you can never enumerate all bad traffic, and anything you forget to block gets through. Default deny inverts this: anything you forget to allow is simply blocked, which fails safe. It is the single most important firewall design decision, and it should be true at every boundary.
Rule ordering matters because most firewalls apply the first matching rule and stop. This has two consequences. First, specific rules must come before general ones: if a broad "allow all from 10.0.0.0/8" sits above a specific "deny 10.0.0.66," the deny never fires because the allow matched first — a silent, dangerous mistake. Second, ordering affects performance (place high-traffic rules early) but correctness must never be sacrificed for it. Good rule design also includes least privilege (allow the narrowest source/destination/port/protocol that works, not any), logging (log denies, and log sensitive allows, so you have evidence — but beware logging so much that real events drown), documentation (comment every rule's purpose and owner, because an unexplained rule is one nobody dares remove), and regular review (rulesets accumulate stale, overly-broad, and shadowed rules — "rule rot" — that must be periodically audited and pruned). Two specific pathologies to recognize: a shadowed rule (one that can never match because an earlier rule always catches its traffic first) and an overly permissive rule (any any allow lurking where a narrow rule was intended). The discipline is the same as all access control: least privilege, fail closed, and keep the policy small enough to understand.
Examples
Ordering is policy: first match wins, so specific before general.
WRONG (the deny never fires): RIGHT (specific first):
1 ALLOW src 10.0.0.0/8 -> any 1 DENY src 10.0.0.66 -> any
2 DENY src 10.0.0.66 -> any <-- 2 ALLOW src 10.0.0.0/8 -> any
shadowed! rule 1 already matched 3 DENY any -> any (default deny)
3 DENY any -> any
Default deny: the LAST rule must drop everything not explicitly allowed,
so anything you forgot to permit fails safe (blocked), not open.
# A well-ordered, documented, default-deny input policy (nftables).
nft 'add chain inet filter input { type filter hook input priority 0; policy drop; }' # DEFAULT DENY
nft add rule inet filter input ct state established,related accept # return traffic
nft add rule inet filter input iif lo accept # loopback
nft add rule inet filter input ip saddr 198.51.100.66 drop # SPECIFIC deny first
nft add rule inet filter input tcp dport 22 ip saddr 10.0.0.0/24 accept # least-privilege SSH
nft add rule inet filter input tcp dport 443 accept # public HTTPS
nft add rule inet filter input log prefix "DENIED: " drop # log what the default deny drops
Key Takeaways
- Rulesets fail more from design mistakes than technology; two principles govern them: default deny and correct ordering.
- Default deny (allow only what is explicitly permitted, drop the rest) fails safe — forgotten traffic is blocked, not allowed — unlike the unwinnable default-allow blocklist.
- First-match-wins means order is policy: specific rules must precede general ones, or the general rule shadows and nullifies the specific one.
- Apply least privilege per rule (narrowest source/dest/port/protocol), log denies and sensitive allows, and document every rule's purpose and owner.
- Audit regularly for rule rot: shadowed rules (can never match) and overly-permissive rules (
any any allow) accumulate and must be pruned.
🧪 Practice
- Explain why default deny fails safe and default allow does not, in firewall terms.
- Spot the bug: a ruleset has "allow all from the office subnet" above "deny the compromised office host." Fix it.
- Define a shadowed rule and describe how you would find one in a large ruleset.
- Interview-style: "Why does rule order matter in most firewalls, and what is the consequence of placing a broad allow above a specific deny?" Hint: recall first-match-wins and what 'shadowed' means for the deny.
iptables/nftables and pf Configuration
Theory
Knowing firewall concepts is not enough; on real systems you configure them with specific tools, and the dominant ones are iptables/nftables on Linux and pf on BSD/macOS. They differ in syntax but share the same model you now understand — ordered rules, matches on header fields, stateful connection tracking, default-deny policy — so the goal here is to map the concepts onto the concrete tools and recognize their structure.
On Linux, the kernel's packet-filtering framework is Netfilter, and it has two generations of front-end. iptables is the long-established tool, organized into tables (filter, nat, mangle) and chains (built-in hook points: INPUT for traffic to the host, OUTPUT from the host, FORWARD through the host as a router, plus PREROUTING/POSTROUTING for NAT). Each chain has an ordered list of rules and a default policy. nftables is its modern replacement — one unified tool (nft) with a cleaner syntax, better performance, atomic rule updates, and sets/maps for compact rules — and it is now the default on current distributions, though iptables syntax remains ubiquitous in documentation and scripts. pf (Packet Filter), from OpenBSD and used across the BSDs and macOS, is admired for its readable, declarative configuration file (pf.conf) with named macros and tables.
The practical knowledge that transfers across all of them: define a default-deny policy on the input chain, accept established/related connections (stateful return traffic), accept loopback, then add least-privilege allows for the specific services you run, and log the drops. The hooks/chains encode where in the packet's journey a rule applies — INPUT for the host itself versus FORWARD for routed traffic is a distinction people constantly get wrong (a Linux router's rules for traffic passing through it go in FORWARD, not INPUT). NAT rules live in their own table/chains (nat table, PREROUTING for destination NAT/port forwarding, POSTROUTING for source NAT/masquerade). Mastering one of these tools means you can read and audit the others, because the underlying model is identical.
Examples
# nftables (modern Linux default): a complete host firewall in one ruleset.
nft add table inet filter
nft 'add chain inet filter input { type filter hook input priority 0; policy drop; }'
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input iif lo accept
nft add rule inet filter input tcp dport { 22, 443 } accept # set = compact rule
nft add rule inet filter input log prefix "nft-drop: " counter drop
nft list ruleset # review the whole policy
# iptables equivalent (still everywhere in docs/scripts):
iptables -P INPUT DROP # default-deny policy
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 22,443 -j ACCEPT
pf (BSD/macOS) -- readable declarative pf.conf:
ext_if = "em0"
table <badhosts> persist { 198.51.100.66 }
set skip on lo0
block in all # default deny inbound
pass out keep state # stateful outbound (return traffic auto)
block in quick from <badhosts> # specific deny first ("quick" = stop here)
pass in on $ext_if proto tcp to port { 22 443 } keep state # least-privilege allows
Chains/hooks tell you WHERE a rule applies:
INPUT = traffic TO this host FORWARD = routed THROUGH this host
OUTPUT = traffic FROM this host (router rules go in FORWARD, not INPUT!)
Key Takeaways
- iptables/nftables (Linux) and pf (BSD/macOS) differ in syntax but share the model: ordered rules, header matches, stateful tracking, default-deny policy.
- Linux filtering is Netfilter; iptables organizes it into tables (filter/nat/mangle) and chains (INPUT/OUTPUT/FORWARD/PRE-/POSTROUTING); nftables is the modern unified replacement with sets and atomic updates.
- pf is valued for a readable, declarative config with macros and tables.
- The transferable pattern: default-deny input, accept established/related, accept loopback, add least-privilege service allows, log drops.
- Chains/hooks encode where a rule applies — INPUT is for the host, FORWARD is for routed traffic (a common mistake); NAT lives in its own table (PREROUTING for DNAT, POSTROUTING for SNAT/masquerade).
🧪 Practice
- Write an nftables input chain with default deny, established/related accept, loopback, and SSH-from-one-subnet.
- Translate that ruleset into iptables commands.
- Explain when a rule belongs in FORWARD rather than INPUT on a Linux router.
- Interview-style: "On a Linux box acting as a router, your INPUT rules work for traffic to the box but not for traffic passing through it. Why?" Hint: recall which chain handles routed (through-the-host) traffic.
NAT, Port Forwarding, and Their Security Impact
Theory
NAT was introduced in the networking refresher as an addressing mechanism; here the focus is its security impact, which is widely misunderstood in both directions. NAT rewrites addresses as packets cross a boundary, and in doing so it changes what is reachable — but it was designed to conserve IPv4 addresses, not to enforce security, and conflating the two leads to real exposure.
The security side effects of NAT are genuine but incidental. Source NAT (SNAT / masquerade) rewrites the private source address of outbound traffic to the router's public address; as a byproduct, it hides the internal network topology (external observers see one address, not your internal structure) and — because the NAT table only has entries for connections initiated from inside — unsolicited inbound connections have nowhere to be translated to, so they are effectively dropped. This looks like a firewall, which is the dangerous misconception: NAT's "protection" is a consequence of there being no mapping, not a policy decision, and it provides no filtering, logging, or control. The moment you add inbound mappings, it evaporates.
Those inbound mappings are port forwarding (DNAT, destination NAT): a rule that sends traffic arriving at the public IP on a given port to a specific internal host and port (public:443 → 10.0.0.10:443), which is how you expose an internal service to the internet. Each port forward is a deliberate hole punched in NAT's incidental protection, and it is a frequent source of accidental exposure — forwarding a management port (RDP 3389, database 3306) to the internet is a classic breach origin. The automated version, UPnP, lets internal applications request their own port forwards without administrator approval, which is convenient and a notorious security risk (malware and misconfigured devices expose themselves). Two more considerations round out the picture: NAT complicates some security operations (it obscures which internal host originated traffic, hampering incident investigation unless NAT logs are kept), and IPv6, with its vast address space, largely eliminates the need for NAT — which means hosts can be globally addressable and the "NAT as accidental firewall" crutch disappears, making an explicit firewall mandatory. The correct mental model throughout: NAT is addressing; a firewall is policy; never rely on the former for the latter.
Examples
NAT's "protection" is the absence of a mapping, not a policy:
Outbound (SNAT): 10.0.0.5:51000 -> rewritten -> 203.0.113.9:40001 -> server
table entry created; reply maps back. Internal topology hidden.
Unsolicited inbound: attacker -> 203.0.113.9:3389
NO table entry for this -> nowhere to translate to -> dropped.
Looks like a firewall, but it is just "no mapping exists".
Port forward (DNAT): 203.0.113.9:443 -> 10.0.0.10:443 <- a DELIBERATE hole
now that service is internet-exposed. Forward a mgmt port by mistake = breach.
# NAT configuration and its security-relevant choices (nftables).
# SNAT/masquerade for outbound (addressing, not security):
nft add rule inet nat postrouting oif "eth0" masquerade
# Port forward (DNAT) -- each line is an intentional exposure, so be deliberate:
nft add rule inet nat prerouting iif "eth0" tcp dport 443 dnat to 10.0.0.10:443
# DANGER patterns to audit for: management ports forwarded to the internet
# dport 3389 dnat ... (RDP) dport 3306 dnat ... (MySQL) -> almost always wrong
# Disable UPnP on gateways: it lets apps/malware open their own forwards unasked.
Key Takeaways
- NAT is an addressing mechanism (IPv4 conservation), not a security control; its protective effects are incidental side effects, not policy.
- SNAT/masquerade hides internal topology and drops unsolicited inbound traffic only because no translation mapping exists — there is no filtering, logging, or decision behind it.
- Port forwarding (DNAT) deliberately exposes an internal service; each forward is a hole, and forwarding management/database ports is a classic breach origin.
- UPnP automates port forwarding without admin approval and is a notorious risk — disable it on gateways.
- NAT complicates incident attribution (keep NAT logs), and IPv6 removes the need for NAT, making an explicit firewall mandatory rather than relying on NAT's accidental shielding.
🧪 Practice
- Explain precisely why NAT drops unsolicited inbound traffic and why that is not the same as a firewall rule.
- Describe the risk of UPnP and why you would disable it on a home or office gateway.
- Explain why "NAT as a firewall" becomes dangerous advice in an IPv6 network.
- Interview-style: "A team says their internal service is safe because it is behind NAT. What is the flaw in that reasoning?" Hint: distinguish 'no mapping currently exists' from 'a policy forbids access,' and consider what one port-forward or UPnP request changes.
Network Segmentation, VLANs, and DMZ Design
Theory
Segmentation is the architectural application of a single idea: contain the blast radius. A flat network, where every host can reach every other host, means one compromised machine can be used to attack all the rest — lateral movement is trivial. Segmentation divides the network into zones separated by controls, so that compromising one zone does not grant access to others. It is defense in depth made concrete at the network layer, and it is one of the highest-impact architectural decisions for limiting how far an intrusion spreads.
The techniques operate at different layers. VLANs (Virtual LANs) segment at Layer 2, logically dividing one physical switch infrastructure into separate broadcast domains (so the finance VLAN and the guest VLAN cannot see each other's traffic even on the same switch), with a router/firewall controlling traffic between VLANs. Subnetting and firewalled zones segment at Layer 3, placing firewalls between networks to enforce which zones may talk to which. The classic design pattern is the DMZ (Demilitarized Zone): a separate zone for internet-facing services (web, mail, DNS) that sits between the hostile internet and the trusted internal network, so that a compromised public server is in the DMZ, not inside. The DMZ is typically built with firewall rules that allow the internet to reach DMZ services, allow the DMZ to reach only specific internal resources (e.g. the web server may reach only the database, on only the database port), and never allow the DMZ to freely initiate connections inward — so a breached web server is trapped.
The modern evolution is microsegmentation: rather than a few coarse zones, isolate workloads down to the individual host or application, with fine-grained policy controlling every flow (enabled by host firewalls, SDN, and cloud security groups). This is the network expression of the Zero Trust principle (later in the course) — "never trust, always verify," applied so that even hosts on the same segment must be explicitly authorized to communicate, eliminating the "soft chewy inside" of traditional perimeter designs. Across all these techniques the goals are the same: limit lateral movement (a foothold in one zone cannot reach others), reduce attack surface (each zone exposes only what it must), contain breaches, and enforce least privilege between zones. A useful caution: VLANs provide logical separation but share physical hardware, so VLAN hopping attacks (exploiting trunk misconfiguration or double-tagging) can defeat weak VLAN setups — segmentation must be configured correctly, not merely present.
Examples
Three-zone design with a DMZ (contain the blast radius):
INTERNET
| (firewall: allow 80/443 to DMZ only)
+--------- DMZ ---------+ public web/mail/DNS live here
| web server, mail, DNS |
+----------------------+
| (firewall: DMZ -> internal ONLY to DB:5432; NEVER DMZ -> internal freely)
+------ INTERNAL -------+ user workstations, file servers
| finance VLAN | HR VLAN| inter-VLAN traffic via firewall only
+----------------------+
Compromise the web server -> attacker is stuck in the DMZ, can reach only DB:5432.
# Enforcing DMZ containment with firewall rules (concept via nftables FORWARD):
# Internet may reach DMZ web server on 443:
nft add rule inet filter forward ip daddr 10.1.0.10 tcp dport 443 accept
# DMZ web server may reach ONLY the internal DB on ONLY 5432:
nft add rule inet filter forward ip saddr 10.1.0.10 ip daddr 10.2.0.20 tcp dport 5432 accept
# Everything else between zones is denied by the default-deny FORWARD policy:
nft 'add chain inet filter forward { type filter hook forward priority 0; policy drop; }'
# Result: a breached DMZ host cannot pivot into the internal network at large.
Key Takeaways
- Segmentation contains the blast radius: dividing a network into controlled zones stops one compromise from reaching everything (limiting lateral movement).
- VLANs segment at Layer 2 (logical broadcast domains on shared switches); subnets/firewalled zones segment at Layer 3; a router/firewall controls traffic between them.
- A DMZ isolates internet-facing services between the internet and the internal network, with rules that trap a compromised public server (it may reach only specific internal resources, never inward freely).
- Microsegmentation isolates down to individual workloads with per-flow policy — the network expression of Zero Trust, eliminating implicit same-segment trust.
- VLANs are logical on shared hardware and can be defeated by VLAN hopping if misconfigured — segmentation must be configured correctly, not just present.
🧪 Practice
- Explain how network segmentation limits lateral movement, with a concrete before/after example.
- Design the firewall rules for a DMZ web server that must serve the internet and reach one internal database.
- Contrast VLAN segmentation with microsegmentation and relate the latter to Zero Trust.
- Interview-style: "Why is a flat internal network dangerous even behind a strong perimeter firewall?" Hint: think about what a single phished workstation can reach once it is inside, and the 'soft chewy center' problem.
Network Access Control (NAC)
Theory
Firewalls and segmentation control traffic between networks, but they assume the devices on a network belong there. Network Access Control (NAC) addresses a different question: should this device be allowed onto the network at all, and with what level of access? It enforces policy at the point of connection — the moment a laptop plugs into an Ethernet port or joins Wi-Fi — rather than after the device is already inside. The motivation is that an unmanaged, infected, or rogue device connected to an internal network bypasses the perimeter entirely; NAC moves the trust decision to the edge.
NAC makes two kinds of checks. Authentication (who/what is this device and user?) is typically enforced with 802.1X, the port-based access-control standard: before a switch port or wireless association passes any traffic, the device (supplicant) must authenticate through the switch/AP (authenticator) to a RADIUS server (authentication server) — the EAP-over-802.1X exchange. Until authentication succeeds, the port carries only authentication traffic; no network access is granted to an unauthenticated device. Posture assessment (is this device healthy enough to be trusted?) checks compliance: is the OS patched, is antivirus running and current, is disk encryption on, is it a managed corporate device? Based on both checks, NAC assigns the device to an appropriate outcome — full access, a restricted VLAN, a quarantine/remediation network (where a non-compliant device can be patched before being admitted), or denial.
NAC is the practical enforcement point for several policies that matter operationally: keeping rogue and BYOD devices off sensitive segments, ensuring only compliant endpoints touch the network (tying into the endpoint-hardening chapter), and dynamically placing devices into the right segment (connecting to the segmentation topic — NAC is often what assigns a device to its VLAN). Its challenges are real: 802.1X requires supplicant support and infrastructure that can authenticate every port, devices that cannot do 802.1X (printers, IoT, cameras) need exceptions like MAC Authentication Bypass (which is weak, since MACs are spoofable), and overly strict posture policies create help-desk friction. Conceptually, NAC is an early and important embodiment of the Zero Trust idea applied to network admission: do not grant access based on physical connection alone; verify identity and health first.
Examples
802.1X: no network access until authentication succeeds.
SUPPLICANT AUTHENTICATOR AUTH SERVER
(laptop) ---EAP---> (switch/AP) ---RADIUS---> (RADIUS -> directory)
| port is "unauthorized": only EAP passes, no data traffic
| auth OK + posture check (patched? AV on? managed?)
v
outcome: full access | restricted VLAN | quarantine/remediate | deny
NAC decision flow combining authentication and posture:
device connects
-> 802.1X authenticate (identity) fail -> DENY / guest VLAN
-> posture check (OS patch, AV, encryption)
compliant -> assign production VLAN (full access)
non-compliant-> quarantine VLAN (can reach only patch servers)
-> no 802.1X support (printer/IoT) -> MAB (MAC auth) -> restricted IoT VLAN
(MAB is weak: MACs are spoofable -> isolate these devices tightly)
Key Takeaways
- NAC decides whether a device may join the network and with what access, enforcing policy at the point of connection rather than after the device is inside.
- It combines authentication (commonly 802.1X: supplicant → authenticator → RADIUS server, with no access until auth succeeds) and posture assessment (patch level, antivirus, encryption, managed status).
- Based on both checks it assigns full access, a restricted VLAN, a quarantine/remediation network, or denial — and often places devices into the correct segment.
- NAC keeps rogue/BYOD and non-compliant devices off sensitive segments, tying network admission to endpoint health.
- Challenges include supporting non-802.1X devices (MAC Authentication Bypass, which is spoofable and weak) and avoiding overly strict posture policies; NAC is an early embodiment of Zero Trust network admission.
🧪 Practice
- Name the three 802.1X roles and describe what traffic a port allows before authentication succeeds.
- Explain the difference between authentication and posture assessment in NAC, with an example of each check.
- Describe what a quarantine/remediation VLAN is for and when a device is placed there.
- Interview-style: "A printer cannot run an 802.1X supplicant. How is it admitted, and why is that method weak?" Hint: recall MAC Authentication Bypass and whether a MAC address can be forged.
Firewall Evasion Techniques and Limitations
Theory
Understanding how firewalls are evaded is essential both to appreciate their limits and to configure them correctly — a firewall gives a false sense of security if you do not know what it cannot do. The unifying insight is that a firewall enforces policy based on what it can see and understand, so every evasion technique is fundamentally about presenting traffic in a form the firewall does not inspect, does not understand, or is configured to permit.
The techniques cluster by the limitation they exploit. Fragmentation splits an attack across multiple IP fragments so that no single fragment matches a signature, relying on the firewall failing to reassemble before inspecting (modern firewalls reassemble, but misconfigured or legacy ones do not). Tunneling and encapsulation hide forbidden traffic inside an allowed protocol: DNS tunneling (exfiltrating data in DNS queries, which are almost always allowed outbound), ICMP tunneling (data in ping payloads), and HTTP/HTTPS tunneling (wrapping anything in web traffic, since 80/443 are universally open) — these exploit the firewall's trust in the carrier protocol. Encryption is the broadest limitation: a firewall that does not perform TLS inspection sees only that encrypted traffic is flowing, not what it contains, so malware using HTTPS for command-and-control passes a content-blind firewall freely. Port manipulation runs services on unexpected ports (SSH on 443) to slip past port-based rules, and source manipulation/spoofing or using allowed ports (tunneling out over 443) exploits overly permissive egress rules. More advanced evasion includes protocol ambiguity (crafting packets that the firewall and the target interpret differently, so the firewall's view of "safe" does not match what the target actually processes).
The deeper point is a set of fundamental limitations no firewall overcomes. A firewall cannot inspect what it cannot decrypt (encrypted traffic without interception). It cannot stop attacks that ride entirely within explicitly allowed traffic (a SQL injection inside a permitted HTTPS request to your web server — the firewall correctly allowed port 443; the attack is in the content, needing a WAF). It does nothing against insider threats or compromised endpoints already inside the perimeter (segmentation and Zero Trust address this). And it is only as good as its rules — a misconfiguration or an overly permissive egress policy is the most common "evasion" of all. The practical lessons: enforce egress filtering (control outbound traffic too, not just inbound — this is what catches tunneling and C2), use defense in depth (firewall plus IDS/IPS plus WAF plus endpoint controls), inspect encrypted traffic where policy allows, and never treat the firewall as a single sufficient control.
Examples
Evasion = present traffic the firewall won't inspect/understand/block:
Fragmentation: split payload across IP fragments -> no fragment matches sig
DNS tunneling: data encoded in subdomain queries -> dns.allowed, data leaves
e.g. <base32-data>.exfil.attacker.com (looks like DNS lookups)
HTTPS tunneling: C2 inside TLS on 443 -> content-blind firewall sees only "HTTPS"
Port manipulation: run SSH on 443 -> port-based rule for "web" lets it through
Protocol ambiguity: firewall and host disagree on how to parse -> "safe" to one,
malicious to the other.
What a firewall fundamentally CANNOT do (and the right additional control):
can't see inside encrypted traffic -> TLS inspection / endpoint controls
can't block attacks in ALLOWED traffic -> WAF (web), IPS (signatures)
can't stop insiders / internal hosts -> segmentation, Zero Trust
only as good as its rules -> egress filtering, review, least privilege
EGRESS FILTERING is the highest-value lesson: controlling OUTBOUND traffic
catches tunneling and C2 that inbound-only firewalls miss entirely.
Key Takeaways
- Every firewall evasion presents traffic in a form the firewall does not inspect, does not understand, or is configured to permit.
- Techniques: fragmentation (defeats non-reassembling inspection), tunneling inside allowed protocols (DNS/ICMP/HTTPS), encryption (content-blind without TLS inspection), port manipulation, and protocol ambiguity.
- Fundamental limits: a firewall cannot inspect undecrypted traffic, cannot block attacks inside explicitly allowed traffic (needs a WAF/IPS), and does nothing against insiders or already-compromised internal hosts.
- A firewall is only as good as its rules — overly permissive egress policy is the most common real-world "evasion."
- Enforce egress filtering (control outbound traffic — it catches tunneling and C2), use defense in depth, and never rely on the firewall as a single sufficient control.
🧪 Practice
- Explain how DNS tunneling exfiltrates data past a firewall and why egress filtering helps detect it.
- Describe why an encrypted C2 channel over 443 passes a firewall that does not do TLS inspection.
- Give an attack that a correctly-configured firewall cannot stop and name the control that can.
- Interview-style: "Your firewall blocks all inbound except 443, yet a host is beaconing to an attacker. How, and what control would have caught it?" Hint: the firewall never controlled outbound — think about what egress filtering inspects.
Intrusion Detection vs. Prevention Systems
Theory
Firewalls decide what traffic may pass based on policy; intrusion detection and prevention systems (IDS/IPS) go further by analyzing traffic (and host activity) for signs of attack, not just policy violation. The difference between the two is one of the most tested distinctions in the field, and it comes down to a single question: does the system just watch and alert, or can it actively block?
An IDS (Intrusion Detection System) is passive — it monitors traffic (usually from a copy via a SPAN port or TAP), identifies suspicious or malicious activity, and generates alerts, but it sits out of band and cannot stop the traffic. An IPS (Intrusion Prevention System) is active — it sits inline in the traffic path and can drop, reset, or block malicious traffic in real time, preventing the attack rather than merely reporting it. The deployment position is the defining architectural difference: out-of-band (IDS, sees a copy, cannot interfere) versus inline (IPS, traffic flows through it, can intervene).
This leads directly to the central trade-off. An IPS is more powerful (it stops attacks) but carries two risks an IDS does not: because it is inline, it is a potential point of failure and a bottleneck (if it dies or is overwhelmed, it can take down connectivity — hence "fail open" vs "fail closed" design decisions), and a false positive on an IPS blocks legitimate traffic, causing an outage, whereas a false positive on an IDS merely generates a spurious alert. This is why some organizations run detection in IPS-capable hardware but in alert-only mode for rules they do not fully trust, graduating rules to blocking only once tuned. There are also host-based (HIDS/HIPS, monitoring a single system's logs, files, and behavior) and network-based (NIDS/NIPS, monitoring network traffic) variants — complementary, since one sees the wire and the other sees what actually happened on the endpoint. The detection methods an IDS/IPS uses (signatures vs anomalies) are the subject of the next topic; the key concept here is the detect-vs-prevent distinction and its operational consequences.
| IDS | IPS | |
|---|---|---|
| Action | detect and alert | detect and block |
| Position | out of band (sees a copy) | inline (traffic flows through) |
| Can stop an attack? | no | yes |
| False-positive impact | spurious alert | blocked legitimate traffic (outage) |
| Availability risk | none (passive) | bottleneck / point of failure |
Examples
Deployment position IS the difference:
IDS (out of band, passive): IPS (inline, active):
traffic ====================> traffic ===[ IPS ]===>
\ (copy via SPAN) |
[ IDS ] -> ALERT +-> can DROP/RESET/BLOCK
cannot stop the packet stops the attack, but:
- false positive = outage
- failure = bottleneck (fail open/closed?)
A Snort/Suricata rule in each mode (same signature, different consequence):
alert tcp any any -> 10.0.0.10 80 (msg:"SQLi attempt"; content:"union select"; ...)
^ IDS mode: logs an ALERT, traffic still reaches the server
drop tcp any any -> 10.0.0.10 80 (msg:"SQLi blocked"; content:"union select"; ...)
^ IPS mode (inline): DROPS the packet -> but a false match blocks a real user.
Practice: run new rules as 'alert' first, promote to 'drop' only once tuned.
Key Takeaways
- IDS detects and alerts (passive, out of band, sees a copy of traffic) — it cannot stop an attack.
- IPS detects and blocks (active, inline, traffic flows through it) — it prevents attacks in real time.
- Deployment position is the defining difference: out-of-band versus inline.
- The IPS trade-off: it stops attacks but a false positive blocks legitimate traffic (outage), and being inline makes it a potential bottleneck/point of failure (fail-open vs fail-closed design).
- Host-based (HIDS/HIPS) and network-based (NIDS/NIPS) variants are complementary; tune new rules in alert mode before promoting them to blocking.
🧪 Practice
- State the core difference between IDS and IPS and the deployment position each implies.
- Explain why a false positive is far more serious on an IPS than on an IDS.
- Describe the complementary roles of a network IPS and a host IDS during the same attack.
- Interview-style: "Why might an organization deploy a capable IPS but run many of its rules in alert-only mode?" Hint: think about the cost of a false positive when the device is inline and can block real traffic.
Signature-Based vs. Anomaly-Based Detection
Theory
Whether a system is an IDS or an IPS, it must decide what counts as malicious, and there are two fundamentally different ways to make that decision — signature-based and anomaly-based detection. They have complementary strengths and weaknesses, and mature deployments use both, so understanding the trade-off is more useful than picking a winner.
Signature-based detection (also "misuse detection") matches traffic or behavior against a database of known-bad patterns — the exploit's byte sequence, a malware hash, a known-malicious URL, a specific attack string. It is the antivirus model applied to the network. Its strengths are precision and clarity: when a signature matches, you know exactly what was detected, false positives are low, and the alert is immediately actionable. Its fatal limitation is in the name — it can only detect what it has a signature for, so it is blind to novel (zero-day) attacks and to known attacks that have been modified enough to break the signature. It also requires constant signature updates, and attackers specifically craft payloads to evade signatures (polymorphism, encoding).
Anomaly-based detection takes the inverse approach: it builds a baseline of normal behavior (normal traffic volumes, protocols, connection patterns, user activity) and flags deviations from it. Its great strength is the complement of signature detection's weakness: because it looks for abnormality rather than known badness, it can detect novel attacks, zero-days, and insider threats that no signature covers — a user suddenly downloading gigabytes at 3 a.m., a server initiating outbound connections it never made before. Its weakness is also the inverse: high false-positive rates, because "different from normal" is not the same as "malicious" (legitimate but unusual activity triggers alerts), and defining/maintaining an accurate baseline is hard, especially in dynamic environments. There is also the risk that an attacker can slowly poison the baseline (train the system to accept malicious activity as normal). Modern behavioral/ML-based detection is a sophisticated form of anomaly detection, and the overwhelming consensus is to combine the two: signatures for efficient, precise catching of the known, and anomaly detection for the unknown — layered so each covers the other's blind spot.
| Signature-based | Anomaly-based | |
|---|---|---|
| Detects by | matching known-bad patterns | deviation from a normal baseline |
| Catches novel/zero-day? | no (blind to the unknown) | yes (its key strength) |
| False positives | low | high |
| Alert clarity | precise, actionable | often ambiguous, needs triage |
| Maintenance | constant signature updates | baseline tuning, drift management |
Examples
Same intrusion, two detection philosophies:
SIGNATURE: "does this match a KNOWN attack pattern?"
content:"'; DROP TABLE" -> matches -> ALERT (precise, but misses novel SQLi)
ANOMALY: "is this DIFFERENT from normal?"
baseline: web server receives traffic, never SENDS outbound to new IPs
observed: web server opens 500 outbound connections to a foreign IP
-> deviation -> ALERT (catches the unknown C2, but may false-positive on
a legitimate new integration)
Why you need both (each covers the other's blind spot):
known exploit, exact bytes -> signature catches it; anomaly may miss (small)
zero-day, never-seen payload -> signature MISSES; anomaly catches the deviation
insider slowly exfiltrating -> signature MISSES; anomaly flags unusual volume
attacker poisons the baseline -> anomaly weakened; signatures still fire on known IOCs
=> layer them: precision for the known + coverage for the unknown.
Key Takeaways
- Signature-based detection matches known-bad patterns: precise, low false positives, immediately actionable — but blind to novel/zero-day attacks and needing constant updates.
- Anomaly-based detection flags deviations from a learned baseline of normal: able to catch zero-days and insider threats — but with high false positives and hard-to-maintain baselines.
- The two are mirror images — signatures catch the known, anomalies catch the unknown — so mature deployments combine them.
- Signature detection is evaded by polymorphism/encoding; anomaly detection can be defeated by slowly poisoning the baseline.
- Behavioral/ML detection is advanced anomaly detection; layering both so each covers the other's blind spot is the standard practice.
🧪 Practice
- Explain why signature-based detection cannot catch a zero-day and why anomaly-based detection can.
- Explain why anomaly-based detection suffers high false positives and give a benign example that would trigger it.
- Describe a layered deployment using both methods and what each contributes.
- Interview-style: "An attacker gradually increases a compromised host's nightly data transfer over weeks. Which detection method is at risk, and why?" Hint: think about how a baseline is learned and what 'poisoning' it means.
Honeypots and Deception Technology
Theory
Every control so far is about blocking or detecting attacks on real assets. Deception technology inverts the logic: it deliberately plants fake assets designed to be attacked, so that any interaction with them is, by definition, suspicious. A honeypot is a decoy system — a fake server, database, or service with no legitimate business purpose — placed where an attacker might find it. Because no real user has any reason to touch it, there are essentially no false positives: a connection to the honeypot is a high-confidence signal of reconnaissance, lateral movement, or compromise. This is deception's defining advantage — it produces rare, high-fidelity alerts in a world drowning in noisy ones.
Honeypots are classified by interaction level, which trades realism against risk. A low-interaction honeypot emulates just enough of a service to detect and log connection attempts (it fakes a login banner, records the attempt, but offers nothing real to exploit) — safe and cheap, good for detecting scanning, but easily fingerprinted by a careful attacker. A high-interaction honeypot is a real (or realistic) system that lets the attacker actually interact, run commands, and reveal their tools, techniques, and intent — far richer intelligence, but dangerous, because a real exploitable system can be used as a pivot to attack others if not rigorously isolated and monitored. The core risk of any high-interaction deception is that it must never become a stepping stone into the real network.
The concept scales up in two directions. A honeynet is an entire fake network of honeypots, used for research and to study attacker behavior at scale. Honeytokens apply the same idea to data rather than systems: a fake credential, a decoy database record, a planted file, or a canary API key that no legitimate process should ever use — so any use of it is an instant alarm (a honeytoken AWS key that triggers on first use is a classic, cheap, high-value tripwire). The strategic value of deception is distinctive: it detects attackers already inside the perimeter (where other controls may be blind), it imposes cost and uncertainty on the attacker (they cannot tell which assets are real, slowing them down and risking exposure with every move), and it yields threat intelligence about real adversary behavior. Its limitations: a honeypot only sees attackers who interact with it (it is not comprehensive coverage), it must be convincing enough not to be trivially identified and avoided, and high-interaction deployments carry genuine containment risk. Deception is therefore a complement to detection and prevention — a high-signal layer, not a replacement for them.
Examples
Interaction level trades realism against risk:
LOW-interaction: fakes a service banner, logs the attempt, nothing to exploit
+ safe, cheap, great for detecting scans
- easily fingerprinted; limited intel
HIGH-interaction: real/realistic system, attacker runs commands, reveals TTPs
+ rich intelligence about tools and intent
- DANGEROUS: could be used to pivot to real systems if not isolated
honeynet = a whole fake network of honeypots (research/scale)
honeytoken = a fake secret/record; ANY use = instant, high-confidence alarm
Why deception is high-signal (near-zero false positives):
Real asset: thousands of legitimate connections/day -> noisy, hard to triage.
Honeypot: ZERO legitimate reason to connect
-> a single connection = reconnaissance/lateral movement/compromise.
Honeytoken example: a planted AWS key "AKIA...DECOY" in a config file.
No process should ever use it. First API call with it -> alert:
an attacker has read your files and is probing your cloud. Cheap tripwire.
Key Takeaways
- Deception plants fake assets with no legitimate purpose, so any interaction is high-confidence malicious — producing rare, high-fidelity alerts with near-zero false positives.
- Honeypots are classified by interaction level: low-interaction (emulated, safe, cheap, easily fingerprinted) versus high-interaction (real/realistic, rich intelligence, but risky as a potential pivot).
- Honeynets scale the idea to whole fake networks; honeytokens apply it to data (fake credentials, canary keys, decoy records) as cheap tripwires.
- Deception's strategic value: detecting attackers already inside the perimeter, imposing cost and uncertainty on them, and yielding real threat intelligence.
- Limitations: it only sees attackers who interact with it, must be convincing, and high-interaction deployments carry real containment risk — it complements, not replaces, detection and prevention.
🧪 Practice
- Explain why a honeypot has almost no false positives while a production IDS has many.
- Contrast low- and high-interaction honeypots by intelligence value and risk.
- Design a honeytoken for a cloud environment and describe exactly what event triggers the alert.
- Interview-style: "What is the primary danger of a high-interaction honeypot, and how do you mitigate it?" Hint: the attacker gets a real system to play with — think about isolation and what it must never be able to reach.
<a id="65-network-attacks"></a>
6.5 Network Attacks
This section catalogs the offensive techniques that the defenses in this chapter exist to stop, organized from passive eavesdropping through active interception to availability attacks. Each attack is presented with the design weakness it exploits and the defense that closes it, so the attacks and controls reinforce one another.
Packet Sniffing and Eavesdropping
Theory
The most basic network attack requires no exploitation at all — just listening. Packet sniffing is the passive capture of traffic traversing a network, and eavesdropping is reading the content of that traffic. It is the foundation of many other attacks because it costs the attacker nothing to attempt and, against unencrypted traffic, hands them credentials, session tokens, and data directly. Its passivity is what makes it dangerous: a pure sniffing attack generates no packets of its own, so it leaves almost no trace and is extremely hard to detect.
Whether sniffing works depends on the network medium. On a hub (or any shared medium) every host sees all traffic, so sniffing is trivial — but hubs are obsolete. On a switched network, the switch forwards frames only to the destination port, so an attacker normally sees only their own traffic plus broadcasts. This is why sniffing on modern networks usually requires an active step first — ARP spoofing or MAC flooding (next topics) to redirect or broadcast traffic to the attacker — which is the irony of switching: it raised the bar for sniffing but the techniques to defeat it are well known. On wireless, radio is inherently a shared medium, so anyone in range can capture frames (encrypted or not), making Wi-Fi a prime sniffing target. To capture, the attacker's interface must be in promiscuous mode (accept all frames, not just those addressed to it) or, for Wi-Fi, monitor mode (capture raw radio frames).
The decisive defense is encryption, and this is the single most important lesson of the topic: encrypted traffic (TLS, SSH, a VPN) can be captured but not read, which reduces eavesdropping from a catastrophe to a metadata leak. A sniffer on an encrypted session sees who is talking, when, and how much — but not the plaintext credentials or data. This is precisely why the historical migration from HTTP to HTTPS, Telnet to SSH, and FTP to SFTP matters so much: those cleartext protocols hand everything to any listener. Secondary defenses include switched networks with port security and Dynamic ARP Inspection (to prevent the active redirection sniffing often needs), network segmentation (limiting what an attacker can even reach to sniff), and detection of interfaces in promiscuous mode.
Examples
Why switching changed sniffing (and why attackers add an active step):
HUB (shared): every host sees ALL traffic -> sniff trivially (obsolete)
SWITCH: frames go only to the destination port -> you see only your own
-> attacker must first ARP-spoof or MAC-flood to redirect traffic
WIRELESS: radio is shared -> anyone in range can capture frames
Defense that actually matters: ENCRYPTION. Captured TLS/SSH = unreadable.
# Capturing traffic, and the stark difference encryption makes.
ip link set eth0 promisc on # promiscuous mode: accept all frames
tcpdump -i eth0 -A 'tcp port 80' # cleartext HTTP: credentials visible in -A ascii
# -> POST /login user=alice&password=hunter2 <- handed to any listener
tcpdump -i eth0 'tcp port 443' # HTTPS: captured, but payload is encrypted
# -> only metadata (IPs, SNI, timing, volume); no plaintext credentials
Key Takeaways
- Packet sniffing is passive capture of traffic; eavesdropping is reading its content — cheap, trace-free, and devastating against unencrypted protocols.
- Its passivity makes it very hard to detect, since the attacker sends nothing.
- Hubs expose all traffic; switches limit an attacker to their own traffic (so sniffing usually needs an active redirection step like ARP spoofing); wireless is inherently shared and a prime target.
- Capture requires promiscuous mode (or monitor mode for Wi-Fi).
- Encryption (TLS, SSH, VPN) is the decisive defense: captured traffic becomes unreadable, leaking only metadata — the reason HTTP→HTTPS, Telnet→SSH, and FTP→SFTP migrations matter.
🧪 Practice
- Explain why sniffing is trivial on a hub but requires an extra step on a switch.
- Describe what an attacker gains from sniffing HTTP versus HTTPS traffic.
- Explain why passive sniffing is so hard to detect and name one detection approach.
- Interview-style: "If an attacker can capture all your TLS traffic, what have they actually learned?" Hint: separate content from metadata — think SNI, timing, volume, and endpoints.
ARP Spoofing and MAC Flooding
Theory
These two Layer 2 attacks, introduced in the networking refresher, are the active techniques attackers use to defeat switching and enable sniffing or man-in-the-middle on a local network. Both exploit the trusting, stateless design of Ethernet and ARP — protocols built for a cooperative LAN with no notion of authentication.
ARP spoofing (ARP cache poisoning) exploits the fact that hosts accept ARP replies unconditionally, even unsolicited ones. The attacker sends forged ARP replies telling the victim "the gateway's IP is at my MAC address" and telling the gateway "the victim's IP is at my MAC address." Both update their ARP caches with the lie, and now all traffic between victim and gateway flows through the attacker — a Layer 2 man-in-the-middle. The attacker can then sniff everything (passive), modify traffic (active), or simply drop it (denial of service). Because it rewrites the cache, the position persists until the cache is corrected, and the attacker typically forwards traffic onward so the victim notices no disruption. ARP spoofing is the engine behind most LAN-based MitM.
MAC flooding attacks the switch rather than the hosts. The switch's CAM table (MAC-to-port map) is finite; the attacker floods the switch with frames bearing thousands of fake source MAC addresses until the table overflows. Many switches then fail open — unable to learn where legitimate MACs are, they revert to broadcasting all frames to every port, like a hub — which re-enables the trivial sniffing that switching was designed to prevent. It is cruder than ARP spoofing (it degrades the whole switch rather than targeting one victim) but requires no per-host targeting.
The defenses live on managed switches and directly counter each mechanism. Dynamic ARP Inspection (DAI) validates ARP replies against a trusted database (built from DHCP snooping bindings) and drops forged ones — the direct answer to ARP spoofing. Port security limits the number of MAC addresses allowed per switch port, so a flood of fake MACs trips a limit and the port shuts down or alerts — the direct answer to MAC flooding. Both are examples of pushing security into the Layer 2 infrastructure, which is necessary precisely because ARP and Ethernet have no built-in authentication. Detection is also possible: duplicate MAC-to-IP mappings and sudden ARP table changes are classic spoofing signatures.
Examples
ARP spoofing: poison both caches to sit in the middle.
Attacker -> Victim : "gateway 192.168.1.1 is at EE:EE:EE" (lie)
Attacker -> Gateway: "victim 192.168.1.5 is at EE:EE:EE" (lie)
Result: Victim <===> Attacker <===> Gateway (Layer 2 MitM)
attacker forwards traffic on -> victim notices nothing.
MAC flooding: overflow the switch's CAM table.
attacker -> switch: frames from AA:00:00:00:00:01, ..:02, ..:03, ...(thousands)
CAM table full -> switch fails open -> broadcasts all frames -> sniff like a hub.
# Detecting ARP spoofing: a duplicated MAC across IPs is the tell.
ip neigh show
# 192.168.1.1 dev eth0 lladdr ee:ee:ee:ee:ee:ee REACHABLE <- gateway
# 192.168.1.5 dev eth0 lladdr ee:ee:ee:ee:ee:ee REACHABLE <- same MAC?! spoof
# Switch-side defenses (managed switch, concept):
# ip arp inspection vlan 10 -> Dynamic ARP Inspection (drops forged ARP)
# switchport port-security maximum 2 -> cap MACs/port (stops MAC flooding)
Key Takeaways
- ARP spoofing and MAC flooding are active Layer 2 attacks exploiting Ethernet/ARP's lack of authentication to defeat switching.
- ARP spoofing poisons victim and gateway caches so traffic flows through the attacker — the engine of most LAN man-in-the-middle attacks; it enables sniffing, modification, or denial of service.
- MAC flooding overflows the switch's finite CAM table, making many switches fail open and broadcast all frames like a hub, re-enabling trivial sniffing.
- Dynamic ARP Inspection (validating ARP against DHCP bindings) counters ARP spoofing; port security (capping MACs per port) counters MAC flooding.
- Detect spoofing via duplicate MAC-to-IP mappings and sudden ARP table changes.
🧪 Practice
- Walk through the exact forged ARP replies an attacker sends to man-in-the-middle a victim and its gateway.
- Explain why a switch "fails open" under MAC flooding and what that enables.
- Map each attack to its specific switch-based defense and explain how the defense works.
- Interview-style: "You see two different IPs mapped to the same MAC in a host's ARP table, one of them the gateway. What is happening?" Hint: recall what ARP spoofing does to the cache and which device the attacker impersonates.
DNS Spoofing and Cache Poisoning
Theory
DNS spoofing attacks the trust dependency identified in the networking refresher: if an attacker can make a victim resolve a name to the wrong IP address, they redirect the victim's traffic to an attacker-controlled server without ever touching the victim's machine or the real destination. The victim types the correct domain, sees no obvious error, and lands on the attacker's server — which makes DNS attacks a powerful and stealthy redirection primitive.
There are two main variants by where the forgery happens. DNS spoofing in the local/on-path sense means an attacker who can see the victim's DNS query (via ARP spoofing, a rogue AP, or any MitM position) races to send a forged response before the legitimate resolver answers. Because classic DNS is unauthenticated UDP, the victim accepts whichever valid-looking response arrives first that matches the query's transaction ID and source port. DNS cache poisoning is more potent: instead of targeting one victim, the attacker injects a forged record into a recursive resolver's cache, so that every client using that resolver gets the poisoned answer for the record's TTL. The classic Kaminsky attack (2008) showed how an off-path attacker could poison a resolver by flooding forged responses with guessed transaction IDs while triggering queries for many subdomains, dramatically improving the odds of a match — which forced the industry-wide adoption of source port randomization (adding ~16 bits of entropy the attacker must also guess).
The root cause is the same throughout: classic DNS has no authentication of responses, relying only on a 16-bit transaction ID and (originally predictable) source port, which is simply not enough entropy against a determined attacker. The defenses map directly onto this weakness. DNSSEC cryptographically signs DNS records, so a resolver can verify a response genuinely came from the authoritative zone and was not forged or altered — it makes poisoning detectable and rejectable (though it protects integrity, not confidentiality, and adoption is incomplete). Source port and transaction ID randomization raise the guessing difficulty for on-the-wire forgery. DoH/DoT (encrypted DNS) prevent an on-path attacker from seeing the query to race it. And for the local-MitM variant, the underlying enabler (ARP spoofing, rogue AP) is itself defended as covered elsewhere. Understanding DNS spoofing ties together the chapter: it is often the payload of a MitM position, and its defense is a layered combination of authentication (DNSSEC), entropy (randomization), and encryption (DoH/DoT).
Examples
Two variants of DNS forgery:
ON-PATH SPOOFING (one victim):
victim asks "bank.com?" -> attacker (who can see the query) races a forged
reply "bank.com = 6.6.6.6" that matches the txn ID -> victim -> attacker's site.
CACHE POISONING (all clients of a resolver):
attacker floods resolver with forged answers for "bank.com", guessing txn ID
(+ source port). One match is cached -> EVERY client gets 6.6.6.6 for the TTL.
(Kaminsky: query many subdomains to get many guessing chances fast.)
Root cause: classic DNS responses are unauthenticated (only a 16-bit txn ID).
# Check whether a zone is protected by DNSSEC (the authentication defense):
dig bank.com +dnssec
# look for RRSIG records and the 'ad' (authenticated data) flag in the response
# If signed and validated, a forged answer fails signature verification -> rejected.
# Encrypted DNS (DoT) stops an on-path attacker from seeing the query to race it:
# resolver configured for DNS-over-TLS (port 853) or DoH (over HTTPS).
Key Takeaways
- DNS spoofing redirects a victim's traffic by making a name resolve to an attacker's IP, without touching the victim's host or the real server — stealthy and powerful.
- On-path DNS spoofing races a forged reply to one victim; cache poisoning injects a forged record into a recursive resolver, affecting every client for the record's TTL (the Kaminsky attack).
- The root cause is that classic DNS responses are unauthenticated, protected only by a 16-bit transaction ID and (originally predictable) source port.
- DNSSEC signs records so forgery is detectable and rejectable (protects integrity, not confidentiality; adoption incomplete); source-port/txn-ID randomization raises guessing difficulty.
- DoH/DoT encrypt queries so on-path attackers cannot see them to race; DNS spoofing is often the payload of a MitM position, defended by layering authentication, entropy, and encryption.
🧪 Practice
- Explain the difference between on-path DNS spoofing and cache poisoning in terms of who is affected.
- Describe the entropy classic DNS relies on and why the Kaminsky attack defeated it.
- Explain how DNSSEC stops cache poisoning and why it does not provide confidentiality.
- Interview-style: "Why does source-port randomization meaningfully raise the bar for cache poisoning?" Hint: count the bits an off-path attacker must guess before and after randomization.
Man-in-the-Middle Attacks
Theory
A man-in-the-middle (MitM) attack is the general pattern beneath many of the specific attacks already covered: the attacker secretly positions themselves between two communicating parties, relaying (and potentially reading or altering) their messages, while each party believes it is talking directly and securely to the other. It is the archetypal attack on confidentiality and integrity in transit, and understanding it as a class unifies ARP spoofing, DNS spoofing, rogue APs, and SSL stripping — those are all ways to achieve the MitM position, which is then used to eavesdrop or tamper.
Achieving the position requires getting traffic to flow through the attacker. The techniques are the ones in this section: ARP spoofing (LAN), DNS spoofing (redirect the name), a rogue/evil-twin access point (the victim connects to the attacker's Wi-Fi), BGP/route hijacking (at the internet scale), or a compromised proxy/router. Once in the middle, the attacker's leverage depends entirely on whether the traffic is authenticated and encrypted. Against cleartext, the attacker reads and rewrites at will. Against TLS, the attacker's problem is that TLS is designed to defeat MitM — it authenticates the server via certificates, so the attacker cannot simply impersonate the real server without a valid certificate for its name.
This is why the interesting MitM techniques are about defeating or bypassing the encryption that would otherwise stop them. SSL stripping (Moxie Marlinspike's attack) is the classic: the attacker sits between the victim and an HTTPS site but ensures the victim-to-attacker leg is plain HTTP — the victim never gets upgraded to HTTPS, so there is no certificate to validate, and the attacker speaks HTTPS to the real site while reading everything from the victim in cleartext. The defense is HSTS (HTTP Strict Transport Security), which forces the browser to use HTTPS and refuse the downgrade (detailed under Secure Communication Protocols). Other TLS-MitM approaches require a fraudulent or trusted certificate — a compromised CA, a user tricked into installing the attacker's CA, or a corporate TLS-inspection proxy whose CA is already trusted. The defenses therefore cluster around authenticated encryption and certificate validation: use TLS everywhere, enforce HSTS, validate certificates strictly (reject errors — the "click through the warning" habit is exactly what MitM relies on), use certificate pinning for high-value apps, and employ mutual authentication (both sides prove identity) where possible. The meta-lesson: a MitM position is often easy to obtain, so security must assume the network is hostile and rely on end-to-end authenticated encryption rather than on the network being trustworthy.
Examples
MitM is a POSITION achieved by various means, then used to read/alter:
ways IN: ARP spoofing | DNS spoofing | evil-twin AP | route hijack | bad proxy
then: victim <===> ATTACKER <===> real server
each side thinks it talks directly to the other.
Against cleartext: read + rewrite freely.
Against TLS: TLS authenticates the server -> attacker needs to DEFEAT it:
SSL STRIP: keep victim<->attacker on HTTP (no cert to check),
attacker<->site on HTTPS -> victim's data in cleartext.
or a FRAUDULENT/trusted cert (compromised CA, user-installed CA).
Defenses map to "authenticate the encryption, refuse downgrades":
HTTPS everywhere + HSTS -> browser refuses HTTP downgrade (kills SSL strip)
strict cert validation -> reject cert errors (don't click through warnings)
certificate pinning -> app trusts only ITS cert, not any trusted CA
mutual TLS -> both sides authenticate -> no silent impersonation
assume hostile network -> rely on end-to-end crypto, not network trust
Key Takeaways
- A man-in-the-middle secretly relays between two parties who believe they communicate directly — the archetypal attack on in-transit confidentiality and integrity.
- ARP spoofing, DNS spoofing, rogue/evil-twin APs, and route hijacking are all ways to obtain the MitM position, which is then used to read or tamper.
- TLS is designed to defeat MitM by authenticating the server via certificates, so attackers must bypass it — classically with SSL stripping (keeping the victim on HTTP so there is no certificate to validate).
- Defenses center on authenticated encryption and strict certificate validation: TLS everywhere, HSTS to refuse downgrades, reject certificate errors, certificate pinning, and mutual authentication.
- The meta-lesson: assume the network is hostile and rely on end-to-end authenticated encryption, since a MitM position is often easy to obtain.
🧪 Practice
- List four distinct techniques for achieving a MitM position and the layer each operates at.
- Explain how SSL stripping works and exactly how HSTS defeats it.
- Explain why strictly validating certificates (and not clicking through warnings) is critical against TLS MitM.
- Interview-style: "TLS authenticates the server, so how can a MitM ever read HTTPS traffic?" Hint: consider downgrade to HTTP before TLS starts, and the case of a certificate the victim's browser already trusts.
Session Hijacking
Theory
Authentication proves who you are at login, but most of the interaction that follows is governed by a session — a token (a cookie, a session ID) that the server issues after login and the client presents on every subsequent request, so the user does not re-authenticate each time. Session hijacking is the theft or forgery of that token: the attacker who obtains a valid session identifier becomes the authenticated user, with no need to know the password or defeat MFA. This is why session management is a security control in its own right — the session token is, in effect, a bearer credential equivalent to being logged in.
There are several routes to the token. Sniffing/MitM captures it in transit if the session is not encrypted (the reason cookies must travel only over HTTPS). Cross-site scripting (XSS) steals it from the browser via malicious JavaScript reading the cookie (the reason for the HttpOnly flag, which hides cookies from script). Session fixation tricks the victim into using a session ID the attacker already knows (the attacker sets the ID before login; after the victim authenticates, the attacker uses the same ID — defeated by regenerating the session ID on login). Prediction works if session IDs are generated with insufficient randomness, letting an attacker guess valid ones. At the network layer, classic TCP session hijacking involves predicting sequence numbers to inject into or take over an established connection (hard against modern randomized ISNs, but the conceptual ancestor).
The defenses are a coherent set of session-management best practices, each closing one route: transmit tokens only over TLS (defeats sniffing); mark cookies HttpOnly (defeats XSS theft) and Secure (never sent over HTTP) and SameSite (limits cross-site sending, helping against CSRF); generate session IDs with high entropy from a CSPRNG (defeats prediction); regenerate the session ID on privilege change/login (defeats fixation); enforce idle and absolute timeouts and proper logout that invalidates the token server-side (limits the window of a stolen token); and optionally bind the session to attributes like IP or user-agent (with care, as these can change legitimately). The unifying principle is that the session token must be hard to steal, hard to guess, short-lived, and revocable — because whoever holds it is treated as the user. Session hijacking also connects forward to the web-security chapters, where XSS, CSRF, and cookie security are developed in depth; here the key framing is that a stolen session bypasses authentication entirely.
Examples
A session token is a bearer credential: holding it == being logged in.
login -> server issues session cookie SESSIONID=9f8a... (high-entropy)
client -> sends it on every request -> server trusts it as "this user"
ATTACKER who steals/guesses it -> sends it too -> IS the user. No password needed.
Theft routes: sniffing/MitM | XSS reads cookie | fixation | prediction
Each route -> a specific cookie flag / practice closes it (below).
Cookie flags and practices, mapped to the route each defeats:
Secure -> cookie never sent over HTTP (defeats sniffing on HTTP)
HttpOnly -> JavaScript cannot read the cookie (defeats XSS theft)
SameSite -> limits cross-site sending (helps vs CSRF)
high entropy from CSPRNG (defeats prediction)
regenerate ID on login (defeats session fixation)
idle + absolute timeout, server-side logout (limits stolen-token window)
Set-Cookie: SESSIONID=...; Secure; HttpOnly; SameSite=Strict; Path=/; Max-Age=1800
Key Takeaways
- A session token is a bearer credential issued after login; whoever holds it is treated as the authenticated user, so stealing it bypasses the password and MFA entirely.
- Theft routes: sniffing/MitM (unencrypted transit), XSS (script reading the cookie), session fixation (forcing a known ID), and prediction (weak randomness).
- Defenses map to routes: TLS transport,
HttpOnly/Secure/SameSitecookie flags, high-entropy IDs from a CSPRNG, and regenerating the session ID on login. - Limit a stolen token's value with idle and absolute timeouts and proper server-side logout/invalidation.
- The principle: make the token hard to steal, hard to guess, short-lived, and revocable; session hijacking connects forward to XSS/CSRF in the web chapters.
🧪 Practice
- Explain why a stolen session token lets an attacker in without knowing the password or defeating MFA.
- Map each cookie flag (
Secure,HttpOnly,SameSite) to the attack it mitigates.- Describe session fixation and why regenerating the session ID on login defeats it.
- Interview-style: "After login your app keeps the same session ID the user had before authenticating. What attack does this enable and what is the fix?" Hint: the attacker could have planted that pre-login ID — name the attack and the one-line remedy.
IP and MAC Spoofing
Theory
Spoofing is forging a source address to impersonate another device or to hide the attacker's identity. Because the internet's core protocols were designed to trust source addresses rather than verify them, spoofing is both easy and foundational to many other attacks. There are two levels, matching the two addressing layers.
MAC spoofing forges the Layer 2 source hardware address. A MAC address is supposed to be a device's permanent hardware identifier, but it is trivially changed in software (one command). Attackers use MAC spoofing to bypass MAC-based access controls (MAC filtering on Wi-Fi, or MAC Authentication Bypass in NAC — recall why MAB is weak), to impersonate an authorized device, or to evade MAC-based tracking. It is confined to the local segment (MACs are not routed), but on that segment it undermines any control that trusts the MAC as an identity.
IP spoofing forges the Layer 3 source IP address. Its consequences depend on whether the attacker needs to receive replies. For attacks where the reply is irrelevant or deliberately sent elsewhere, IP spoofing is extremely effective: DoS/DDoS attacks spoof source IPs to hide the origin and frustrate blocking, and amplification/reflection attacks (next topic) spoof the victim's IP as the source so that servers' large replies are aimed at the victim. For attacks requiring a two-way conversation (like completing a TCP handshake), blind IP spoofing is much harder, because the SYN-ACK goes to the spoofed address, not the attacker — they would have to predict sequence numbers blind. This is the key nuance: IP spoofing is easy for one-way/flooding attacks and hard for connection-oriented ones.
The root cause is the absence of source-address verification in IP, and the defenses attack exactly that. Ingress/egress filtering (BCP 38) is the most important: networks should drop outbound packets whose source address does not belong to their own range (so a network cannot emit spoofed packets) and drop inbound packets claiming to originate from inside — if universally deployed, this would eliminate most spoofing, but adoption is incomplete, which is why reflection DDoS persists. Unicast Reverse Path Forwarding (uRPF) on routers automates this check. For MAC spoofing, port security and 802.1X (binding ports to authenticated identities, not just MACs) are the answer. And at the application layer, the general lesson is to never trust a source address as an authentication mechanism — use cryptographic authentication instead, because any address-based trust can be spoofed.
Examples
# MAC spoofing: a "permanent" hardware ID changed in one command.
ip link set eth0 down
ip link set eth0 address 00:11:22:33:44:55 # impersonate / bypass MAC filtering
ip link set eth0 up
# -> defeats Wi-Fi MAC filtering and MAC Authentication Bypass (why MAB is weak).
IP spoofing is easy one-way, hard two-way:
ONE-WAY (flooding/reflection): spoof freely -- you don't need the reply.
DDoS: spoof random sources -> hide origin, frustrate blocking
Reflection: spoof the VICTIM's IP -> servers' big replies hit the victim
TWO-WAY (TCP connect): spoofing is HARD -- SYN/ACK goes to the spoofed IP,
not to you; you'd have to guess sequence numbers blind.
Defense (BCP 38 ingress/egress filtering):
drop outbound packets whose source isn't in YOUR range -> you can't emit spoofs
drop inbound packets claiming to be from INSIDE -> no external impersonation
Key Takeaways
- Spoofing forges a source address to impersonate a device or hide the attacker; the internet's protocols trust source addresses rather than verifying them, making it easy and foundational.
- MAC spoofing forges the Layer 2 address (trivial in software) to bypass MAC filtering/MAB and impersonate devices on the local segment.
- IP spoofing forges the Layer 3 address: easy and effective for one-way flooding and reflection attacks (hiding origin, aiming replies at a victim), but hard for connection-oriented attacks that need the reply.
- BCP 38 ingress/egress filtering (and uRPF) is the key defense — drop packets with source addresses that cannot legitimately originate where they appear — but incomplete adoption lets reflection DDoS persist.
- Never use a source address as authentication; MAC spoofing is countered by port security and 802.1X, and all address-based trust can be forged.
🧪 Practice
- Explain why IP spoofing is easy for a DDoS flood but hard for establishing a TCP connection.
- Describe how MAC spoofing defeats Wi-Fi MAC filtering and why MAC Authentication Bypass is weak.
- Explain BCP 38 ingress/egress filtering and why incomplete adoption enables reflection attacks.
- Interview-style: "Why can a reflection/amplification attacker spoof the victim's IP, but a TCP-connection attacker generally cannot spoof successfully?" Hint: think about where the response packets go and whether the attacker needs to see them.
DoS and Distributed DoS Techniques
Theory
Where most attacks target confidentiality or integrity, denial-of-service attacks target the third pillar: availability. The goal is not to steal or alter data but to make a service unavailable to its legitimate users by exhausting a resource it depends on. A DoS (Denial of Service) attack comes from one source; a DDoS (Distributed Denial of Service) attack comes from many — typically a botnet of thousands of compromised devices — which makes it vastly more powerful and much harder to stop, because you cannot simply block one IP.
DoS/DDoS techniques are best understood by which resource they exhaust, which also tells you which defense applies. Volumetric attacks (the most common) saturate the target's bandwidth with sheer traffic volume — UDP floods, ICMP floods, and especially amplification/reflection attacks (next topic) that generate enormous traffic. Protocol/state-exhaustion attacks exhaust connection state or processing capacity rather than bandwidth — the SYN flood (from the TCP handshake topic) sends floods of SYNs that are never completed, filling the server's half-open connection table; others target firewalls' and load balancers' state tables. Application-layer (Layer 7) attacks exhaust application resources with requests that look legitimate but are expensive to serve — flooding a search endpoint, a login page, or any CPU/database-heavy operation (e.g. HTTP floods, Slowloris which holds connections open with partial requests). Layer 7 attacks are insidious because the traffic is low-volume and looks like real users, making it hard to distinguish from a legitimate traffic spike.
The defining defensive challenge is distinguishing malicious traffic from legitimate traffic, especially at Layer 7, and absorbing or filtering volumetric floods that can exceed any single site's capacity. The defenses therefore combine scale and filtering: rate limiting (per-IP and per-endpoint caps), traffic scrubbing services and CDNs (massive distributed capacity that absorbs and filters floods before they reach the origin — the dominant commercial defense), anycast (spreading the target IP across many global locations so an attack is diluted), SYN cookies (defeating SYN floods without keeping state — the server encodes connection state into the sequence number instead of storing it), blackholing/sinkholing (dropping traffic to a targeted IP, a last resort that completes the DoS for that IP but saves the rest), and upstream/ISP cooperation (filtering near the source). The strategic reality is that DDoS is an arms race of capacity: because amplification lets attackers generate terabits, defense has largely moved to specialized providers with more capacity than any attacker, plus BCP 38 filtering (previous topic) to reduce the spoofing that makes amplification possible in the first place.
Examples
DoS/DDoS classified by the resource exhausted (and its defense):
VOLUMETRIC (bandwidth): UDP/ICMP flood, amplification -> saturate the pipe
defense: CDN/scrubbing, anycast, upstream filtering (need MORE capacity)
PROTOCOL/STATE (tables): SYN flood -> fill half-open connection table
defense: SYN cookies (encode state in seq num, store nothing)
APPLICATION (Layer 7): HTTP flood, Slowloris -> exhaust app/DB/CPU
defense: rate limiting, WAF, bot management (hard: looks like real users)
DoS = one source. DDoS = a botnet of thousands -> can't just block one IP.
SYN cookies: defeat a SYN flood without storing per-connection state.
Normal: SYN -> server ALLOCATES state, waits for ACK (flood exhausts the table)
Cookie: SYN -> server encodes connection info into the ISN it returns,
stores NOTHING. Legit ACK echoes it back -> server reconstructs
state from the ACK. Flood of SYNs costs the server no memory.
Key Takeaways
- DoS/DDoS attacks target availability by exhausting a resource; DoS is one source, DDoS is many (a botnet), making it far more powerful and impossible to stop by blocking one IP.
- Classify by exhausted resource: volumetric (bandwidth — floods and amplification), protocol/state (connection tables — SYN floods), and application-layer (app/CPU/DB — HTTP floods, Slowloris).
- Layer 7 attacks are hardest to detect because low-volume, legitimate-looking requests are hard to tell from a real traffic spike.
- The core defensive challenge is separating malicious from legitimate traffic and having enough capacity to absorb volumetric floods.
- Defenses combine scale and filtering: rate limiting, CDN/scrubbing services, anycast, SYN cookies (state-free SYN-flood defense), blackholing, and BCP 38 to curb the spoofing that enables amplification.
🧪 Practice
- Classify each by exhausted resource: SYN flood, UDP amplification, Slowloris, and name a defense for each.
- Explain why a DDoS from a botnet cannot be stopped by blocking a single source IP.
- Explain how SYN cookies defeat a SYN flood without maintaining a state table.
- Interview-style: "Why are Layer 7 DDoS attacks harder to mitigate than volumetric ones despite using far less bandwidth?" Hint: consider how closely the requests resemble legitimate user activity.
Amplification and Reflection Attacks
Theory
Amplification and reflection are the techniques that make volumetric DDoS devastating, turning an attacker with modest bandwidth into one capable of generating terabits per second. They combine two ideas — reflection (bouncing traffic off third-party servers so the attack appears to come from them, hiding the real origin) and amplification (choosing services whose response is much larger than the request, multiplying the attacker's bandwidth). Used together, they are the dominant form of large-scale volumetric attack, and they depend critically on two weaknesses you have already met: IP spoofing and certain UDP services.
The mechanism: the attacker sends requests to many publicly-reachable UDP servers (reflectors) but spoofs the source IP to be the victim's address. Each server, believing the request came from the victim, sends its (large) reply to the victim. The victim is flooded with responses from thousands of innocent servers, while the attacker's own small requests are hidden behind them. UDP is essential here precisely because it has no handshake to verify the source — the reason, from the UDP topic, that UDP is the workhorse of these attacks. The amplification factor is what makes specific services attractive: it is the ratio of response size to request size, and attackers seek the highest.
| Reflector service | Port | Approx. amplification | Why |
|---|---|---|---|
| DNS | 53 | ~28–54× | small query, large (ANY/DNSSEC) response |
| NTP (monlist) | 123 | ~556× | tiny request returns a long list |
| memcached | 11211 | up to ~51,000× | huge responses, no auth (if internet-exposed) |
| SSDP | 1900 | ~30× | device discovery replies |
| CLDAP | 389 | ~56–70× | connectionless LDAP |
The defenses attack each ingredient. The most fundamental is BCP 38 ingress/egress filtering (from the spoofing topic): if networks refused to forward packets with spoofed source addresses, reflection would be impossible, because the attacker could not claim to be the victim — this is why BCP 38 is considered the root fix, and why its incomplete deployment lets these attacks continue. Second, do not expose amplifiable UDP services to the internet (the memcached catastrophe of 2018 came from tens of thousands of internet-exposed memcached servers that should have been internal-only), and disable dangerous features (like NTP monlist) and apply rate limiting on reflectors (DNS response rate limiting). Third, on the victim side, the same volumetric defenses apply — scrubbing/CDN capacity to absorb the flood. The elegant insight for a defender is that amplification attacks are a shared responsibility failure: they exploit misconfigured third parties and networks that permit spoofing, so defending against them is partly about not being a reflector (securing your own UDP services) and advocating for anti-spoofing filtering, not only about protecting your own site.
Examples
Reflection + amplification (small spoofed request -> huge flood at the victim):
attacker (small bandwidth)
| spoofs SOURCE = victim's IP
v tiny requests
[ thousands of open UDP reflectors: DNS, NTP, memcached ]
| each sends a LARGE reply "back to the source" (= the victim)
v
VICTIM <==== massive aggregated flood ==== (attacker's identity hidden)
memcached: 15-byte request -> ~750 KB response => ~51,000x amplification.
Defenses map to each ingredient of the attack:
spoofed source IP -> BCP 38 ingress/egress filtering (THE root fix)
open UDP reflectors -> don't expose DNS/NTP/memcached to the internet;
disable NTP monlist; DNS response rate limiting
flood reaches victim -> scrubbing service / CDN absorbs volumetric traffic
Shared responsibility: secure your OWN UDP services so you aren't a reflector.
Key Takeaways
- Amplification/reflection attacks combine reflection (bouncing off third-party servers to hide origin) with amplification (responses far larger than requests) to generate massive volumetric floods.
- The attacker sends small requests to open UDP servers while spoofing the victim's IP as the source, so the servers' large replies all flood the victim.
- They depend on IP spoofing and connectionless UDP services; the amplification factor (response/request size ratio) drives reflector choice — memcached reaching ~51,000×.
- BCP 38 ingress/egress filtering is the root fix (no spoofing → no reflection); its incomplete deployment is why these attacks persist.
- Also defend by not exposing amplifiable UDP services to the internet, disabling dangerous features (NTP monlist), rate-limiting reflectors, and absorbing floods with scrubbing/CDN capacity — partly a shared-responsibility problem of not being a reflector.
🧪 Practice
- Explain the roles of reflection and amplification and why UDP is essential to both.
- Define the amplification factor and explain why memcached was so catastrophic.
- Explain why BCP 38 is considered the root fix and why the attacks persist anyway.
- Interview-style: "How does an attacker with 1 Gbps of bandwidth generate a 50 Tbps attack, and whose misconfiguration enables it?" Hint: combine spoofing the victim's address with services whose replies dwarf the requests, and consider who runs those reflectors.
Rogue Access Points and Evil Twin
Theory
Wireless networks introduce an attack surface wired networks do not: anyone within radio range can both listen and broadcast, and crucially, clients choose which network to join based on little more than a name. Rogue access points and evil twins exploit this to insert the attacker into the victim's connection — they are the wireless route to the man-in-the-middle position discussed earlier.
The two terms describe related but distinct threats. A rogue access point is any unauthorized AP connected to a network — classically, an employee who plugs a cheap wireless router into the corporate LAN for convenience, unknowingly creating an unsecured backdoor that bypasses the entire perimeter (an attacker in range now has a path inside). It is primarily an infrastructure problem: an unmanaged entry point into a trusted network. An evil twin is more targeted and deceptive: an attacker sets up an AP that impersonates a legitimate network, broadcasting the same SSID (network name) — and often a stronger signal — so that victims' devices connect to it believing it is the real thing. Once connected, the attacker is the man in the middle for all the victim's traffic, able to sniff, inject, redirect (DNS spoofing, SSL stripping), and harvest credentials via fake captive portals.
The evil twin works because of two weaknesses. First, SSIDs are not authenticated — any AP can claim any name, and devices often auto-connect to remembered networks by name alone, so a device that once joined "CoffeeShop-WiFi" will silently reconnect to any AP broadcasting that SSID. Second, on open or pre-shared-key networks there is no mutual authentication of the AP to the client, so the client cannot tell the real AP from the impostor. This is why open public Wi-Fi is so dangerous and why the defenses are specific: enterprise Wi-Fi with 802.1X and server-certificate validation (the client verifies the authentication server's certificate, so an evil twin without the valid certificate is rejected — mutual authentication defeats impersonation), WPA3 (which adds protections including for open networks), always using a VPN on untrusted Wi-Fi (so even a successful evil twin sees only encrypted tunnel traffic), disabling auto-connect to open networks and forgetting old ones, and — on the infrastructure side — wireless intrusion detection (WIDS) and site surveys to detect rogue and impersonating APs by their characteristics. The connecting theme with the rest of the chapter is clear: an evil twin is just another way to become the man in the middle, defended by the same principles — mutual authentication and end-to-end encryption that does not trust the network.
Examples
Rogue AP vs Evil Twin:
ROGUE AP: unauthorized AP plugged into the corporate LAN (e.g. by an employee)
-> an unmanaged backdoor; anyone in range has a path INSIDE the perimeter.
EVIL TWIN: attacker AP impersonates a real network's SSID (+ stronger signal)
"CoffeeShop-WiFi" (real) "CoffeeShop-WiFi" (attacker, louder)
victim's device auto-connects to the impostor by NAME ->
attacker is MitM: sniff, DNS-spoof, SSL-strip, fake captive portal for creds.
Why it works, and the defenses:
SSIDs are NOT authenticated + devices auto-connect to remembered names
-> any AP can claim to be "CoffeeShop-WiFi".
Defenses:
802.1X enterprise Wi-Fi + validate the RADIUS server CERTIFICATE
-> client rejects an evil twin lacking the valid cert (mutual auth)
VPN on untrusted Wi-Fi -> evil twin sees only encrypted tunnel traffic
disable auto-connect / forget open networks
WIDS + site surveys -> detect rogue and impersonating APs
Key Takeaways
- Wireless lets anyone in range listen and broadcast, and clients pick networks by name — the weakness rogue APs and evil twins exploit to achieve a wireless man-in-the-middle.
- A rogue AP is an unauthorized AP on the network (e.g. an employee's router), creating an unmanaged backdoor past the perimeter — an infrastructure problem.
- An evil twin impersonates a legitimate SSID (often with a stronger signal) so victims' devices connect to it, giving the attacker a MitM position to sniff, redirect, and harvest credentials.
- Evil twins work because SSIDs are unauthenticated and devices auto-connect to remembered network names, and open/PSK networks do not authenticate the AP to the client.
- Defend with 802.1X enterprise Wi-Fi plus server-certificate validation (mutual auth defeats impersonation), a VPN on untrusted Wi-Fi, disabling auto-connect, and WIDS/site surveys to detect rogue and impersonating APs.
🧪 Practice
- Distinguish a rogue access point from an evil twin by intent and threat.
- Explain the two weaknesses that let an evil twin succeed, including why devices auto-connect to it.
- Explain how 802.1X with server-certificate validation prevents an evil-twin attack.
- Interview-style: "Why does validating the authentication server's certificate on enterprise Wi-Fi stop an evil twin, when a WPA2-PSK network cannot?" Hint: think about mutual authentication — what the client verifies about the AP in each case.
<a id="66-secure-communication-protocols"></a>
6.6 Secure Communication Protocols
The attacks in the previous section assumed a hostile network; secure communication protocols are the end-to-end defenses that make a hostile network survivable. This section covers how TLS, SSH, IPsec, VPNs, secure DNS, and email authentication apply cryptography to achieve confidentiality, integrity, and authentication in transit.
TLS Handshake and Record Protocol
Theory
TLS (Transport Layer Security) is the protocol that secures the overwhelming majority of internet traffic — every HTTPS connection, and much email, messaging, and API traffic. It solves the exact problem the Network Attacks section posed: communicating securely over a network where attackers can sniff, tamper, and impersonate. It does so by providing three guarantees at once — confidentiality (encryption, so sniffers see only ciphertext), integrity (so tampering is detected), and authentication (so you know you are talking to the real server, defeating man-in-the-middle). Understanding how it achieves all three requires separating its two phases: the handshake and the record protocol.
The handshake is the setup phase, and it elegantly combines the asymmetric and symmetric cryptography from Chapter 3. The problem it solves is the key-distribution dilemma: symmetric encryption is fast and ideal for bulk data, but how do two strangers agree on a shared secret key over a channel an attacker can read? TLS uses asymmetric cryptography to authenticate and to establish a shared symmetric key, then switches to that symmetric key for the actual data. In outline: the client and server agree on cipher suites, the server presents its certificate (proving its identity via the PKI chain of trust — the client validates it against trusted CAs, which is what defeats MitM), and the two perform a key exchange (modern TLS uses ephemeral Diffie-Hellman) to derive a shared session key that an eavesdropper cannot compute. The handshake ends with both sides confirming they derived the same key. This is the security-critical phase — it authenticates the server and bootstraps the encryption.
The record protocol is the working phase: once the handshake establishes the session keys, all application data is broken into records, each encrypted and integrity-protected with those symmetric keys (using authenticated encryption — AEAD — in modern TLS, which combines confidentiality and integrity in one operation). This is where the bulk, efficient symmetric encryption happens. The division of labor is the key insight: asymmetric crypto does the expensive authentication and key-establishment once in the handshake; symmetric crypto does the cheap bulk encryption continuously in the record protocol. This hybrid design is why TLS is both secure and fast, and it is the template for nearly every secure-channel protocol.
Examples
TLS = handshake (asymmetric: authenticate + agree on a key) then
record protocol (symmetric: bulk encrypt/authenticate the data).
HANDSHAKE (once, expensive):
client: "hello, here are cipher suites I support"
server: "hello, chosen suite, here is my CERTIFICATE (PKI identity)"
+ ephemeral DH key-exchange parameters
client: validates cert against trusted CAs <- defeats MitM
both derive the SAME session key via DH (eavesdropper cannot)
both: "finished" (confirm the derived key matches)
RECORD PROTOCOL (continuous, cheap):
[app data] -> split into records -> AEAD-encrypt with the session key
-> confidentiality + integrity on every record.
# Inspect a real TLS handshake: certificate, chain, cipher, and protocol version.
openssl s_client -connect example.com:443 -servername example.com </dev/null
# shows: the certificate chain (PKI), negotiated cipher suite, TLS version,
# and whether the server cert validates to a trusted CA.
# A validation FAILURE here is exactly what a MitM (fake cert) would cause.
Key Takeaways
- TLS secures most internet traffic by providing confidentiality, integrity, and server authentication at once — directly countering sniffing, tampering, and MitM.
- It has two phases: the handshake (setup) and the record protocol (data transfer).
- The handshake uses asymmetric cryptography to authenticate the server (via its PKI certificate, validated against trusted CAs) and to establish a shared symmetric session key over an open channel.
- The record protocol uses that symmetric key for fast, authenticated (AEAD) encryption of all application data.
- The hybrid design — asymmetric once for authentication/key-exchange, symmetric continuously for bulk data — makes TLS both secure and efficient and is the template for secure channels.
🧪 Practice
- Explain the division of labor between asymmetric and symmetric cryptography in TLS and why it exists.
- Describe what the server's certificate accomplishes in the handshake and which attack it defeats.
- Distinguish the handshake from the record protocol by purpose and cryptography used.
- Interview-style: "Why does TLS not just use asymmetric encryption for all the data?" Hint: compare the performance of asymmetric and symmetric operations for bulk throughput.
TLS 1.2 vs. TLS 1.3 Improvements
Theory
TLS 1.3 (2018) was the most significant redesign of the protocol in two decades, and its changes were driven by hard lessons from a long history of attacks against TLS 1.2 and earlier. The theme of the redesign is "secure by default, and faster" — TLS 1.3 removes the options that made TLS 1.2 dangerous and simultaneously makes the handshake quicker. Knowing the differences matters because both are deployed, and the reasons for each change encode years of accumulated security knowledge.
The security improvements all stem from removing choices that could be made insecurely. TLS 1.2 accumulated a large menu of cipher suites including weak and broken options (RC4, DES, export ciphers, static RSA key exchange, CBC modes vulnerable to padding attacks), and much real-world insecurity came from negotiating down to a weak one (sometimes forced by a downgrade attack). TLS 1.3 removed all the legacy and weak algorithms, keeping only strong AEAD cipher suites and modern key exchange. Critically, it mandates forward secrecy by removing static RSA key exchange entirely (only ephemeral Diffie-Hellman remains — next topic), so every TLS 1.3 session has forward secrecy, whereas in TLS 1.2 it was optional and often not used. It also hardens against downgrade attacks and removes problematic features like renegotiation and compression (which enabled the CRIME attack).
The performance improvement is the faster handshake. TLS 1.2 required two round trips (2-RTT) before application data could flow; TLS 1.3 streamlines this to one round trip (1-RTT), and supports 0-RTT resumption for repeat connections (sending data in the very first message when reconnecting to a known server). This latency reduction is significant at web scale. The one caution worth knowing is that 0-RTT data is replayable (an attacker can resend the early data), so it must only be used for idempotent requests — a rare case where TLS 1.3 reintroduces a subtle risk in exchange for speed. The overall lesson generalizes beyond TLS: reducing configurability eliminates whole classes of misconfiguration and downgrade attacks, which is why "secure defaults with fewer knobs" is a recurring principle in protocol design.
| TLS 1.2 | TLS 1.3 | |
|---|---|---|
| Cipher suites | large menu, includes weak/broken | few, strong AEAD only |
| Forward secrecy | optional | mandatory (ephemeral DH only) |
| Handshake latency | 2-RTT | 1-RTT (0-RTT resumption) |
| Legacy key exchange | static RSA allowed | removed |
| Known-dangerous features | renegotiation, compression | removed |
| Downgrade protection | weaker | hardened |
Examples
Handshake round-trips (why 1.3 is faster):
TLS 1.2 (2-RTT): ClientHello -> ServerHello,cert,params ->
ClientKeyExchange,Finished -> Finished -> [data]
(two full round trips before data)
TLS 1.3 (1-RTT): ClientHello (+ key share) -> ServerHello,cert,Finished (+ key share)
-> Finished + [data] (one round trip)
0-RTT resumption: reconnect -> send data in the FIRST message
BUT 0-RTT data is REPLAYABLE -> idempotent requests only.
# Force a version to see support, and confirm strong suites only on 1.3.
openssl s_client -connect example.com:443 -tls1_3 </dev/null | grep -E "Protocol|Cipher"
openssl s_client -connect example.com:443 -tls1_2 </dev/null | grep -E "Protocol|Cipher"
# Disable old protocols on your server (concept): permit only TLS 1.2+ (ideally 1.3),
# refuse SSLv3/TLS1.0/1.1 -> removes downgrade targets.
Key Takeaways
- TLS 1.3's redesign theme is "secure by default and faster," encoding two decades of attack lessons.
- Security gains come from removing insecure choices: all weak/legacy algorithms gone, only strong AEAD suites kept, and dangerous features (renegotiation, compression) removed — eliminating whole classes of downgrade and misconfiguration attacks.
- TLS 1.3 mandates forward secrecy (ephemeral Diffie-Hellman only; static RSA key exchange removed), so every session has it, unlike optional-and-often-unused forward secrecy in TLS 1.2.
- Performance improves from a 2-RTT handshake to 1-RTT, with 0-RTT resumption for repeat connections.
- 0-RTT early data is replayable, so it must be limited to idempotent requests — the one speed/safety tradeoff reintroduced.
🧪 Practice
- List three security improvements TLS 1.3 made over TLS 1.2 and the reason for each.
- Explain why mandating ephemeral key exchange guarantees forward secrecy for all TLS 1.3 sessions.
- Explain the 0-RTT replay risk and what kinds of requests it is safe for.
- Interview-style: "How does removing cipher-suite options make TLS 1.3 more secure, not just simpler?" Hint: think about downgrade attacks and the weakest option an attacker could force in TLS 1.2.
Forward Secrecy
Theory
Forward secrecy (also called perfect forward secrecy, PFS) answers a single, serious question: if the server's long-term private key is compromised tomorrow, can an attacker who recorded today's encrypted traffic decrypt it? Without forward secrecy, the answer is yes — and that is a catastrophic property, because it means an adversary can record encrypted traffic now and decrypt it later once they obtain the key (by subpoena, theft, or future cryptanalysis). Forward secrecy makes the answer no: past sessions stay secret even after the long-term key is compromised.
The distinction lies in how the session key is established. In the non-forward-secret design (static RSA key exchange, used in older TLS), the client picks the session key, encrypts it with the server's long-term public key, and sends it; the server decrypts it with its long-term private key. The fatal consequence: anyone who records that handshake and later obtains the server's private key can decrypt the session key and then all the traffic. The long-term key is a single point of failure protecting every past session. In the forward-secret design (ephemeral Diffie-Hellman, ECDHE/DHE), the two parties use Diffie-Hellman to derive a shared session key using ephemeral (one-time, per-session) key pairs that are discarded after the handshake. The server's long-term key is used only to authenticate (sign) the exchange, not to encrypt the session key. Because the ephemeral private keys are thrown away and never transmitted, there is nothing to recover later — compromising the long-term key lets an attacker impersonate the server going forward, but it does not help decrypt past recorded sessions.
The practical importance has grown with the "harvest now, decrypt later" threat model — adversaries recording encrypted traffic en masse in anticipation of future key compromise or cryptographic advances (notably quantum computing against today's asymmetric algorithms). Forward secrecy directly defeats harvesting for the sessions it protects. This is why TLS 1.3 made it mandatory (previous topic): ephemeral Diffie-Hellman is the only key-exchange mechanism, so every connection is forward-secret. The concept generalizes to any protocol handling long-lived secrets — messaging apps (Signal's ratchet extends forward secrecy to every message), SSH, and VPNs all value it — and the general principle is to minimize the consequences of inevitable key compromise by ensuring no single key, once broken, unravels the entire history.
Examples
Non-forward-secret (static RSA) vs forward-secret (ephemeral DH):
STATIC RSA:
client encrypts session key WITH server's long-term public key -> sends it.
attacker records the handshake... later steals the server's private key
-> decrypts the session key -> decrypts ALL recorded past traffic. BAD.
EPHEMERAL DH (ECDHE):
both derive the session key via DH using ONE-TIME keys, discarded after.
long-term key only SIGNS the exchange (authentication), never encrypts it.
attacker records + later steals long-term key -> can impersonate going
forward, but CANNOT decrypt past sessions (ephemeral keys are gone). GOOD.
"Harvest now, decrypt later" and why forward secrecy defeats it:
adversary records terabytes of encrypted traffic today
-> waits for a future key compromise / quantum break of the asymmetric key
WITHOUT forward secrecy: all that recorded traffic becomes readable.
WITH forward secrecy: each session's ephemeral key is gone -> nothing to
retroactively decrypt. TLS 1.3 makes this mandatory.
Key Takeaways
- Forward secrecy ensures that compromising a server's long-term private key does not allow decryption of previously recorded sessions.
- Without it (static RSA key exchange), the session key is protected by the long-term key, so recording traffic now and stealing the key later decrypts everything — a single point of failure over all history.
- With it (ephemeral Diffie-Hellman, ECDHE/DHE), one-time per-session keys are derived and discarded; the long-term key only authenticates, so there is nothing to recover later.
- It defeats the "harvest now, decrypt later" threat, increasingly important against future key compromise and quantum attacks.
- TLS 1.3 mandates forward secrecy by using only ephemeral key exchange; the principle — no single key compromise unravels the whole history — extends to messaging, SSH, and VPNs.
🧪 Practice
- Explain, step by step, why static RSA key exchange lacks forward secrecy.
- Explain how ephemeral Diffie-Hellman provides forward secrecy and what the long-term key is still used for.
- Describe the "harvest now, decrypt later" threat and how forward secrecy counters it.
- Interview-style: "An attacker records your TLS traffic and a year later steals your server's private key. With ephemeral DH, what can they decrypt?" Hint: consider whether the keys that actually encrypted the data still exist anywhere.
HTTPS, HSTS, and Mixed Content
Theory
HTTPS is simply HTTP carried over TLS, and it is the single most important security deployment on the web — but enabling HTTPS is not the same as enforcing it, and the gap between the two is exactly where attacks like SSL stripping (from the MitM topic) live. This topic is about closing that gap: making sure a user who intends to use a site securely cannot be silently downgraded or undermined by insecure sub-resources.
The core problem is the initial, insecure request. When a user types example.com (without https://), the browser's first request goes out over plain HTTP, and the server responds with a redirect to HTTPS. That brief HTTP moment is the attacker's opportunity: an on-path attacker (SSL stripping) can intercept it and keep the user on HTTP, never letting them reach the secure version, reading everything in cleartext. HSTS (HTTP Strict Transport Security) closes this hole. It is a response header (Strict-Transport-Security: max-age=...) by which a site tells the browser "for the next N seconds, always use HTTPS for me, and never allow an HTTP connection or a click-through of a certificate error." Once a browser has seen the HSTS header, it internally upgrades every future request to that domain to HTTPS before sending anything, eliminating the insecure initial request. To close the gap on the very first visit (before the browser has seen the header), browsers ship an HSTS preload list — a built-in set of domains hardcoded as HTTPS-only — which sites can join. HSTS is therefore the definitive defense against SSL stripping and cookie-stealing downgrade attacks.
The second subtlety is mixed content: an HTTPS page that loads sub-resources (scripts, images, stylesheets, iframes) over plain HTTP. This silently undermines the page's security, because those HTTP resources can be intercepted and modified in transit — a MitM can replace an HTTP-loaded script with malicious code, compromising the "secure" page entirely. Browsers now treat mixed content seriously: active mixed content (scripts, iframes — things that can execute) is blocked outright, while passive mixed content (images — things that only display) may be blocked or upgraded, often automatically via the upgrade-insecure-requests Content Security Policy directive. The practical deployment checklist ties these together: serve everything over HTTPS, redirect HTTP to HTTPS, set HSTS (and consider preloading), mark cookies Secure, eliminate mixed content, and use a current TLS configuration. The recurring theme is that security on the web must be enforced and complete, not merely available — a single insecure request or sub-resource is enough for an attacker.
Examples
The insecure first request and how HSTS closes it:
WITHOUT HSTS:
user types "example.com" -> plain HTTP request -> [attacker strips SSL here]
-> victim stays on HTTP -> cleartext forever.
WITH HSTS (header seen on a prior visit):
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
browser UPGRADES every request to HTTPS before sending -> no HTTP request
exists to intercept, and cert errors can't be clicked through.
First-visit gap -> HSTS PRELOAD list (hardcoded in the browser) closes it.
Mixed content undermines an HTTPS page:
https://bank.example loads <script src="http://cdn.example/app.js">
-> that script travels over HTTP -> MitM swaps it for malicious code
-> the "secure" page is fully compromised.
Browser policy:
active mixed content (script, iframe) -> BLOCKED
passive (img) -> blocked or auto-upgraded
fix: load everything over HTTPS; CSP 'upgrade-insecure-requests'.
Key Takeaways
- HTTPS is HTTP over TLS; enabling it is not the same as enforcing it, and the gap is where SSL stripping lives.
- The insecure initial HTTP request (before the HTTPS redirect) is the attacker's opportunity; HSTS closes it by telling the browser to always use HTTPS for the domain and refuse HTTP and certificate-error click-throughs.
- The HSTS preload list hardcodes HTTPS-only domains into browsers, closing the first-visit gap before any header is seen.
- Mixed content (HTTP sub-resources on an HTTPS page) silently undermines security; browsers block active mixed content (scripts/iframes) and block or upgrade passive content (images).
- Web security must be enforced and complete — redirect to HTTPS, set HSTS, mark cookies
Secure, and eliminate mixed content — because one insecure request or resource suffices for an attacker.
🧪 Practice
- Explain the insecure-first-request problem and exactly how HSTS eliminates it.
- Explain what the HSTS preload list adds beyond the HSTS header.
- Distinguish active and passive mixed content and how browsers treat each.
- Interview-style: "A site redirects all HTTP to HTTPS but has no HSTS. Is it still vulnerable to SSL stripping, and why?" Hint: focus on what happens during that very first HTTP request before the redirect is received.
SSH Architecture and Key Authentication
Theory
SSH (Secure Shell) is the standard protocol for secure remote administration and encrypted file transfer, and it is the secure replacement for the cleartext protocols (Telnet, rlogin, FTP) that hand credentials to any sniffer. Covered operationally in Chapter 2, here the focus is its security architecture: how it authenticates both the server and the client, and why public-key authentication is both more secure and more convenient than passwords.
SSH is layered. A transport layer establishes an encrypted, integrity-protected channel and — crucially — authenticates the server to the client using the server's host key. This is the step that prevents man-in-the-middle: on first connection the client records the server's host key fingerprint (trust on first use, TOFU), and on every subsequent connection it verifies the server presents the same key. The infamous "host key verification failed" warning is SSH detecting that the key changed — which could be a legitimate server rebuild or an active MitM, and should never be dismissed carelessly (verifying the fingerprint out of band on first connect is the correct discipline). On top of the transport layer, a user authentication layer proves the client's identity, and a connection layer multiplexes channels (shells, port forwards, file transfers) over the one encrypted connection.
The security heart of SSH is public-key authentication, which is strongly preferred over passwords. The client holds a private key (ideally protected by a passphrase and stored in an agent) and places the corresponding public key in the server's ~/.ssh/authorized_keys. Authentication is a challenge-response: the server challenges, the client signs with its private key, the server verifies with the stored public key — the private key never leaves the client, and nothing reusable crosses the network. This is far better than passwords for several reasons: it is immune to the password-guessing, brute-force, and credential-stuffing attacks that plague SSH's internet-facing port 22; there is no shared secret to phish or leak server-side; and it enables automation. The hardening consequences follow directly: disable password authentication entirely where possible (PasswordAuthentication no), disable root login (PermitRootLogin no), protect private keys with passphrases and an agent, and rotate/manage keys (orphaned authorized_keys entries are a real risk). SSH also provides powerful secure tunneling (local, remote, and dynamic port forwarding), which carries other protocols safely over its encrypted channel but must be controlled, since it can also be used to tunnel past network controls.
Examples
SSH layers and what each authenticates:
TRANSPORT layer -> encrypts + integrity-protects, AUTHENTICATES THE SERVER
via its host key (TOFU: remembered in known_hosts).
"host key verification failed" = key changed = rebuild OR MitM.
USER AUTH layer -> authenticates the CLIENT (public key preferred over password).
CONNECTION layer -> multiplexes shells, port-forwards, file transfer on one channel.
# Public-key authentication: private key signs a challenge; it never leaves the client.
ssh-keygen -t ed25519 -C "admin@example" # generate a modern keypair (passphrase!)
ssh-copy-id -i ~/.ssh/id_ed25519.pub host # install PUBLIC key in authorized_keys
# Hardening sshd_config -- eliminate the attacks against port 22:
# PasswordAuthentication no -> no password guessing/brute-force/stuffing
# PermitRootLogin no -> no direct root login
# PubkeyAuthentication yes -> keys only
# Verify a host key fingerprint OUT OF BAND before trusting it on first connect:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Key Takeaways
- SSH is the secure replacement for Telnet/rlogin/FTP, providing encrypted, authenticated remote administration and file transfer.
- Its transport layer authenticates the server via a host key (trust on first use, stored in
known_hosts); a changed key triggers the "host key verification failed" warning, which may indicate a legitimate rebuild or an active MitM. - Public-key authentication (private key signs a server challenge; public key in
authorized_keys) is strongly preferred over passwords — immune to guessing/brute-force/stuffing, with no server-side shared secret to phish. - Harden by disabling password authentication and root login, protecting private keys with passphrases and an agent, and managing/rotating keys.
- SSH tunneling carries other protocols over its encrypted channel but can also bypass network controls, so it must be governed.
🧪 Practice
- Explain what the SSH host key authenticates and what a "host key verification failed" warning may mean.
- Describe the public-key authentication challenge-response and why the private key never crossing the network matters.
- List three
sshd_confighardening settings and the attack each prevents.- Interview-style: "Why is SSH public-key authentication more resistant to internet-facing brute force than password authentication?" Hint: consider what an attacker must possess versus guess, and whether there is anything to guess at all.
IPsec: AH, ESP, Transport and Tunnel Modes
Theory
IPsec is a suite of protocols that secures communication at the network layer (Layer 3) — unlike TLS and SSH, which secure individual application connections, IPsec protects IP packets themselves, transparently, for any application. This is its defining characteristic and the reason it underpins most VPNs: because it works at the IP layer, applications need no awareness of it, and all traffic between two endpoints or networks can be protected at once. Understanding IPsec means understanding two orthogonal choices: which protocol (AH vs ESP) and which mode (transport vs tunnel).
The two core protocols provide different protections. AH (Authentication Header) provides integrity and authentication of the packet — it proves the packet was not altered and came from the claimed sender — but does not provide encryption (no confidentiality). AH also authenticates parts of the outer IP header, which is precisely why it is largely incompatible with NAT (NAT rewrites those header fields, breaking AH's integrity check) and is rarely used today. ESP (Encapsulating Security Payload) provides confidentiality (encryption) and can also provide integrity and authentication of the payload — it is the workhorse that does what people actually want (encrypt the traffic), and it is NAT-traversable, so it is used almost exclusively in practice. The simple takeaway: ESP (encryption, used everywhere) versus AH (integrity only, obsolete).
The two modes determine how much of the packet is protected and what the topology is. Transport mode protects only the payload of the IP packet, leaving the original IP header intact; it is used for host-to-host communication (two endpoints securing their direct traffic). Tunnel mode encapsulates the entire original packet (header and all) inside a new IP packet with a new header; this hides the original source and destination and is used for network-to-network or host-to-network VPNs — the classic site-to-site VPN where two office networks are bridged over the internet. Tunnel mode is what most VPNs use, because it protects the whole packet and allows gateways to represent entire networks. The key management that sets all this up is IKE (Internet Key Exchange), which authenticates the peers (via pre-shared keys or certificates) and negotiates the encryption keys and parameters — the IPsec equivalent of the TLS handshake. Putting it together: a typical VPN is ESP in tunnel mode, negotiated by IKE — encrypting entire packets between two gateways so that all traffic between two networks travels securely over the untrusted internet.
| Choice | Option | Provides / Use |
|---|---|---|
| Protocol | AH | integrity + auth, no encryption; NAT-incompatible; obsolete |
| Protocol | ESP | encryption (+ optional integrity/auth); NAT-traversable; used everywhere |
| Mode | Transport | protects payload only; host-to-host |
| Mode | Tunnel | protects the whole original packet; network-to-network VPNs |
Examples
IPsec operates at Layer 3 -> protects IP packets for ANY application transparently.
Transport mode (host-to-host): protect the payload, keep the original header
[ IP hdr | ESP | payload ] two endpoints securing direct traffic
Tunnel mode (network-to-network VPN): wrap the WHOLE packet in a new one
[ new IP hdr | ESP | ORIGINAL IP hdr | payload ]
\__ gateway-to-gateway: hides the original src/dst, bridges two networks __/
Typical VPN = ESP + Tunnel mode, keys negotiated by IKE (the "handshake").
Choosing protocol and mode:
want encryption? -> ESP (always, in practice)
only integrity, no crypto?-> AH (rare, and breaks through NAT)
securing two hosts' direct traffic? -> Transport mode
bridging two networks / remote access VPN? -> Tunnel mode
Site-to-site office VPN: ESP, Tunnel mode, IKE with certificates or PSK.
Key Takeaways
- IPsec secures traffic at the network layer (Layer 3), protecting IP packets transparently for any application — the basis of most VPNs.
- AH provides integrity and authentication but no encryption and is NAT-incompatible (it authenticates header fields NAT rewrites), so it is obsolete; ESP provides encryption (plus optional integrity) and is NAT-traversable — used almost exclusively.
- Transport mode protects only the payload for host-to-host communication; tunnel mode encapsulates the entire original packet for network-to-network and remote-access VPNs.
- IKE (Internet Key Exchange) authenticates peers and negotiates keys/parameters — IPsec's equivalent of the TLS handshake.
- A typical VPN is ESP in tunnel mode negotiated by IKE, encrypting whole packets between gateways over the untrusted internet.
🧪 Practice
- Contrast AH and ESP by the protections they provide and explain why AH is rarely used.
- Explain the difference between transport and tunnel mode and the topology each suits.
- Explain why a site-to-site VPN uses ESP in tunnel mode specifically.
- Interview-style: "Why does AH break when traffic passes through NAT, while ESP generally does not?" Hint: recall which header fields each protocol protects and what NAT modifies.
VPN Types: Site-to-Site and Remote Access
Theory
A VPN (Virtual Private Network) creates a secure, encrypted tunnel across an untrusted network (usually the internet), making geographically separate systems behave as if they were on the same private network. The "virtual" and "private" in the name capture the idea: you get the privacy of a dedicated private link without the cost of actually running private cable, by encrypting traffic so the public internet cannot read it. VPNs are the primary way organizations extend their trusted network securely, and they come in two architectural types that solve different problems.
A site-to-site VPN connects entire networks to each other — typically two offices, or an office and a cloud environment — through VPN gateways at each end. Users on either network communicate transparently, unaware the traffic is being encrypted and tunneled between the gateways; no VPN software runs on the individual devices. This is the IPsec-ESP-tunnel-mode scenario from the previous topic, and it is how multi-site organizations build a unified private network over the internet. A remote-access VPN connects an individual user's device to a network — the classic "work from home" VPN, where an employee's laptop runs a VPN client that establishes an encrypted tunnel to the corporate gateway, after which the laptop behaves as if it were on the office network. Remote-access VPNs authenticate the user (and increasingly the device posture) and are implemented with IPsec, or increasingly with TLS-based VPNs (SSL VPN, OpenVPN) and modern protocols like WireGuard (valued for its simplicity, small codebase, and performance).
Several security considerations shape VPN deployment. The first is the split-tunnel versus full-tunnel decision: a full tunnel sends all the user's traffic through the corporate network (so it is inspected and protected by corporate controls, but adds latency and load), while a split tunnel sends only corporate-bound traffic through the VPN and the rest directly to the internet (faster, but the device's non-corporate traffic bypasses corporate security — a real risk if the device is compromised). The second is that the VPN extends the trust boundary to the remote device: a compromised laptop on a full VPN is effectively a compromised device inside the network, which is exactly the flat-network lateral-movement risk from the segmentation topic — and a major reason the industry is shifting from VPNs toward Zero Trust Network Access (ZTNA), which grants access to specific applications after per-request verification rather than placing the device on the whole network. The third is that the VPN gateway is a high-value, internet-facing target (VPN appliance vulnerabilities have caused major breaches), so it must be patched and hardened. The framing to carry forward: a VPN provides an encrypted tunnel and network extension, but "connected to the VPN" is not the same as "trusted," which is the critique Zero Trust answers.
| Site-to-site VPN | Remote-access VPN | |
|---|---|---|
| Connects | network ↔ network | individual device ↔ network |
| Endpoints | VPN gateways at each site | client software ↔ gateway |
| Authenticates | the gateways/sites | the user (and device posture) |
| Typical use | branch offices, office↔cloud | work-from-home, mobile users |
Examples
Two VPN architectures:
SITE-TO-SITE (networks): no client software on devices
Office A LAN --[gateway]==encrypted tunnel==[gateway]-- Office B LAN
users on each side communicate transparently (ESP tunnel mode).
REMOTE-ACCESS (device): VPN client on the laptop
laptop --[VPN client]==encrypted tunnel==[corporate gateway]-- office network
authenticates the USER (+ posture); laptop acts as if on the office LAN.
Split vs full tunnel, and the trust problem VPNs create:
FULL tunnel: ALL traffic -> corporate network (inspected/protected, slower)
SPLIT tunnel: corporate traffic -> VPN; internet traffic -> direct (faster,
but device's other traffic bypasses corporate security)
TRUST RISK: a compromised laptop on a full VPN = a compromised device INSIDE
the network (lateral movement). -> industry shift to ZERO TRUST (ZTNA):
grant access per-application after verifying each request, not the whole network.
Key Takeaways
- A VPN creates an encrypted tunnel over an untrusted network, giving the privacy of a dedicated private link without the cost.
- Site-to-site VPNs connect entire networks via gateways (no client on devices — branch offices, office↔cloud); remote-access VPNs connect an individual device via client software, authenticating the user and device posture.
- Full tunnel routes all traffic through the corporate network (inspected but slower); split tunnel routes only corporate traffic through the VPN (faster but the rest bypasses corporate security).
- A VPN extends the trust boundary to the remote device — a compromised device on a full VPN is effectively inside the network (lateral-movement risk), driving the shift to Zero Trust Network Access.
- VPN gateways are high-value internet-facing targets requiring patching and hardening; "connected to the VPN" is not the same as "trusted."
🧪 Practice
- Distinguish site-to-site and remote-access VPNs by what they connect and where the encryption endpoints are.
- Explain the split-tunnel vs full-tunnel tradeoff and the security risk of split tunneling.
- Explain how a VPN extends the trust boundary and why that motivates Zero Trust Network Access.
- Interview-style: "Why is 'the device is connected to the corporate VPN' an insufficient basis for trusting it, and what model addresses this?" Hint: think about what a compromised laptop can reach once it is placed on the network, and per-request verification.
DNSSEC, DoH, and DoT
Theory
The DNS attacks earlier in the chapter (spoofing, cache poisoning) exploited two separate weaknesses: DNS responses are not authenticated (so forgeries are accepted) and DNS queries are not encrypted (so they can be observed and tampered with in transit). These three technologies address those weaknesses, and the essential point — frequently confused — is that they solve different problems and are complementary, not alternatives: DNSSEC provides integrity/authentication, while DoH and DoT provide confidentiality.
DNSSEC (DNS Security Extensions) adds authentication and integrity to DNS by cryptographically signing DNS records. Each zone signs its records with a private key, and resolvers validate the signatures up a chain of trust rooted at the DNS root zone — so a resolver can verify that an answer genuinely came from the authoritative zone and was not forged or altered (defeating cache poisoning, as the DNS spoofing topic noted). What DNSSEC does not do is encrypt: the queries and answers still travel in cleartext, so an observer can see what you are looking up. It also does not protect the "last mile" between the resolver and the client by itself, and its deployment remains incomplete. The mental model: DNSSEC makes DNS answers trustworthy (you know they are genuine), not private.
DoT (DNS over TLS) and DoH (DNS over HTTPS) add confidentiality by encrypting the DNS query between the client and the resolver, so an on-path observer (or an ISP, or an attacker in a MitM position) cannot see or tamper with your DNS lookups. DoT runs DNS inside a TLS connection on a dedicated port (853), which keeps it identifiable as DNS traffic (network operators can see that it is DNS, just not the contents). DoH runs DNS inside HTTPS on port 443, making it indistinguishable from ordinary web traffic — which is a privacy advantage (it cannot be selectively blocked or monitored as DNS) but also a point of controversy, because it bypasses network-level DNS monitoring and filtering that enterprises and security tools rely on, and centralizes DNS with the DoH provider. What DoH/DoT do not do is authenticate the data — they secure the channel to the resolver, but if the resolver itself returns a forged answer (or is compromised), encryption does not detect it; that is DNSSEC's job. The complete picture: DNSSEC authenticates the answer, DoH/DoT encrypt the question — a fully protected DNS lookup wants both, and understanding which provides which is the key exam-and-interview distinction.
| DNSSEC | DoT | DoH | |
|---|---|---|---|
| Provides | authentication/integrity of answers | confidentiality of queries | confidentiality of queries |
| Encrypts? | no | yes (TLS, port 853) | yes (HTTPS, port 443) |
| Authenticates data? | yes (signatures) | no (channel only) | no (channel only) |
| Distinguishable as DNS? | yes | yes (dedicated port) | no (looks like HTTPS) |
| Addresses | cache poisoning/forgery | eavesdropping on lookups | eavesdropping + evades DNS filtering |
Examples
Complementary, not alternatives -- they solve different problems:
DNSSEC -> "is this answer GENUINE?" (integrity/auth; NOT encrypted)
DoT/DoH -> "can anyone SEE my query?" (confidentiality; NOT data-authenticated)
Fully protected lookup wants BOTH:
DoH/DoT encrypts the question to the resolver
+ DNSSEC lets the resolver prove the answer is authentic.
# DNSSEC: look for signatures (RRSIG) and the authenticated-data flag.
dig example.com +dnssec | grep -E "RRSIG|flags:"
# 'ad' flag set => the resolver validated DNSSEC signatures -> answer is authentic.
# DoT (port 853) and DoH (port 443) encrypt the query to the resolver:
kdig -d @1.1.1.1 +tls example.com # DNS over TLS
curl -s -H 'accept: application/dns-json' \
'https://1.1.1.1/dns-query?name=example.com&type=A' # DNS over HTTPS
# Note: these encrypt the CHANNEL; they do not prove the ANSWER is genuine (that's DNSSEC).
Key Takeaways
- DNS's weaknesses are unauthenticated answers and unencrypted queries; these technologies address different ones and are complementary, not alternatives.
- DNSSEC signs DNS records so resolvers can verify answers are genuine via a chain of trust to the root — providing authentication/integrity (defeating forgery/poisoning) but not confidentiality.
- DoT encrypts DNS in TLS on port 853 (identifiable as DNS); DoH encrypts DNS in HTTPS on port 443 (indistinguishable from web traffic) — both provide confidentiality of queries but do not authenticate the answer.
- DoH's indistinguishability is a privacy gain but controversial, as it bypasses enterprise DNS monitoring/filtering and centralizes DNS with the provider.
- The complete picture: DNSSEC authenticates the answer, DoH/DoT encrypt the question — full protection wants both.
🧪 Practice
- State which property (confidentiality vs authentication) each of DNSSEC, DoT, and DoH provides.
- Explain why DNSSEC does not make your DNS lookups private, and why DoH does not make the answers trustworthy.
- Explain the enterprise controversy around DoH compared to DoT.
- Interview-style: "A resolver uses DoH but not DNSSEC. Can it still be fed a forged answer, and by whom?" Hint: encryption protects the channel to the resolver — consider a malicious or poisoned resolver itself.
Email Security: SPF, DKIM, DMARC
Theory
Email's foundational protocol, SMTP, was designed in an era of mutual trust and has no built-in authentication of the sender — anyone can put any address in the "From" field, which is why email spoofing, phishing, and business email compromise are so pervasive. SPF, DKIM, and DMARC are three DNS-based standards that, layered together, let a receiving mail server verify that a message genuinely came from the domain it claims — they are the authentication SMTP never had. They are best understood as a stack where each covers a gap the others leave.
SPF (Sender Policy Framework) lets a domain publish, in DNS, a list of the IP addresses/servers authorized to send email on its behalf. A receiving server checks whether the message arrived from an IP on that list. SPF's limitation is that it authenticates the envelope sender (the MAIL FROM, used in routing) and the connecting IP — not the "From" header the user actually sees — and it breaks when email is forwarded (the forwarder's IP is not in the original domain's SPF record). DKIM (DomainKeys Identified Mail) addresses the integrity and forwarding gaps: the sending server attaches a cryptographic signature (over the message headers and body) using a private key, and publishes the corresponding public key in DNS. The receiver verifies the signature, proving the message was authorized by the domain and was not altered in transit — and because the signature travels with the message, DKIM survives forwarding. DKIM's limitation is that it does not, by itself, tell the receiver what to do if validation fails, nor does it require that the signing domain match the visible "From."
DMARC (Domain-based Message Authentication, Reporting, and Conformance) ties the other two together and closes the critical gap: it requires that SPF or DKIM not only pass but align with the domain in the visible "From" header (so an attacker cannot pass SPF/DKIM for their own domain while spoofing yours in the From field). DMARC lets the domain owner publish a policy telling receivers what to do with messages that fail alignment — none (monitor only), quarantine (send to spam), or reject (refuse outright) — and provides reporting so the owner sees who is sending (and spoofing) mail as their domain. The progression is the key insight: SPF authorizes sending IPs, DKIM cryptographically signs the message (surviving forwarding), and DMARC enforces alignment with the visible sender and dictates the action plus reporting. Deployed together with a reject policy, they make it very hard to spoof a protected domain — which is why they are a baseline anti-phishing control, though they protect against exact-domain spoofing, not lookalike domains or display-name tricks (which need user awareness and other controls).
| SPF | DKIM | DMARC | |
|---|---|---|---|
| Mechanism | DNS list of authorized sending IPs | cryptographic signature + public key in DNS | policy + alignment + reporting |
| Verifies | connecting IP / envelope sender | message authorized by domain + unaltered | SPF/DKIM align with visible "From" |
| Survives forwarding? | no | yes | relies on DKIM |
| Adds | sender IP authorization | integrity + domain signing | enforcement action + visibility |
Examples
The three layers, each covering the others' gaps:
SPF: "which IPs may send for example.com?" (DNS TXT list)
- authenticates envelope sender/IP, NOT the visible From; breaks on forwarding
DKIM: "this message is signed by example.com and unaltered" (crypto signature)
- survives forwarding; but doesn't dictate action or enforce From alignment
DMARC: "require SPF or DKIM to ALIGN with the visible From, else <policy>, and report"
- closes the spoofed-From gap; actions: none | quarantine | reject
; DNS records that implement the three (conceptual):
example.com. TXT "v=spf1 ip4:192.0.2.0/24 include:_spf.provider.com -all"
; authorized senders ---------------------- -all = reject others
sel._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSq...AQAB" ; DKIM public key
_dmarc.example.com. TXT "v=DMARC1; p=reject; rua=mailto:reports@example.com; adkim=s; aspf=s"
; ^enforce reject ^get reports ^strict alignment
Key Takeaways
- SMTP has no built-in sender authentication (anyone can forge "From"), so SPF, DKIM, and DMARC are DNS-based layers that verify a message truly came from the claimed domain.
- SPF publishes authorized sending IPs in DNS but authenticates the envelope sender/IP (not the visible "From") and breaks on forwarding.
- DKIM cryptographically signs the message (headers and body) with a key whose public half is in DNS, proving authorization and integrity and surviving forwarding — but does not dictate action or enforce "From" alignment.
- DMARC requires SPF or DKIM to align with the visible "From," publishes an enforcement policy (none/quarantine/reject), and provides reporting — closing the spoofed-From gap.
- Together with a
rejectpolicy they strongly prevent exact-domain spoofing, but not lookalike domains or display-name tricks, which need user awareness.
🧪 Practice
- Explain the specific gap in SPF that DKIM fixes, and the gap in DKIM that DMARC fixes.
- Explain why SPF breaks on forwarding but DKIM does not.
- Describe the three DMARC policy actions and what "alignment" means.
- Interview-style: "A phishing email passes SPF and DKIM checks yet spoofs your company in the From field. How, and which control stops it?" Hint: the attacker authenticated their own domain — think about what DMARC alignment additionally requires.
<a id="67-wireless-and-mobile-network-security"></a>
6.7 Wireless and Mobile Network Security
Wireless media broadcast to anyone in range, so they cannot rely on physical access control the way wired networks do — security must come entirely from cryptography and protocol design. This section covers Wi-Fi security's evolution and its attacks, then the broader wireless attack surface of Bluetooth, cellular, NFC, and RFID, and the operational practice of surveying and defending wireless environments.
WEP, WPA, WPA2, and WPA3
Theory
The history of Wi-Fi security is a cautionary tale about getting cryptography right, told through four generations of protocols. Each was created to fix the fatal flaws of its predecessor, and tracing that evolution teaches both why each mechanism exists and how cryptographic mistakes get exploited. The common challenge throughout: a wireless network broadcasts to everyone in range, so unlike a wired network it cannot assume that physical access equals authorization — strong encryption and authentication are the only protection.
WEP (Wired Equivalent Privacy) was the original (1997) and is catastrophically broken — a textbook case of flawed crypto. It used the RC4 stream cipher with a fatally short, reused initialization vector (IV): because the IV space was tiny (24 bits), IVs inevitably repeated, and repeated IVs with a stream cipher leak key material. Within minutes of captured traffic, tools can recover the WEP key entirely. WEP must never be used. WPA (Wi-Fi Protected Access) was a 2003 stopgap designed to run on existing WEP hardware via a firmware update; it introduced TKIP, which added per-packet key mixing and a message integrity check to patch WEP's worst flaws, but because it was constrained to the same hardware and still built on RC4, it was a transitional fix and is now also considered insecure.
WPA2 (2004) was the long-standing standard and the first to use AES-CCMP — real, strong, modern authenticated encryption rather than RC4 patches. WPA2 is fundamentally sound in its cryptography, and its main weaknesses are in the handshake (the KRACK attack, next topic) and in WPA2-Personal's pre-shared key, which is vulnerable to offline dictionary attacks: an attacker who captures the 4-way handshake can brute-force a weak passphrase offline at leisure. WPA3 (2018) is the current standard and fixes these remaining issues. Its headline improvement is replacing the PSK handshake with SAE (Simultaneous Authentication of Equals, a.k.a. Dragonfly), which provides forward secrecy and — crucially — is resistant to offline dictionary attacks (an attacker who captures the handshake cannot brute-force the password offline; each guess requires a fresh interaction, which is detectable and rate-limitable). WPA3 also adds protected management frames (against deauthentication attacks) and opportunistic wireless encryption for open networks (encrypting even passwordless Wi-Fi). The arc of the story is the recurring security lesson: do not invent or cling to weak cryptography — WEP's homemade IV scheme, WPA's hardware-constrained patches, and WPA2's handshake flaw were each fixed by adopting properly designed primitives.
| Year | Encryption | Key weakness | Status | |
|---|---|---|---|---|
| WEP | 1997 | RC4 + 24-bit IV | IV reuse → key recovery in minutes | catastrophically broken |
| WPA | 2003 | TKIP (RC4-based) | hardware-constrained patch | insecure/deprecated |
| WPA2 | 2004 | AES-CCMP | KRACK; offline PSK dictionary attack | sound crypto, use with care |
| WPA3 | 2018 | AES + SAE handshake | current best; adoption ongoing | recommended |
Examples
Why WEP fails (the archetypal crypto mistake):
RC4 is a STREAM cipher: keystream = f(key, IV). Reusing (key, IV) reuses keystream.
WEP's IV is only 24 bits -> ~16.7M values -> repeats quickly on a busy network.
repeated keystream + known plaintext -> recover key material -> full key in MINUTES.
Lesson: a short, reused IV with a stream cipher is fatal. WPA3's SAE avoids this entirely.
The security progression (each fixes the prior's fatal flaw):
WEP -> broken IV/RC4 -> key recovered in minutes
WPA -> TKIP patch on old HW -> transitional, now insecure
WPA2 -> AES-CCMP (strong crypto) -> but handshake (KRACK) + offline PSK cracking
WPA3 -> SAE handshake -> forward secrecy + offline-dictionary RESISTANT
+ protected mgmt frames + encrypted open Wi-Fi
Key Takeaways
- Wireless broadcasts to everyone in range, so cryptography and authentication are the only protection — physical access cannot be assumed to equal authorization.
- WEP is catastrophically broken: RC4 with a 24-bit IV reuses keystream, allowing full key recovery in minutes — never use it.
- WPA was a transitional patch (TKIP on WEP-era hardware) and is now insecure; WPA2 introduced strong AES-CCMP encryption and is cryptographically sound.
- WPA2's weaknesses are its handshake (KRACK) and WPA2-Personal's offline dictionary attack on weak pre-shared keys from a captured handshake.
- WPA3 replaces the PSK handshake with SAE (Dragonfly), adding forward secrecy and resistance to offline dictionary attacks, plus protected management frames and encrypted open networks — the current recommendation.
🧪 Practice
- Explain precisely why WEP's initialization vector makes it breakable, in terms of stream-cipher keystream reuse.
- Explain the offline dictionary attack against WPA2-Personal and how WPA3's SAE resists it.
- Order the four protocols by security and state the single most important improvement at each step.
- Interview-style: "Why can an attacker who captures a WPA2-Personal handshake crack a weak password, but capturing a WPA3 handshake does not allow the same offline attack?" Hint: compare whether each password guess can be tested offline or requires a fresh, detectable interaction with the network.
4-Way Handshake and KRACK Attack
Theory
The 4-way handshake is the mechanism WPA2 (and WPA) use to confirm that both the client and the access point know the network password and to derive the fresh session keys that will encrypt the actual data — without ever sending the password over the air. It is a challenge-response/key-confirmation protocol (connecting to the challenge-response concepts from the authentication section), and understanding it is necessary both to see how Wi-Fi keys are established and to understand the KRACK attack that broke it.
The handshake's purpose is to take the shared secret (the PMK, derived from the passphrase in Personal mode, or from 802.1X in Enterprise mode) and use a four-message exchange of nonces to derive a unique per-session PTK (Pairwise Transient Key) and install it for encryption. In outline: the AP sends a nonce (message 1); the client derives the PTK and sends its own nonce plus a message integrity code (message 2); the AP derives the same PTK and sends the group key plus confirmation (message 3); the client acknowledges and installs the key (message 4). After this, both sides have a fresh session key and data encryption begins. Because fresh nonces are used each time, each session gets unique keys, and the password itself is never transmitted — only used locally to derive the PMK.
KRACK (Key Reinstallation Attack, 2017) was a devastating flaw not in WPA2's encryption but in this handshake's state machine. The vulnerability: message 3 can be retransmitted (in case message 4 is lost), and when a client receives message 3 again, it reinstalls the already-in-use session key — resetting the associated nonce/packet-number counter to zero. With a stream-cipher-like construction, reusing a nonce with the same key reuses keystream, which (as with WEP) leaks plaintext and allows decryption, replay, and in some cases forgery of packets. The attacker, in a MitM position, forces the reinstallation by blocking message 4 and replaying message 3. The crucial lessons are twofold: first, that a cryptographically strong cipher can still be defeated by a flaw in the protocol that manages its keys — the encryption (AES-CCMP) was fine; the key-handling logic was broken, reiterating that nonce reuse is a recurring fatal mistake. Second, KRACK was fixed with software patches on both clients and APs (so patching was the immediate remedy, not replacing WPA2 wholesale), and WPA3's new handshake design avoids the class of flaw. It is a perfect case study in why protocol-level reasoning matters as much as choosing strong primitives.
Examples
The WPA2 4-way handshake (derive + install a fresh session key, password never sent):
AP Client
| --- msg1: ANonce ------------------------> | client derives PTK from PMK+nonces
| <-- msg2: SNonce + MIC ------------------- | AP derives the same PTK
| --- msg3: group key + MIC ---------------> |
| <-- msg4: ACK ---------------------------- | CLIENT INSTALLS THE KEY -> encrypt
fresh nonces => unique per-session keys.
KRACK: reinstall the key by replaying message 3.
attacker (MitM) BLOCKS msg4 -> AP retransmits msg3 -> client REINSTALLS the
in-use PTK and RESETS its nonce/packet counter to 0.
nonce reuse with the same key -> keystream reuse (like WEP!) ->
decrypt / replay / sometimes forge packets.
Lesson: AES-CCMP was fine; the KEY-MANAGEMENT state machine was flawed.
Fix: software patch (don't reinstall an in-use key). WPA3 avoids the class entirely.
Key Takeaways
- The WPA2 4-way handshake confirms both sides know the password and derives a fresh per-session key (PTK) from the shared PMK using exchanged nonces — the password is never transmitted.
- Fresh nonces per handshake give each session unique keys; it is a challenge-response/key-confirmation protocol.
- KRACK exploited the handshake's state machine, not the encryption: replaying message 3 forces the client to reinstall the in-use key and reset its nonce counter to zero.
- Resulting nonce/keystream reuse (the same class of error as WEP) allowed decryption, replay, and sometimes forgery — showing a strong cipher can be defeated by flawed key management.
- KRACK was fixed with software patches on clients and APs; WPA3's handshake design avoids the vulnerability class — protocol-level reasoning matters as much as choosing strong primitives.
🧪 Practice
- Describe the purpose of the 4-way handshake and what key it produces, and confirm the password is never sent.
- Explain the KRACK attack: what is reinstalled, what counter resets, and why that breaks encryption.
- Explain why KRACK is a protocol flaw rather than a weakness in AES-CCMP.
- Interview-style: "KRACK causes nonce reuse. Why is that catastrophic, and what earlier Wi-Fi protocol failed for the same underlying reason?" Hint: relate keystream reuse to WEP's IV problem.
Enterprise Wi-Fi with 802.1X
Theory
The Wi-Fi security so far assumed a single shared password (WPA-Personal / PSK mode), which is fine for a home but has serious problems at organizational scale: everyone shares one secret, so you cannot identify who connected, you cannot revoke one user without changing the password for everyone, and a single leaked passphrase compromises the whole network. Enterprise Wi-Fi solves this by using 802.1X (the port-based authentication standard from the NAC topic) to give each user or device its own credentials, authenticated against a central server. This is WPA2/WPA3-Enterprise mode, and it is the standard for any serious deployment.
The architecture is the same three-role 802.1X model seen in NAC: the supplicant (the connecting device), the authenticator (the access point/controller), and the authentication server (a RADIUS server, which checks credentials against a directory like Active Directory). Instead of a shared PSK, the client authenticates through an EAP (Extensible Authentication Protocol) method, and the resulting per-user authentication both grants access and feeds the key derivation — so each user gets unique session keys derived from their own authentication, not from a network-wide password. The benefits are exactly the PSK weaknesses inverted: individual accountability (logs show which user/device connected), per-user revocation (disable one account without affecting others), no shared secret to leak, and integration with existing identity systems and policies (including posture checks and dynamic VLAN assignment).
The security of Enterprise Wi-Fi hinges on the EAP method chosen, and this is where deployments succeed or fail. The strongest common methods wrap authentication in a TLS tunnel and depend critically on the client validating the authentication server's certificate — which is precisely the defense against the evil-twin attack from the Network Attacks section. EAP-TLS uses mutual certificate authentication (both client and server present certificates) and is the most secure, but requires a client-certificate (PKI) deployment. PEAP and EAP-TTLS tunnel a password-based inner authentication inside a server-authenticated TLS tunnel — easier to deploy (users just have passwords) but only secure if the client verifies the server certificate; a client misconfigured to skip that check can be lured onto a rogue RADIUS server (an evil twin) that harvests the credentials. This is the single most important Enterprise Wi-Fi pitfall: the whole security model rests on server-certificate validation, and disabling it (a common "make it work" shortcut) reopens the evil-twin attack it was meant to close. The takeaway connects the authentication, NAC, and wireless-attack topics: Enterprise Wi-Fi brings real identity and mutual authentication to wireless, but only if configured to actually verify the server.
Examples
Personal (PSK) vs Enterprise (802.1X):
PERSONAL: one shared passphrase for everyone
- no per-user identity, no selective revocation, one leak = whole network
ENTERPRISE (WPA2/WPA3-Enterprise via 802.1X):
supplicant --EAP--> authenticator (AP) --RADIUS--> auth server --> directory
per-user credentials -> individual accountability, per-user revocation,
unique session keys per user, posture/VLAN policy.
EAP method security rests on SERVER-CERTIFICATE VALIDATION (anti evil-twin):
EAP-TLS : mutual certs (client + server) -> strongest; needs client PKI
PEAP/EAP-TTLS: password inside a server-cert TLS tunnel -> easy, BUT only safe if
the client VALIDATES the server cert.
MISCONFIG: client set to NOT verify the server cert
-> attacker runs a rogue RADIUS (evil twin) -> harvests the inner credentials.
=> The #1 Enterprise Wi-Fi pitfall: skipping server-cert validation reopens evil twin.
Key Takeaways
- WPA-Personal's single shared PSK gives no per-user identity, no selective revocation, and total compromise from one leaked passphrase — unacceptable at scale.
- Enterprise Wi-Fi (WPA2/WPA3-Enterprise) uses 802.1X to give each user/device its own credentials authenticated against a central RADIUS server, with the same supplicant/authenticator/auth-server roles as NAC.
- Benefits are the PSK weaknesses inverted: individual accountability, per-user revocation, no shared secret, and integration with identity, posture, and VLAN policy; each user gets unique session keys from their own authentication.
- Security depends on the EAP method: EAP-TLS (mutual certificates) is strongest; PEAP/EAP-TTLS tunnel a password inside a server-authenticated TLS tunnel and are safe only if the client validates the server certificate.
- The top pitfall is disabling server-certificate validation, which reopens the evil-twin attack by letting a rogue RADIUS server harvest credentials.
🧪 Practice
- List three concrete problems with WPA-Personal that Enterprise Wi-Fi solves and how.
- Name the three 802.1X roles in an Enterprise Wi-Fi authentication and what each does.
- Explain why server-certificate validation is essential for PEAP/EAP-TTLS and what breaks without it.
- Interview-style: "An Enterprise Wi-Fi deployment using PEAP is having credentials stolen. What misconfiguration should you suspect?" Hint: recall what the client must verify about the RADIUS server and the evil-twin attack enabled by skipping it.
Bluetooth Attack Surface
Theory
Bluetooth is ubiquitous — headsets, keyboards, wearables, car systems, medical devices, IoT — and every one of those connections is a short-range wireless attack surface. Because Bluetooth devices are often "invisible" infrastructure that users rarely think about as networked, its security is frequently neglected, making it a rewarding target. The core security challenges stem from its design for convenient, ad-hoc pairing between devices that may have no prior relationship and often minimal user interfaces (no screen or keyboard to confirm a connection).
The attack surface spans several categories, and the named attacks illustrate the recurring themes of pairing weaknesses, information leakage, and implementation bugs. Pairing/authentication attacks exploit weak or legacy pairing: older "Just Works" pairing provides no man-in-the-middle protection, and attacks like BIAS and the KNOB attack (Key Negotiation of Bluetooth) force the negotiation of a dangerously short encryption key (as little as 1 byte of entropy) that is then brute-forced — another instance of a downgrade attack against the key-establishment step. Information-gathering/tracking attacks include bluesnarfing (unauthorized access to data — contacts, messages — on a device) and tracking devices by their Bluetooth identifiers (a privacy concern that modern address randomization aims to mitigate). Unsolicited-contact attacks like bluejacking (sending unsolicited messages) are mostly nuisance, but bluebugging (gaining control of a device's functions) is serious. And as with all software, implementation vulnerabilities in Bluetooth stacks have been severe — BlueBorne (2017) was a set of flaws allowing remote code execution with no pairing and no user interaction, across billions of devices, demonstrating that a listening Bluetooth stack is remote attack surface even when "not connected."
The practical defenses follow from the threats. Keep Bluetooth off or non-discoverable when not in use (reducing the surface — a device not listening cannot be BlueBorne'd), use modern versions and pairing (Bluetooth 4.2+ with Secure Connections, which uses proper ECDH key exchange and provides MitM protection when a comparison method is used), patch device firmware (implementation bugs are fixed in updates), avoid pairing in public/untrusted settings, and for sensitive devices prefer those that require user confirmation for pairing. A useful framing that connects to the rest of the chapter: Bluetooth recapitulates the same security themes as Wi-Fi — weak legacy crypto, downgrade/key-negotiation attacks, and the critical importance of authenticated pairing — just at short range and on a far more diverse and often unpatched device population, which is what makes it a persistent and under-appreciated risk.
Examples
Bluetooth attack surface by category (and the recurring theme each shows):
Pairing/key: KNOB / BIAS -> force a 1-byte encryption key -> brute-force it
(a DOWNGRADE attack on key negotiation -- same theme as Wi-Fi)
"Just Works" pairing -> no MitM protection
Data/tracking: bluesnarfing (steal contacts/messages), BT-identifier tracking
Unsolicited: bluejacking (nuisance messages), bluebugging (control the device)
Implementation: BlueBorne (2017) -> RCE with NO pairing, NO user action,
just a listening stack -> billions of devices.
Defenses map to the threats:
turn Bluetooth OFF / non-discoverable when unused -> shrink attack surface
Bluetooth 4.2+ Secure Connections (ECDH + numeric compare) -> MitM-resistant pairing
patch firmware/stack -> fixes BlueBorne-class bugs
don't pair in public / require user confirmation -> blocks rogue pairing
Key Takeaways
- Bluetooth is a ubiquitous, often-neglected short-range attack surface across headsets, keyboards, wearables, cars, and IoT, with security challenges rooted in convenient ad-hoc pairing and minimal device UIs.
- Pairing/key-negotiation attacks (KNOB, BIAS) downgrade encryption to a brute-forceable key; legacy "Just Works" pairing offers no MitM protection.
- Data and tracking attacks include bluesnarfing (stealing data) and identifier-based tracking; bluejacking is nuisance while bluebugging grants control.
- Implementation flaws can be severe — BlueBorne allowed remote code execution with no pairing or user interaction, proving a listening stack is remote attack surface.
- Defend by disabling/hiding Bluetooth when unused, using modern Secure Connections pairing, patching firmware, and avoiding pairing in untrusted settings — Bluetooth recapitulates Wi-Fi's themes (weak legacy crypto, downgrade attacks, authenticated pairing) on a more diverse, less-patched device population.
🧪 Practice
- Explain the KNOB attack as a downgrade attack and relate it to a Wi-Fi equivalent.
- Explain why BlueBorne was especially dangerous given its pairing and interaction requirements.
- List four practical Bluetooth defenses and the threat each addresses.
- Interview-style: "Why is 'Just Works' Bluetooth pairing convenient but risky, and what does Secure Connections add?" Hint: think about man-in-the-middle during pairing and what a numeric-comparison step verifies.
Cellular Network Security Concerns
Theory
Cellular networks (2G/3G/4G/5G) connect billions of mobile devices, and their security is distinctive because the network operator provides much of it and because legacy generations remain supported for compatibility — which is precisely where many attacks live. Unlike Wi-Fi, where you control the access point, on cellular you are trusting the carrier's infrastructure, and the historical weakness has been that devices can be tricked into using an older, weaker generation or a fake base station.
The foundational problem in older generations is lack of mutual authentication. In 2G (GSM), the network authenticates the phone but the phone does not authenticate the network — so a device will attach to any base station claiming to be its carrier. This is the enabling flaw for the IMSI catcher / Stingray (fake base station): an attacker operates a rogue cell tower with a strong signal, devices in range connect to it believing it is the real network, and the attacker can then identify/track devices (capturing the IMSI, the subscriber's unique identifier), and in 2G even intercept calls and texts (2G's encryption, A5/1, is also broken). The classic attack is a downgrade: even on a 4G/5G phone, an IMSI catcher can force the device down to 2G where authentication is one-way and crypto is weak — the same downgrade pattern seen in TLS, Bluetooth, and Wi-Fi. 3G and 4G (LTE) introduced mutual authentication (the device authenticates the network too), closing the basic fake-base-station problem for those generations, though other weaknesses and tracking vectors remained.
5G makes meaningful security improvements: stronger mutual authentication, and notably encryption of the IMSI (now called SUPI, transmitted as an encrypted SUCI) to defeat the IMSI-catcher identification attack that plagued earlier generations, plus better integrity protection. However, 5G still interoperates with older generations for coverage, so downgrade attacks remain a concern until legacy support is fully retired, and 5G's expanded, software-defined, IoT-heavy architecture introduces new attack surface. The broader security concerns relevant to a mobile user and defender: SIM-related attacks — most importantly SIM swapping (a social-engineering attack where an attacker convinces the carrier to port the victim's number to the attacker's SIM, defeating SMS-based MFA and enabling account takeover, which is the concrete reason SMS is the weakest MFA factor from the authentication section) — SS7/Diameter signaling attacks (exploiting the trusted inter-carrier signaling protocols to intercept texts/calls or track location, often used to defeat SMS 2FA remotely), and location tracking. The practical takeaways: treat SMS as a weak second factor (prefer app-based or hardware MFA), be aware that cellular interception is feasible (use end-to-end encrypted apps for sensitive communication regardless of the carrier link), and recognize that the persistence of legacy generations is the root of much cellular insecurity — the same "weak legacy still supported" theme that runs through this entire section.
Examples
The IMSI catcher / downgrade attack (enabled by one-way auth in 2G):
2G: network authenticates phone, but PHONE DOES NOT AUTHENTICATE NETWORK.
attacker runs a fake base station (Stingray) with a strong signal:
4G/5G phone --(forced downgrade to 2G)--> FAKE tower
-> captures IMSI (identify/track), 2G crypto (A5/1) broken -> intercept.
3G/4G added MUTUAL authentication; 5G encrypts the IMSI (SUCI) to stop capture.
BUT legacy interop keeps the downgrade path alive until 2G/3G are retired.
SIM swap defeats SMS MFA (why SMS is the weakest factor):
attacker social-engineers the carrier: "port my number to this new SIM"
victim's number now rings the attacker's phone ->
attacker triggers "SMS code" login -> receives the code -> takes over accounts.
Also: SS7/Diameter signaling attacks intercept SMS/calls remotely.
Defense: use app-based (TOTP) or hardware (FIDO2) MFA, not SMS, for anything valuable.
Key Takeaways
- Cellular security is provided largely by the carrier and weakened by the continued support of legacy generations, where many attacks live.
- 2G lacks mutual authentication (the phone does not authenticate the network), enabling IMSI catchers/Stingrays — fake base stations that identify, track, and (in 2G) intercept — commonly via a forced downgrade from 4G/5G.
- 3G/4G added mutual authentication; 5G further encrypts the subscriber identity (SUPI/SUCI) to defeat IMSI capture, but legacy interop keeps downgrade attacks relevant.
- SIM swapping (social-engineering a number port) and SS7/Diameter signaling attacks defeat SMS-based MFA — the concrete reason SMS is the weakest second factor.
- Practical guidance: treat SMS as weak MFA (prefer app-based or hardware), use end-to-end encrypted apps for sensitive communication, and recognize legacy-generation support as the root of much cellular insecurity.
🧪 Practice
- Explain how the lack of mutual authentication in 2G enables an IMSI catcher, and how a downgrade attack exploits it on a modern phone.
- Describe SIM swapping and why it specifically defeats SMS-based MFA.
- State one concrete security improvement 5G makes over 4G and the attack it addresses.
- Interview-style: "Given SIM swapping and SS7 attacks, why is SMS considered the weakest MFA factor, and what should replace it?" Hint: both attacks let someone else receive the victim's texts — relate this to phishing-resistant possession factors.
NFC and RFID Risks
Theory
RFID (Radio-Frequency Identification) and NFC (Near-Field Communication) are short-range wireless identification technologies behind access badges, contactless payments, passports, transit cards, inventory tags, and key fobs. RFID is the broad family of tag-and-reader systems operating at various ranges; NFC is a specific short-range (a few centimeters) subset of high-frequency RFID used for phones and payments. Their security concerns stem from a deceptive assumption: that the short range provides security. It does not — range can be extended, and even at close range the communication can be attacked — so, as everywhere in wireless, security must come from cryptography and protocol design, not from physical proximity.
The risks cluster into recognizable categories. Eavesdropping captures the communication between tag and reader (and the practical range is longer than the nominal operating range, especially with a good antenna). Skimming/unauthorized reading reads a tag without the owner's knowledge — the classic concern with contactless cards and badges, where an attacker with a concealed reader reads a card through a wallet or pocket. Cloning duplicates a tag: many low-cost RFID systems (notably older 125 kHz proximity badges and the broken MIFARE Classic cards) use no or weak authentication and are trivially cloned with cheap hardware (a Proxmark or even a phone), which is a serious physical-access-control weakness — a cloned badge opens the door. Relay attacks are especially important and subtle: the attacker relays the communication between a legitimate tag and reader in real time over a distance, defeating the proximity assumption entirely — the prominent example is keyless car entry relay attacks, where one attacker near the car and another near the key fob (e.g. inside the owner's house) relay the signal to unlock and start the car, even though the key is far away. Finally, replay and data-modification attacks target systems that do not use fresh challenges or integrity protection.
The defenses mirror the rest of the chapter's principles. Cryptographic authentication (challenge-response rather than a static readable ID) defeats cloning and replay — modern payment cards (EMV contactless) and secure badges use this, which is why they cannot be trivially cloned like a 125 kHz proximity card. Encryption protects against eavesdropping. Shielding (RFID-blocking wallets/sleeves) physically blocks skimming when not in use. Relay attacks are the hardest to defeat with crypto alone (the relayed messages are cryptographically valid), so the countermeasure is distance bounding (measuring signal round-trip time to detect the extra latency a relay introduces) or simpler mitigations like motion-sensing key fobs that stop transmitting when still, or storing fobs in a Faraday pouch. The practical lesson: never rely on short range as a security control, prefer systems with cryptographic authentication over static-ID tags, and recognize that the cheapest and most common deployments (old badges, basic tags) are often the most vulnerable — a cloned access badge or a relayed car key are concrete, real-world consequences of treating proximity as security.
Examples
Why "short range = secure" is false (two illustrative attacks):
CLONING a static-ID badge (no crypto):
attacker reads a 125 kHz prox card / MIFARE Classic with a cheap Proxmark
-> writes an identical clone -> the clone opens the door. Trivial.
RELAY attack on keyless car entry (defeats proximity entirely):
[key fob in house] <--relay device A ~~~ relay device B--> [car in driveway]
the car and key exchange VALID messages via the relay -> car unlocks & starts,
even though the key is 30m away. Crypto is fine; proximity assumption is broken.
Defenses map to each risk:
eavesdropping / skimming -> encryption + RFID-blocking sleeve (shielding)
cloning / replay -> CRYPTOGRAPHIC challenge-response (not static IDs)
(EMV contactless, secure badges resist cloning)
relay attack -> DISTANCE BOUNDING (measure round-trip time);
motion-sensing fobs; Faraday pouch for the key
Principle: never treat short range as a security control.
Key Takeaways
- RFID (tag-and-reader identification) and NFC (its short-range subset for phones/payments) are behind badges, contactless payments, passports, and key fobs; their danger is the false assumption that short range provides security.
- Risks: eavesdropping (range is longer than nominal), skimming (unauthorized reading through a wallet), cloning (duplicating a tag), relay attacks, and replay/modification.
- Cheap, common systems — 125 kHz proximity badges and MIFARE Classic — use weak or no authentication and are trivially cloned with inexpensive hardware, a serious physical-access-control weakness.
- Relay attacks (notably keyless car entry) defeat the proximity assumption by relaying cryptographically valid messages over distance in real time.
- Defend with cryptographic challenge-response (defeats cloning/replay — as in EMV contactless), encryption and shielding (eavesdropping/skimming), and distance bounding or Faraday pouches for relay attacks; never treat short range as a security control.
🧪 Practice
- Explain why a 125 kHz proximity badge is trivially cloned while an EMV contactless card is not.
- Describe a keyless-car relay attack and why cryptographic authentication alone does not prevent it.
- List the defenses for skimming, cloning, and relay attacks respectively.
- Interview-style: "Why does the short range of NFC not make it secure, and what must provide the security instead?" Hint: consider range extension, relay attacks, and whether proximity authenticates anything.
Wireless Site Survey and Rogue Detection
Theory
The final topic brings the wireless chapter back to operations: how do you actually know what wireless is present in your environment, whether it is secure, and whether something malicious is operating? A wireless site survey is the systematic process of mapping and analyzing a wireless environment, and rogue detection is the ongoing practice of identifying unauthorized or malicious wireless devices. Together they are how an organization maintains visibility and control over a medium that, by its nature, extends beyond its walls and is invisible without the right tools — you cannot secure wireless you cannot see.
A site survey serves both performance and security goals. For security, it establishes a baseline of what should be present (your authorized APs, their channels, signal coverage, and where it bleeds outside the building — because signal leaking into the parking lot is attackable from there) and reveals what should not be present. Surveys are typically done by walking the premises with specialized software and adapters, producing a heat map of coverage and an inventory of detected networks. The security questions a survey answers: Is signal over-propagating beyond the intended area? Are all APs using strong security (WPA2/WPA3-Enterprise, not open or WEP)? Are there unexpected networks? This connects directly to the rogue-AP and evil-twin attacks from the Network Attacks section — a survey is how you detect them.
Rogue detection is the continuous counterpart, usually automated by a Wireless Intrusion Detection/Prevention System (WIDS/WIPS) — sensors that monitor the RF spectrum and compare observed devices against a policy of what is authorized. The key distinction is between a rogue AP (an unauthorized AP connected to your network — the dangerous backdoor from before, which a WIPS can correlate by seeing the same device on both the wired and wireless sides) and an evil twin / neighbor AP (an AP impersonating your SSID, or simply a neighbor's unrelated network — not on your network but potentially a threat or just noise). Good rogue detection classifies detected APs into authorized, rogue (on your network — highest priority), external/neighbor (not your concern), and interfering/evil-twin (impersonating you). A WIPS can go further and actively contain a rogue (sending deauthentication frames to prevent clients connecting to it), though this is powerful and must be used carefully (deauthing a legitimate neighbor is disruptive and potentially unlawful). The operational practices that complete the picture: regular surveys and continuous WIDS/WIPS monitoring, maintaining an inventory of authorized wireless, detecting APs broadcasting your SSID from unexpected locations (evil twins), watching for deauthentication floods (a sign of an active attack or of KRACK/evil-twin setup), and using spectrum analysis to find both rogue devices and interference. The unifying theme closes the chapter: wireless security requires active, ongoing visibility, because the medium is invisible, extends beyond physical boundaries, and is trivial for an attacker to introduce new devices into — so you must continuously look.
Examples
Classifying what a survey / WIDS detects (priority by whether it's on YOUR network):
AUTHORIZED : your known APs, correct channels/security -> baseline
ROGUE : UNAUTHORIZED AP connected to YOUR network -> HIGHEST priority
(the backdoor; WIPS correlates wired+wireless to confirm)
EVIL TWIN : AP broadcasting YOUR SSID from the wrong place -> active threat
EXTERNAL/NEIGHBOR: not on your network, not impersonating you -> noise, ignore
A rogue on your network is far more urgent than a neighbor's AP.
# Surveying and detecting rogue wireless (defensive reconnaissance of your own RF):
iw dev wlan0 scan | grep -E "SSID|signal|WPA|WEP" # enumerate nearby networks + security
# flag any: open/WEP networks, your SSID from an unexpected BSSID (evil twin),
# APs not in your authorized inventory.
airodump-ng wlan0mon # continuous survey: BSSIDs, channels, clients
# WIDS/WIPS (concept): sensors compare observed APs to an authorized policy;
# a WIPS can CONTAIN a rogue via deauth frames -- powerful, use with care
# (deauthing a neighbor's legitimate AP is disruptive and may be unlawful).
# Watch for deauthentication floods -> sign of an active attack or evil-twin setup.
Key Takeaways
- You cannot secure wireless you cannot see; site surveys (map and analyze the environment) and rogue detection (find unauthorized/malicious devices) provide the necessary ongoing visibility.
- A security site survey baselines authorized APs, channels, and coverage — including signal over-propagation beyond the building — and reveals unexpected or insecure networks (open/WEP), producing a coverage heat map and network inventory.
- Rogue detection (automated by WIDS/WIPS) classifies detected APs as authorized, rogue (unauthorized and on your network — highest priority, confirmable by wired+wireless correlation), evil-twin (impersonating your SSID), or external/neighbor (noise).
- A WIPS can actively contain rogues via deauthentication frames, but this must be used carefully to avoid disrupting legitimate neighbors (and potential legal issues).
- Ongoing practice — surveys, continuous monitoring, authorized-device inventory, and watching for evil twins and deauth floods — is essential because wireless is invisible, extends beyond physical boundaries, and is trivial for attackers to add devices to.
🧪 Practice
- Explain why signal over-propagation beyond a building is a security concern a site survey should catch.
- Distinguish a rogue AP, an evil twin, and a neighbor AP, and justify the priority order for response.
- Explain what a WIPS containment action does and why it must be used cautiously.
- Interview-style: "Your WIDS flags an AP broadcasting your corporate SSID but it is not on your wired network. Is this a rogue or an evil twin, and how do you tell?" Hint: the deciding question is whether the device is connected to your own network — and how a WIPS correlates wired and wireless sightings to answer it.
<a id="7-system-and-endpoint-hardening"></a>