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