An IP whitelist is one of the many measures applied to protect services, hosts and networks from attackers. It only allows those that are on the IP whitelist to access the protected resources and all others are denied by default. As attackers we have multiple obstacles to overcome if we want to bypass this and not always will it be possible. In my personal opinion there are two situation in which you will end up as an attacker:
- You are NOT on the same network as your target
- You are on the same network as your target
In the first situation you will (generally speaking) not be able to access or influence the network traffic of your target. This in turn enables the TCP/IP mechanisms to be useful and prevent you from accessing the resources, although maybe not prevent you from discovering who is on the whitelist.
In the second situation you will (generally speaking) be able to access or influence the network traffic of your target. This enables us as attacker to identify as well as bypass IP restrictions, by manipulating the TCP/IP protection mechanisms, to gain access to the protected resources.
For both situations there is an often overlooked detail which is: how do you know which IPs are on the whitelist? Mostly it is just assumed that either you know that upfront or discover that due to a connection being active while you initiate your attack. In this blog posts we’ll discuss the two situations and describe the techniques available to identify IPs on whitelist which have no active connection. A small helper script can be found here.
Background
Let’s refresh our knowledge on why an IP whitelist works pretty well nowadays. If you are not familiar with TCP/IP I’d recommend that you read up on it here or here or here.
The corner stone of an IP whitelist is thus the fact that as an attacker you cannot predict the sequence number. This has not always been the case, since in the early internet and operating system days there have been cases of predictable sequence numbers. A simple google query like “tcp/ip predictable isn” will yield a large variety of examples that used to affect multiple operating systems:
When as an attacker you cannot predict the sequence number the only other option available is to spy on the sequence number when it is being transmitted. This however this requires access to the same network in one way or another. The following are all valid methods of access to spy on sequence numbers: physical presence, infected workstation, satcom sniffing, WiFi access and cable interception.
In the previous paragraphs we have been talking about IP whitelists on the TCP/IP level, this however is not the only place where an IP whitelist can be enabled. Applications like mysql, apache, ssh etc can have their own whitelists. These whitelists profit from the fact that the TCP handshake has already taken place and afterwards they compare the source IP to the list of allowed IPs.
Whitelist identification with zombie/idle-scans
One of the well known techniques to identify which IPs are on the whitelist is the so called ‘zombie’ or ‘idle’ type of scan. You probably recognise it from the multiple tutorials that explain how to use this to hide your ip while scanning a target. The underlying technique however is in essence a way to identify which IP addresses belong to a whitelist, as mentioned in the nmap docs. This is also a technique that applies mostly to the situation when you are not on the same network as your target.
Unfortunately it seems that this technique is becoming less useful due to all kind of changes in the way that the IP identification numbers are generated. I’m not sure if the same applies to IPv6 on which it is also possible to perform idle scans.
If you encounter a situation in which you can reliably identify IP addresses on a whitelist based on the idle scan method, you might be able to do some truly amazing stuff as explained in this presentation (remote blind TCP/IP spoofing).
Whitelist identification with man-in-the-middle (mitm) attacks
Multiple tools out there use mitm techniques to spoof and hijack TCP connections. For now however we will be focussing on identifying which IPs are on the whitelist without a requirement for the whitelisted IPs to have an active connection with the target. You can use this technique when you are on the same network as your target to identify local subnet IPs as well as IPs outside of the subnet that are on the whitelist of your target. Since we control the environment, sort of speak, we can also identify application specific whitelisted IPs. Let’s look at our lab setup:
What you see in the above image is the following:
- One server which allows two IP addresses
- One from within the network
- One from outside the network
- One mitm attack focusing on the traffic between the server and the gateway
- One mitm attack focusing on the traffic between the server and the allowed IP
As a reminder, when the allowed IPs have an active connection with the server the mitm attack is enough to identify those IPs or hijack the connection directly. What we are after are all the IPs that are allowed but don’t have an active connection. Like we all know, the house keeping on whitelists can be a delayed job ;)
Let’s first have a look at identifying IP addresses that are whitelisted, but originate from outside the local network. We will first initiate a mitm attack that hijacks the traffic between the server and the gateway using my favourite tool ‘arpspoof’ written by Dug Song (yes the now CEO of Duo Security).
arpspoof -i eth0 -t 172.16.218.186 -r 172.16.218.2
The above will arp poison the server (-t) (.186) and the gateway (.2) in both direction (-r) forcing the traffic towards our attacker machine. I’ll leave it as an exercise to you to figure out the extra steps to prevent a DOS on the target server ;) So we got the traffic, now what? Well the idea is really simple: spoof IP addresses that you think might be whitelisted and watch for the response, as visualised in the following image:
For the potentially allowed IP addresses we need to spoof their IP address and listen for replies which is pretty doable with python and scapy. Here is the help output from the tool I wrote:
usage: whitelist_finder.py [-h] -i IFACE -p PORTS [PORTS ...] -s SRCIPS targetip scan target with spoofed IP to identify whitelist positional arguments: targetip target ip to perform port scan on optional arguments: -h, --help show this help message and exit -i IFACE, --iface IFACE network interface to use -p PORTS [PORTS ...], --ports PORTS [PORTS ...] space separated list of ports -s SRCIPS, --srcips SRCIPS file with IPs to spoof
Now when we run this script while the arp poisoning is going on, the output might look like this:
arpspoof -i eth0 -t 172.16.218.188 -r 172.16.218.2 ./whitelist_finder.py -i eth0 -p 22 -s spoofip.txt 172.16.218.188 2018-02-18 09:33:57,661 - INFO - 8.8.8.8 possibly allowed in whitelist SYN/ACK
If you are wondering why it says ‘possibly allowed’ that’s because this is still only at the TCP/IP level. The application itself might still apply additional whitelists criteria. We can also check that, but we need to implement some extra code, for starters we need to ‘ACK’ the ‘SYN/ACK’. After that it really depends on the application on what else you need to implement. If we take MySQL as an example it looks like this:
def check_mysql(self, ip, data): banner = 'is not allowed to connect' if banner not in str(data): logging.info('{0} confirmed allowed in whitelist'.format(ip)) ./whitelist_finder.py -i eth0 -p 3306 -s spoofip.txt 172.16.218.188 2018-02-18 10:10:56,045 - INFO - 123.123.123.123 possibly allowed in whitelist SYN/ACK 2018-02-18 10:10:56,169 - INFO - 8.8.8.8 possibly allowed in whitelist SYN/ACK 2018-02-18 10:10:56,290 - INFO - 192.168.2.7 possibly allowed in whitelist SYN/ACK 2018-02-18 10:11:06,233 - INFO - 8.8.8.8 confirmed allowed in whitelist
With MySQL we are lucky since immediately after completing the TCP/IP handshake it will let us know if the IP is allowed or not. Thus the ability to easily confirm if the IP address is really on the whitelist.
For identification of whitelisted IPs within the same subnet the same concept applies, except you need to modify your arp poisoning attack accordingly. We also have a small challenge, since not all of the IPs that we want to try will be online. We can discover which IPs are alive and which are not in our network by using the following oneliner (beware of the line break):
for i in $(seq 0 255);do arping -I eth0 -c 1 "172.16.218."$i | \ grep -i 'unicast reply';done
That narrows down the list of local IPs to spoof, but what to do with the non-existant IPs? Let’s add them to our interface and just use nmap to scan using those unused IPs as our source address:
ip address add 172.16.218.9/24 dev eth0 nmap -n -Pn -p 53 -S 172.16.218.9 8.8.8.8
The above commands will first add an IP address which is not in use to our interface and then using the nmap IP spoof option, scan from that IP address. If you limit the amount of target ports this could help you to quickly identify potential privileged IPs on a network level. Automating the above for all unused IPs is of course an exercise for the reader :p