Denial of service
DHCP starvation
Claiming every address in a DHCP pool under forged MAC addresses so no real device can get one.
A DHCP server leases by MAC address and cannot tell a forged one from a real one. An attacker requests a lease again and again, each under a new made-up MAC, until the pool is empty; from then on any device that relies on DHCP joins and gets nothing — a quiet denial of service. Hosts with static addresses are untouched. The lease table fills with unfamiliar MACs in seconds, the tell-tale sign. The real cure is on the switch: port security caps the MACs one port may present and rate-limits DHCP from it, so one port cannot impersonate a hundred clients.
How a DHCP starvation attack works, step by step
A DHCP server (RFC 2131) owns a finite pool of addresses and leases one to each MAC address that asks.
It cannot tell a forged MAC from a real one. Starvation drains the pool by asking for lease after lease, each under a
fresh made-up MAC, until nothing is left. In the DHCP starvation lab the server leases from
10.0.1.0/27, a pool of nine addresses (10.0.1.22–10.0.1.30); the attacker and the laptops share the LAN.
- The attacker forges a MAC. It sets its card to
02:00:00:00:ab:01and runs the DORA exchange (Discover, Offer, Request, ACK) to claim one lease. - It repeats under new MACs.
02:00:00:00:ab:02,...:03, and on, each a new identity the server treats as a new device. Every round takes one address out of the pool. - The pool empties. After enough rounds all nine addresses are leased to MACs that do not exist. The server has nothing left to offer.
- Real clients are locked out. A genuine laptop sends a Discover, gets no Offer, retries and gives up with no address. With no address it reaches nothing: a quiet denial of service.
- Static hosts ride it out. A printer whose address is set by hand never asked for a lease, so the drained pool never touches it, and devices that already hold a lease keep working until it expires.
Starvation is often step one of a bigger attack: drain the real server, then answer as a rogue DHCP server so only the attacker's offers remain.
What it looks like on a Linux machine
The attacker loops, changing its MAC each round and asking for a lease with udhcpc:
$ for i in $(seq 1 16); do
M=$(printf '02:00:00:00:ab:%02x' $i)
ip link set eth0 down; ip link set eth0 address $M; ip link set eth0 up
udhcpc -i eth0 -n -q -t 2 -T 1
done
On the server the lease table fills with the forged MACs. It is dnsmasq, so the leases live in a file:
$ awk '{print $2, $3}' /var/lib/netlab/dhcp.leases | head -4
02:00:00:00:ab:01 10.0.1.22
02:00:00:00:ab:02 10.0.1.23
02:00:00:00:ab:03 10.0.1.24
02:00:00:00:ab:04 10.0.1.25
A genuine laptop now gets nothing. BusyBox udhcpc prints the failure and the card stays empty:
$ udhcpc -i eth0 -n -q -t 4 -T 2
udhcpc: no lease, failing
$ ip -4 -o addr show eth0 | awk '{print $4}'
The static printer, whose address never came from DHCP, still answers:
$ curl -s http://10.0.1.14/
printer ready
What goes wrong, and how you see it
New devices cannot join, old ones are fine. The signature failure: machines that already hold a lease keep
working, while anything new gets no lease, failing and an empty card. The pool is exhausted, not the wire.
A burst of unfamiliar MACs in the lease table. Dozens of leases to addresses like 02:00:00:00:ab:xx, all
appearing within seconds and all learned from one switch port, is the tell. grep -c '^02:00:00:00:ab' over the
leases counts them.
A link-local 169.254 address appears. A host that gives up on DHCP may self-assign from 169.254.0.0/16
(RFC 3927). That address reaches nothing beyond the wire and marks a DHCP failure.
The switch stops it at the port. Port security caps how many MAC addresses one access port may present and err-disables a port that breaks the limit, so one port cannot pose as a hundred clients; DHCP snooping also rate-limits DHCP per port. The layer 2 security lab shows a port shut for exactly this.
Questions people ask
DHCP starvation vs a rogue DHCP server? Starvation is denial of service: it empties the pool so nobody gets an address. A rogue server hands out poisoned addresses. They combine: starve the real server, then answer in its place.
How many addresses can an attacker take? As many as the pool holds; a /24 has about 254, a /27 only 30.
Smaller pools empty in seconds, which is why the lab uses a /27.
Does giving everything a static address fix it? It protects those hosts, as the lab's printer shows, but it does not scale to a whole network. The real fix is on the switch. See DHCP and MAC flooding, its layer 2 cousin.