Introduction
In my last blog post (Scanning for IP-Forwarding Systems / Routers), I explained why it can be useful during pentests to identify IP-forwarding systems (also known as routers or gateways) and showcased a script that can be used to identify such systems.
In this post, I’ll show how this can be done in IPv6 networks when your host has a routable IPv6 address configured.
Script
The script can be found on GitHub: ip6-forwarding-scanner. The usage is quite simple:
$ ip6-forwarding-scanner -h
Usage: ip6-forwarding-scanner [OPTIONS...]
Program:
Test systems for IPv6 forwarding.
Options:
-i LAN interface (default: eth0)
-d Destinations (default: 2620:fe::9,2001:4860:4860::8888)
-p TCP Ports (default: 53,443)
-t Target IP addresses (default: Hosts responding to all nodes multicast address (ff02::1))
Author: Emanuel Duss (https://emanuelduss.ch)
Example Usage
The following command checks if there are hosts in the local network that have
IP forwarding for IPv6 packets enabled. To be precise, the script tries to
access the systems 2620:fe::9
(Quad9 nameservers) and
2001:4860:4860::8888
(Google nameservers) on port 53
and 443
TCP via other systems in the network and checks if a response was
received.
$ sudo ip6-forwarding-scanner -i wlan0
[*] ip6-forwarding-scanner
[+] LAN interface: wlan0
[+] Source MAC Address: 78:af:42:55:52:50
[+] Source IP Address: 2001:db8:5:23:65e3:e3c5:9d1b:6953 2001:db8:5:23:7aaf:42ff:fe55:5250
[+] Destinations: 2620:fe::9 2001:4860:4860::8888
[+] TCP ports: 53 443
[+] Targets: Hosts responding to all nodes multicast address (ff02::1)
[+] Scaning targets...
[*] Testging 00:01:62:65:65:66 (fe80::201:63ff:fe65:6566) for IP forwarding...
[+] Trying to access 2620:fe::9 via TCP on port 53 from 2001:db8:5:23:65e3:e3c5:9d1b:6953...
[+] Trying to access 2620:fe::9 via TCP on port 443 from 2001:db8:5:23:65e3:e3c5:9d1b:6953...
[+] Trying to access 2620:fe::9 via TCP on port 53 from 2001:db8:5:23:7aaf:42ff:fe55:5250...
[+] Trying to access 2620:fe::9 via TCP on port 443 from 2001:db8:5:23:7aaf:42ff:fe55:5250...
[+] Trying to access 2001:4860:4860::8888 via TCP on port 53 from 2001:db8:5:23:65e3:e3c5:9d1b:6953...
[+] Trying to access 2001:4860:4860::8888 via TCP on port 443 from 2001:db8:5:23:65e3:e3c5:9d1b:6953...
[+] Trying to access 2001:4860:4860::8888 via TCP on port 53 from 2001:db8:5:23:7aaf:42ff:fe55:5250...
[+] Trying to access 2001:4860:4860::8888 via TCP on port 443 from 2001:db8:5:23:7aaf:42ff:fe55:5250...
[*] Testging 50:e6:36:6e:6f:74 (fe80::52e6:36ff:fe6e:6f74) for IP forwarding...
[+] Trying to access 2620:fe::9 via TCP on port 53 from 2001:db8:5:23:65e3:e3c5:9d1b:6953...
RCVD (0.0469s) TCP 2620:fe::9:53 > 2001:db8:5:23:65e3:e3c5:9d1b:6953:32161 SA hopl=51 flow=0 payloadlen=24 seq=1954000791 win=28800 <mss 1440>
[*] Success!
[+] Trying to access 2620:fe::9 via TCP on port 443 from 2001:db8:5:23:65e3:e3c5:9d1b:6953...
RCVD (0.0308s) TCP 2620:fe::9:443 > 2001:db8:5:23:65e3:e3c5:9d1b:6953:53062 SA hopl=55 flow=0 payloadlen=24 seq=340542536 win=28800 <mss 1440>
[*] Success!
[+] Trying to access 2620:fe::9 via TCP on port 53 from 2001:db8:5:23:7aaf:42ff:fe55:5250...
RCVD (0.0463s) TCP 2620:fe::9:53 > 2001:db8:5:23:7aaf:42ff:fe55:5250:5471 SA hopl=51 flow=0 payloadlen=24 seq=1976983770 win=28800 <mss 1440>
[*] Success!
[+] Trying to access 2620:fe::9 via TCP on port 443 from 2001:db8:5:23:7aaf:42ff:fe55:5250...
RCVD (0.0488s) TCP 2620:fe::9:443 > 2001:db8:5:23:7aaf:42ff:fe55:5250:40472 SA hopl=51 flow=0 payloadlen=24 seq=3869630996 win=28800 <mss 1440>
[*] Success!
[+] Trying to access 2001:4860:4860::8888 via TCP on port 53 from 2001:db8:5:23:65e3:e3c5:9d1b:6953...
RCVD (0.0313s) TCP 2001:4860:4860::8888:53 > 2001:db8:5:23:65e3:e3c5:9d1b:6953:5507 SA hopl=117 flow=24cfa payloadlen=24 seq=1435871950 win=65535 <mss 1440>
[*] Success!
[+] Trying to access 2001:4860:4860::8888 via TCP on port 443 from 2001:db8:5:23:65e3:e3c5:9d1b:6953...
RCVD (0.0512s) TCP 2001:4860:4860::8888:443 > 2001:db8:5:23:65e3:e3c5:9d1b:6953:29246 SA hopl=117 flow=94217 payloadlen=24 seq=2483725079 win=65535 <mss 1440>
[*] Success!
[+] Trying to access 2001:4860:4860::8888 via TCP on port 53 from 2001:db8:5:23:7aaf:42ff:fe55:5250...
RCVD (0.0576s) TCP 2001:4860:4860::8888:53 > 2001:db8:5:23:7aaf:42ff:fe55:5250:56462 SA hopl=119 flow=2a3c1 payloadlen=24 seq=3595232015 win=65535 <mss 1440>
[*] Success!
[+] Trying to access 2001:4860:4860::8888 via TCP on port 443 from 2001:db8:5:23:7aaf:42ff:fe55:5250...
RCVD (0.0285s) TCP 2001:4860:4860::8888:443 > 2001:db8:5:23:7aaf:42ff:fe55:5250:45537 SA hopl=119 flow=1a3fe payloadlen=24 seq=3511735293 win=65535 <mss 1440>
[*] Success!
[...]
This shows that the system with the MAC address 50:e6:36:6e:6f:74
forwards
IPv6 packets to the target hosts. If this is not an expected host for IP
forwarding, this should be further analyzed to verify if this system can be used
to access otherwise inaccessible systems.
The next step would be to configure the host fe80::52e6:36ff:fe6e:6f74
as a
default gateway for IPv6 and then perform some host- and service discovery to check
which networks can be accessed through this host:
ip -6 route replace default via fe80::52e6:36ff:fe6e:6f74 dev wlan0
Special Cases
There are special cases that should be kept in mind:
- False positives from redundant routers (when there is an active failover system)
- False negatives in restricted networks (when the default targets from the script are not accessible in a restricted network)
This is basically the same as already discussed in the blogpost about IPv4 forwarding systems / routers.
Behind the Scene
The script works as follows. If no targets are provided, the tool uses nmap
and the NSE script targets-ipv6-multicast-echo
to send an ICMPv6 echo request
to the “all nodes” multicast address IP address ff02::2
/ MAC address
33:33:00:00:00:01
on the specified interface. All hosts in the same network
should then send an ICMPv6 echo replay back. These responding hosts are used as
targets to scan. This process could also be done by using the ping
system
utility and parse the neighbor cache table, but nmap
seemed a bit easier for
me, because only one command is needed for this.
If custom targets are provided via the -t
option, nmap
is used to ping the
specified systems via Neighbor Discovery requests to get the corresponding MAC
addresses.
Then, like in the script for IPv4, nping
(from the nmap
project) is used to
craft the necessary packets which will test for IP forwarding. It basically
creates TCP SYN packets to the target IP addresses via the previously discovered
MAC addresses. Because a host often has multiple global IPv6 addresses
configured (multiple random temporary ones and one with the EUI-64 encoded MAC
address), the packets are sent from all these source IP addresses, just in case
a possible router treats these differently. No packets are sent from the
link-local address (fe80::/10
), because such packets are not routable.
Sadly, ncat
does not support ICMPv6.
Therefore, only TCP packets are sent and no ICMP packets. This means, the script
can not detect systems that only forward ICMPv6 packets but no TCP packets.
The following nping
command is such an example and will send an IPv6 packet to
the address 2620:fe::9
transporting a TCP SYN packet with the destination port
53
via the MAC address 50:e6:36:6e:6f:74
. The system will then forward the
IPv6 packet (or perform NAT, which is transparent to the sending system) and
finally send back the received TCP SYN-ACK packet.
$ sudo nping -6 -e wlan0 -c 1 --source-mac 78:af:42:55:52:50 --source-ip 2001:db8:5:23:65e3:e3c5:9d1b:6953 --dest-mac 50:e6:36:6e:6f:74 --tcp -p 53 2620:fe::9
SENT (0.0531s) TCP 2001:db8:5:23:65e3:e3c5:9d1b:6953:41193 > 2620:fe::9:53 S hopl=64 flow=5aa63 payloadlen=20 seq=3237991574 win=1480
RCVD (0.0616s) TCP 2620:fe::9:53 > 2001:db8:5:23:65e3:e3c5:9d1b:6953:41193 SA hopl=51 flow=0 payloadlen=24 seq=3307132265 win=28800 <mss 1440>
Max rtt: 8.187ms | Min rtt: 8.187ms | Avg rtt: 8.187ms
Raw packets sent: 1 (74B) | Rcvd: 1 (64B) | Lost: 0 (0.00%)
Nping done: 1 IP address pinged in 1.12 seconds
On the network level, it’s possible to exactly see these details:
$ tshark -T fields -e eth.dst -e ipv6.dst -e tcp.flags.str -e tcp.dstport port 53
Capturing on 'wlan0'
50:e6:36:6e:6f:74 2620:fe::9 ··········S· 53
78:af:42:55:52:50 2001:db8:5:23:65e3:e3c5:9d1b:6953 ·······A··S· 50042
50:e6:36:6e:6f:74 2620:fe::9 ·········R·· 53
In the end, it’s no magic the same technique as when doing it via IPv4.
Alternatives
In contrast to IPv4, I could not find any alternative tools which can be used to scan for IPv6 forwarding systems / routers. It’s also not easy to search for this, because most search results are about host- and service discovery on IPv6 networks / hosts and not about identifying routers.
Alternatively, scapy
could be used to implement a similar tool. There you have
more control about the packets and it would also be possible to send ICMPv6 echo
request packets or send packets with a lower TTL (e.g. of 1) and receive the
ICMPv6 hop limit exceeded in transit (type 3
, code 0
) replies of routers.
But this is an exercise for another time 😃.
However, if you know some tools, please leave a comment.
References
- Script
ip6-forwarding-scanner
: https://github.com/emanuelduss/Scripts/blob/master/ip6-forwarding-scanner - IANA IPv6 Multicast Address Space Registry: https://www.iana.org/assignments/ipv6-multicast-addresses/ipv6-multicast-addresses.xhtml
- RFC 4291, IPv6 Addressing Architecture, Pre-Defined Multicast Addresses: https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
- nmap: https://nmap.org/
- NSE
script targets-ipv6-multicast-echo
: https://nmap.org/nsedoc/scripts/targets-ipv6-multicast-echo.html - nping: https://nmap.org/nping/
- Missing ICMPv6 support for nping: https://www.uni-koeln.de/~pbogusze/posts/ICMPv6_traffic_generators.html
- Scapy Python Packet Manipulation Library: https://scapy.net/