Introduction

Systems which have IP forwarding or routing enabled (so called routers or gateways) will forward IP packets to other networks where the system is connected to. In pentests, it can be useful to search for such systems, because these systems could be used to access otherwise inaccessible networks and systems.

I wrote a small script that automates this task.

Script

The script can be found on GitHub: ip-forwarding-scanner. The usage is quite simple:

$ ip-forwarding-scanner -h
Usage: ip-forwarding-scanner [OPTIONS...]

Program:
  Test systems for IP forwarding.

Options:
  -i    LAN interface        (default: eth0)
  -d    Destinations         (default: 1.1.1.1,8.8.8.8)
  -p    TCP Ports            (default: 80,443,445)
  -t    Target IP addresses  (default: local network if LAN interface)

Author: Emanuel Duss (https://emanuelduss.ch)

Example Usage

The following command checks if there are hosts in the local network that have IP forwarding enabled. To be precise, the script tries to access the systems 1.1.1.1 and 8.8.8.8 via ICMP echo requests and on port 80, 443 and 445 and checks if a response was received.

$ sudo ip-forwarding-scanner  -i wlan0
[*] ip6-forwarding-scanner

[+] LAN interface:  wlan0
[+] Destinations:   1.1.1.1 8.8.8.8
[+] TCP ports:      80 443 445
[+] Targets :       192.168.23.23/24

[+] Scanning for hosts in the local network...
[*] Testging 192.168.23.1 (50:E6:32:60:75:01) for IP forwarding...
[+] Trying to access 1.1.1.1 via ICMP...
RCVD (0.0438s) ICMP [1.1.1.1 > 192.168.23.23 Echo reply (type=0/code=0) id=39618 seq=1] IP [ttl=54 id=24392 iplen=28 ]
[*] Success!
[+] Trying to access 1.1.1.1 via TCP on port 80...
RCVD (0.0642s) TCP 1.1.1.1:80 > 192.168.23.23:54921 SA ttl=54 id=0 iplen=44  seq=3046691453 win=65535 <mss 1460>
[*] Success!
[+] Trying to access 1.1.1.1 via TCP on port 443...
RCVD (0.0307s) TCP 1.1.1.1:443 > 192.168.23.23:33046 SA ttl=54 id=0 iplen=44  seq=2151489818 win=65535 <mss 1460>
[*] Success!
[+] Trying to access 1.1.1.1 via TCP on port 445...
[+] Trying to access 8.8.8.8 via ICMP...
RCVD (0.0544s) ICMP [8.8.8.8 > 192.168.23.23 Echo reply (type=0/code=0) id=53416 seq=1] IP [ttl=114 id=0 iplen=28 ]
[*] Success!
[+] Trying to access 8.8.8.8 via TCP on port 80...
[+] Trying to access 8.8.8.8 via TCP on port 443...
RCVD (0.0529s) TCP 8.8.8.8:443 > 192.168.23.23:18093 SA ttl=117 id=0 iplen=44  seq=907004173 win=65535 <mss 1412>
RCVD (0.4127s) TCP 8.8.8.8:443 > 192.168.23.23:18093 SA ttl=119 id=0 iplen=44  seq=907004173 win=65535 <mss 1412>
[*] Success!
[+] Trying to access 8.8.8.8 via TCP on port 445...

[*] Testging 192.168.23.5 (B4:E6:2D:71:CA:BD) for IP forwarding...
[+] Trying to access 1.1.1.1 via ICMP...
[+] Trying to access 1.1.1.1 via TCP on port 80...
[+] Trying to access 1.1.1.1 via TCP on port 443...
[+] Trying to access 1.1.1.1 via TCP on port 445...
[+] Trying to access 8.8.8.8 via ICMP...
[+] Trying to access 8.8.8.8 via TCP on port 80...
[+] Trying to access 8.8.8.8 via TCP on port 443...
[+] Trying to access 8.8.8.8 via TCP on port 445...

[*] Testging 192.168.23.50 (00:01:2E:23:42:E5) for IP forwarding...
[+] Trying to access 1.1.1.1 via ICMP...
RCVD (0.0509s) ICMP [1.1.1.1 > 192.168.23.23 Echo reply (type=0/code=0) id=56201 seq=1] IP [ttl=54 id=48035 iplen=28 ]
[*] Success!
[+] Trying to access 1.1.1.1 via TCP on port 80...
RCVD (0.0402s) TCP 1.1.1.1:80 > 192.168.23.23:34482 SA ttl=54 id=0 iplen=44  seq=2532601867 win=65535 <mss 1460>
[*] Success!
[+] Trying to access 1.1.1.1 via TCP on port 443...
RCVD (0.0288s) TCP 1.1.1.1:443 > 192.168.23.23:35762 SA ttl=54 id=0 iplen=44  seq=2786765437 win=65535 <mss 1460>
[*] Success!
[+] Trying to access 1.1.1.1 via TCP on port 445...
[+] Trying to access 8.8.8.8 via ICMP...
RCVD (0.0427s) ICMP [8.8.8.8 > 192.168.23.23 Echo reply (type=0/code=0) id=10152 seq=1] IP [ttl=114 id=0 iplen=28 ]
[*] Success!
[+] Trying to access 8.8.8.8 via TCP on port 80...
[+] Trying to access 8.8.8.8 via TCP on port 443...
RCVD (0.0539s) TCP 8.8.8.8:443 > 192.168.23.23:28357 SA ttl=119 id=0 iplen=44  seq=3604581008 win=65535 <mss 1412>
RCVD (0.3849s) TCP 8.8.8.8:443 > 192.168.23.23:28357 SA ttl=119 id=0 iplen=44  seq=3604581008 win=65535 <mss 1412>
[*] Success!
[+] Trying to access 8.8.8.8 via TCP on port 445...

[...]

This shows that both systems 192.168.23.1 and 192.168.23.50 forward IP packets to the mentioned hosts. The host 192.168.23.1 is expected, because this is also the default gateway with Internet access. The other host is not expected and has to be further investigated.

The next step would be to configure the host 192.168.23.50 as a default gateway and see which networks can be accessed through this host:

ip route replace default via 192.168.23.50 dev eth1

Special Cases

Redundant Routers

If you find a host with IP forwarding enabled, this does not automatically mean, that you can bypass firewalls and access otherwise inaccessible systems. This always has to be analyzed further.

A special case is when a router redundancy protocol like VRRP or HSRP is used. You will then see multiple hosts with IP forwarding enabled. These are active systems in the network which will take over when one system fails and typically can access the same networks.

Restricted Networks

Another special case is if the IP forwarding system has no direct Internet connection. This is the case when a firewall blocks all outgoing Internet traffic or only a proxy can be used to access the Internet. You will then never be able to get a response from one of the default targets like 1.1.1.1 or 8.8.8.8.

For this, you can specify the target system and port you know that exists. This example tests if the host 10.5.23.42 can be accessed on port 8080:

$ sudo ip-forwarding-scanner -i wlan0 -d 10.5.23.42 -p 8080 -t 192.168.23.1,192.168.23.5
[*] ip6-forwarding-scanner

[+] LAN interface:  wlan0
[+] Destinations:   10.5.23.42
[+] TCP ports:      8080
[+] Targets :       192.168.23.1,192.168.23.5

[+] Scanning for hosts in the local network...

[*] Testging 192.168.23.1 (50:E6:32:60:75:01) for IP forwarding...
[+] Trying to access 10.5.23.42 via ICMP...
[+] Trying to access 10.5.23.42 via TCP on port 8080...

[*] Testging 192.168.23.5 (B4:E6:2D:71:CA:BD) for IP forwarding...
[+] Trying to access 10.5.23.42 via ICMP...
[+] Trying to access 10.5.23.42 via TCP on port 8080...
RCVD (0.3109s) TCP 10.5.23.42:8080 > 192.168.23.23:30165 SA ttl=46 id=0 iplen=44  seq=1563929884 win=64240 <mss 1460>
[*] Success!

The output shows that the host 10.5.23.42 can be accessed on port 8080 via the IP forwarding host 192.168.23.5 but not via 192.168.23.1. The next step would then be to see which other services on this host and which other hosts can be accessed via 192.168.23.5.

Behind the Scene

The script just uses nmap to search for online hosts in the network and get the MAC address from those and then uses nping (from the nmap project) to craft the necessary packets which will test for IP forwarding.

The following nping command will send an IP packet to the IP address 10.5.23.42 transporting a TCP SYN packet with the destination port 8080 to the MAC address 50:e6:36:25:04:ef. The system will then forward the IP packet (or perform NAT, which is transparent to the sending system) and finally send back the replied TCP SYN-ACK packet.

$ sudo nping -e wlan0 -c 1 --dest-mac B4:E6:2D:71:CA:BD --tcp -p 8080 10.5.23.42

SENT (0.0285s) TCP 192.168.23.23:14717 > 10.5.23.42:8080 S ttl=64 id=3980 iplen=40  seq=1108867356 win=1480 
RCVD (0.3134s) TCP 10.5.23.42:8080 > 192.168.23.23:14717 SA ttl=47 id=0 iplen=44  seq=4203475426 win=64240 <mss 1460>
 
Max rtt: 285.003ms | Min rtt: 285.003ms | Avg rtt: 285.003ms
Raw packets sent: 1 (54B) | Rcvd: 1 (44B) | Lost: 0 (0.00%)
Nping done: 1 IP address pinged in 1.08 seconds

On the network level, it’s possible to exactly see these details:

$ tshark -T fields -e eth.dst -e ip.dst -e tcp.flags.str -e tcp.dstport port 8080
B4:E6:2D:71:CA:BD       10.5.23.42      ··········S·    8080
78:af:08:28:af:19       192.168.23.23   ·······A··S·    14906

That’s the entire magic 😀.

Alternatives

There are several alternatives which can also be used to find IP forwarding systems:

However, I wanted to implement this on my own to fully understand what is going on on the cable. In my opinion, my script is a bit easier to use and to configure (e.g. you can provide IP addresses instead of MAC addresses to the script and by default it does automatically scan the local network for active hosts via an ARP host discovery scan).

References