Introduction
It is July 1st, 2018. Many systems and network administrators have a solid understanding of IPv4 networking and its underlying protocols, but little or no experience using IPv6. This is crazy to me, but we live in interesting times. IPv6 has been around for quite some time, but it still hasn’t been fully adopted. See this Wikipedia page for more information about how IPv6 is being utilized in today’s world.
If you are one of these people who manage networks for a living but doesn’t know IPv6 very well, I highly recommend Hurricane Electric’s free IPv6 Sage course. You need an internet-facing host and a domain to do this, but if you work your way through the challenges, they send you a t-shirt.
When performing security audits, this gap in knowledge becomes even more apparent. Organizations may have a robust and mature set of IPv4 firewall rules, ACLs, and monitoring tooling in play, but completely neglect the IPv6 protocol. This blunder can be used to an attacker’s advantage.
This post will cover some of the basics of bypassing IPv4 security measures by way of IPv6. I will not cover the differences between IPv4 and IPv6 because there are already several articles out there that go over this in great detail.
Many of the discovery techniques outlined below only work against hosts on your current network. It is worth checking both IPv4 and IPv6 against hosts if you are able to discover that they are dual stacked. There is nothing groundbreaking, earth-shattering, or novel about these techniques, yet they continue to be an issue on many networks.
Tooling
Many of the commonly available tools for network enumeration work out of the box, will work on IPv6 with special flags, or have separate IPv6 versions of the tool available. Sometimes, a tool may only work on one protocol or the other. When you inevitably run into these scenarios, they can often be overcome with a bit of creativity.
Nmap
To use Nmap against IPv6 endpoints, use the -6 flag:
nmap -6 IPV6_ADDRESSES_HERE
Ping
The ping utility is IPv4 only on Linux. To ping IPv6 addresses on Linux, use the ping6 utility. The -I flag is an uppercase I as in “Interface”:
ping6 -I eth0 IPV6_ADDRESS_HERE
On Windows, use the -6 flag with ping:
ping -6 ipv6.google.com
Wireshark and tcpdump.
Use the “ip6” filter to show IPv6 traffic:
tcpdump -ni eth0 ip6
Over time, sniffing can reveal significant numbers of hosts without sending a single packet. This works well on both protocols.
ARP and NDP
ARP does not exist on IPv6. Instead, the Neighbor Discovery Protocol (NDP) is used. To correlate IPv4 addresses to their IPv6 counterparts, we will need MAC addresses. ARP makes this convenient.
Show ARP tables on Linux and Windows:
arp -a
Show IPv6 neighbors on Linux:
ip -6 neigh show
Show IPv6 neighbors on Windows:
netsh int ipv6 show neigh
Local IPv6 host discovery
IPv4 networks are often broken down into small network segments. For example, your home network is probably using a /24, which contains 254 usable IP addresses. Scanning a few hundred or even thousands of IP addresses is relatively quick and easy. IPv6 networks have much larger usable address space in their subnets.
To put this into perspective, there are 2^32 possible IPv4 addresses. IPv6 has a possible 2^128 addresses:
IPv4: 2^32 = 4,294,967,296
IPv6: 2^128 = 340,282,366,920,938,463,463,374,607,431,768,211,456
It has been said that there are enough IPv6 addresses to assign every grain of sand on the planet with its own unique address, but I do not know enough about geology to validate this statement.
The drastic size difference between IPv4 and IPv6 makes tools such as masscan or nmap impractical to use due to the amount of time it would take to scan this many addresses. Even though IPv6 gets subnetted in a similar fashion to IPv4, a /64 still contains 18,446,744,073,709,551,616 addresses, which is much larger than the entire IPv4 address space.
Luckily, there are ways to discover IPv6 hosts. To discover IPv6-enabled hosts on a local network, you can ping the IPv6 all-nodes link-local multicast group address: ff02::1
ping6 -I eth0 ff02::1
Hosts subscribed to this multicast address will reply to pings:
% ping6 -I eth0 ff02::1
PING ff02::1(ff02::1) from fe80::xxxx:xxxx:xxxx:xxxx eno1: 56 data bytes
64 bytes from fe80::xxxx:xxxx:xxxx:xxxx: icmp_seq=1 ttl=64 time=0.081 ms
64 bytes from fe80::xxxx:xxxx:xxxx:xxxx: icmp_seq=1 ttl=64 time=0.352 ms (DUP!)
64 bytes from fe80::1:1: icmp_seq=1 ttl=64 time=0.376 ms (DUP!)
64 bytes from fe80::xxx:xxxx:xxxx:xxxx: icmp_seq=1 ttl=64 time=0.407 ms (DUP!)
64 bytes from fe80::xxx:xxxx:xxxx:xxxx: icmp_seq=1 ttl=64 time=1.37 ms (DUP!)
64 bytes from fe80::xxxx:xxxx:xxxx:xxxx: icmp_seq=1 ttl=64 time=10.8 ms (DUP!)
64 bytes from fe80::xxxx:xxxx:xxxx:xxx: icmp_seq=1 ttl=64 time=11.2 ms (DUP!)
64 bytes from fe80::xxxx:xxxx:xxxx:xxx: icmp_seq=1 ttl=64 time=14.3 ms (DUP!)
^C
— ff02::1 ping statistics —
1 packets transmitted, 1 received, +7 duplicates, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.081/4.872/14.379/5.717 ms
This network has 7 other hosts besides my machine responding to IPv6.
IPv4 MAC address discovery
Next, you can list your machine’s ARP table using arp -na or use a tool such as arp-scan to get a list of IPv4 addresses and MAC addresses on your local network. Since the MAC addresses will be the same on dual-stacked NICs, this information is required to correlate an endpoint’s IPv4 address with its IPv6 counterpart. Local IPv6 addresses contain their MAC addresses!
% sudo arp-scan -I eno1 192.168.10.0/24
Interface: eno1, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.8.1 with 256 hosts (http://www.nta-monitor.com/tools/arp-scan/)
192.168.10.1 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.2 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.3 xx:xx:xx:xx:xx:xx CORPORATION OF THE PRESIDING BISHOP OF THE CHURCH OF JESUS CHRIST OF LATTER-DAY SAINTS
192.168.10.10 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.50 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.60 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.105 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.111 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.128 xx:xx:xx:xx:xx:xx NATIONAL SECURITY AGENCY.
192.168.10.142 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.147 xx:xx:xx:xx:xx:xx (Unknown)
192.168.10.254 xx:xx:xx:xx:xx:xx (Unknown)
12 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.8.1: 256 hosts scanned in 1.451 seconds (176.43 hosts/sec). 12 responded
IPv6 MAC address discovery
Now that we have a list of MACs and their corresponding IPv4 addresses, it is trivial to calculate their IPv6 equivalents and determine which hosts are dual-stacked. To demonstrate this, I will use the ipv6calc tool, which is available in Ubuntu and Kali package repositories. If installing packages is not an option for you, you can likely find multiple examples on GitHub showing how to calculate these using your favorite scripting languages.
Nmap can also be used, but it ends up transmitting packets over the network:
sudo nmap -6 -sP IPV6_ADDRESS_HERE | grep MAC
I prefer using ipv6calc or a script as it doesn’t transmit any packets:
% ipv6calc \
–out ipv6addr \
–in prefix+mac \
–action prefixmac2ipv6 \
fe80:: MAC_ADDRESS_GOES_HERE
fe80::xxxx:xxxx:xxxx:xxxx
Saving the addresses gleaned from arp-scan into a file named “addrs” and running the following bash script will calculate all of the IPv6 addresses for you:
while read -r line; do
read -r ipv4 mac <<<$(echo $line | awk {‘print $1, $2’});
echo -n “$mac $ipv4 “;
ipv6calc –out ipv6addr –in prefix+mac –action prefixmac2ipv6 fe80:: $mac
done < addrs
Next steps
From here, you can perform port scans to see what doesn’t match up between IPv4 and IPv6 addresses on the same endpoint. The results may surprise you.