Monday, 23 February 2015

Finding rogue DHCP servers with a Raspberry Pi

You can download the dhcp-server-sniffer perl script here.

The main purpose of this script is to find rogue DHCP servers in a subnet and get their IP and MAC address. If you are looking to capture a complete dhcp converation, this is not the tool for you, dhcpdump is a nice tool for that job.

I decided to put the DHCP server sniffer script onto a Raspberry Pi so that we could monitor all traffic on a particular subnet that is used for teaching server administration. Sometimes a rogue DHCP server accidently gets run on this subnet.

Getting the script to run on the Pi was a matter of copying the script onto the Pi and then installing some CPAN libraries

apt-get install libnetpacket-perl libnet-pcap-perl libnet-dhcp-perl

One i was happy that is was running correctly, I left the Pi in a comms cabinet and patched it into the subnet that I wanted to monitor. It is currently sniffing DHCP traffic for the a subnet in that cabinet. I didn't bother attaching a keyboard, mouse or monitor to it so access is over the network via ssh only.

I did encounter a small problem, when I put the Pi into the comms cabinet and plugged it into the network, it grabbed a DHCP address. There's no monitor on the Pi now, so how do I find out the IP address of the pi so that I can ssh to it?!

One way is to use nmap and go through the entire network to see which devices are listening to the ssh port.

So from some other Linux desktop machine you could run the following nmap command:

waltersa@awdeb:~$ nmap -p22 10.108.5.0/24 -oG - | grep open
Host: 10.108.5.2 () Ports: 22/open/tcp//ssh///
Host: 10.108.5.3 () Ports: 22/open/tcp//ssh///
Host: 10.108.5.129 () Ports: 22/open/tcp//ssh///
waltersa@awdeb:~$

Here we can see that three devices answered, and I happen to know that the first two are the routers for the local subnet, so our pi has to be the third one.

A second, more foolproof way is to use a combination of fping and arp. Before putting the Pi into comms cabinet, make a note of it's MAC address, the one on my Pi was b8:27:eb:53:90:e5.

Then from any Linux machine on the local subnet, ping all machines in the subnet with fping. 'apt-get install fping' if you need to.

fping -g 10.108.5.0/24

Pinging every machine in the subnet causes your PC to do arp lookups for each device on the subnet, these are MAC address and IP address pairings. To see this information do an arp -an and look for the MAC address of our Pi.

labadmin@specialistlab:~$ arp -an
? (10.108.5.158) at 00:23:ae:6a:f9:67 [ether] on eth0
? (10.108.5.3) at 00:04:96:41:45:c0 [ether] on eth0
? (10.108.5.196) at 00:18:8b:19:38:61 [ether] on eth0
? (10.108.5.2) at 00:04:96:43:9f:40 [ether] on eth0
? (10.108.5.129) at b8:27:eb:53:90:e5 [ether] on eth0
? (10.108.5.57) at 00:18:8b:19:45:46 [ether] on eth0
? (10.108.5.103) at 00:24:7e:0e:2e:8e [ether] on eth0
? (10.108.5.1) at 00:00:5e:00:01:01 [ether] on eth0
? (10.108.5.132) at 00:23:ae:6a:b2:de [ether] on eth0
? (10.108.5.125) at 00:18:8b:1a:3b:4d [ether] on eth0
labadmin@specialistlab:~$

Here we can see that our Pi, b8:27:eb:53:90:e5, has an IP address of 10.108.5.129.

Now that we have all the information we need to ssh the Pi, I'll talk about the DHCP sniffer script.

This script captures packets in a switched networking environment so it will not capture a complete DHCP conversation. It will only capture those parts that are broadcasts. This is good enough for our purposes as a rogue DHCP server IP address, which is what we want to find, is included in the DHCP payload in these ethernet broadcasts.

Lets talk about the output of the script. Run it with sudo.

pi@raspberrypi ~ $ sudo ./dhcp-server-sniffer.pl 
Timestamp         | Message Type  | DHCP Server IP  | Ether MAC   
20150220 10:43:21 | DHCP Ack      | 10.100.32.12    | 0004964145c0
20150220 10:43:21 | DHCP Ack      | 10.100.32.12    | 000496439f40
20150220 10:53:49 | DHCP Nak      | 10.100.32.12    | 0004964145c0
20150220 10:53:49 | DHCP Nak      | 10.100.32.12    | 000496439f40
20150220 10:53:50 | DHCP Offer    | 10.100.32.12    | 0004964145c0
20150220 10:53:50 | DHCP Request  | 10.100.32.12   
20150220 10:53:50 | DHCP Ack      | 10.100.32.12    | 0004964145c0
20150220 10:53:50 | DHCP Ack      | 10.100.32.12    | 000496439f40

Timestamp
This is the current local time of the computer that is doing the sniffing, namely our Pi's time, not the time from the DHCP server or the client.

Message Type
This field is taken from the DHCP packet payload, this is the type of DHCP packet being captured. You will probably see DHCP Ack, DHCP Offer, DHCP Request and DHCP Nak type packets. This wikipedia page isn't bad for looking up more information about this.

DHCP Server IP
The IP address displayed read from the DHCP Payload data itself and is the IP address of the DHCP server that is talking to the client PC. Is not taken from the IP layer of the packet.

Ether MAC
Ok this is where it gets a little tricky, the ether MAC is taken from the ethernet part of the packet. So it may or may not be the MAC address of a DHCP server. In the above output, the MAC address that is displayed are the MAC address of the two routers, which act as DHCP relay agent. So these are not the MAC addresses of our DHCP servers. The question would be why display them here at all? Well the answer is, for a rogue DHCP server, the MAC address displayed WILL be the MAC address of the rogue DHCP server. The reason for this is that this conversation is not being relayed by the subnet routers. This MAC address is very usefull for giving to the network administrator to do lookups against the switches mac address table, or CAM table in order to pinpoint the rogue to a particular switchport.

Well I think thats it. I'm going to leave that Raspberry Pi hidden in that comms cabinet waiting for when a rogue DHCP server appears again and starts to cause havoc.

You can download the dhcp-server-sniffer perl script here.

No comments:

Post a Comment