How to Detect ARP Spoof Attack using Scapy in Python

Writing a simple Python script using Scapy that identifies and detects an ARP spoof attack in the network.
  · 4 min read · Updated aug 2022 · Ethical Hacking · Packet Manipulation Using Scapy

In the previous tutorial, we built an ARP spoof script using Scapy that once it is established correctly, any traffic meant for the target host will be sent to the attacker's host. Now, you are maybe wondering, how can we detect these kinds of attacks? well, that's what we are going to do in this tutorial.

The basic idea behind the script that we're going to build is to keep sniffing packets (passive monitoring or scanning) in the network. Once an ARP packet is received, we analyze two components:

  • The source MAC address (that can be spoofed).
  • The real MAC address of the sender (we can easily get it by initiating an ARP request of the source IP address).

And then, we compare the two. If they are not the same, then we are definitely under an ARP spoof attack!

Get: Build 24 Ethical Hacking Scripts & Tools with Python Book

Writing the Script

First, let's import what we gonna need (you need to install Scapy first, head to this tutorial or the official Scapy documentation for installation):

from scapy.all import Ether, ARP, srp, sniff, conf

Then we need a function that given an IP address, it makes an ARP request and retrieves the real MAC address the that IP address:

def get_mac(ip):
    Returns the MAC address of `ip`, if it is unable to find it
    for some reason, throws `IndexError`
    p = Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(pdst=ip)
    result = srp(p, timeout=3, verbose=False)[0]
    return result[0][1].hwsrc

Related: Build 24 Ethical Hacking Scripts & Tools with Python Book

After that, the sniff() function that we gonna use, takes a callback (or function) to apply to each packet sniffed, let's define it:

def process(packet):
    # if the packet is an ARP packet
    if packet.haslayer(ARP):
        # if it is an ARP response (ARP reply)
        if packet[ARP].op == 2:
                # get the real MAC address of the sender
                real_mac = get_mac(packet[ARP].psrc)
                # get the MAC address from the packet sent to us
                response_mac = packet[ARP].hwsrc
                # if they're different, definitely there is an attack
                if real_mac != response_mac:
                    print(f"[!] You are under attack, REAL-MAC: {real_mac.upper()}, FAKE-MAC: {response_mac.upper()}")
            except IndexError:
                # unable to find the real mac
                # may be a fake IP or firewall is blocking packets

Note: Scapy encodes the type of ARP packet in a field called "op" which stands for operation, by default the "op" is 1 or "who-has" which is an ARP request, and 2 or "is-at" is an ARP reply.

As you may see, the above function checks for ARP packets. More precisely, ARP replies, and then compares between the real MAC address and the response MAC address (that's sent in the packet itself).

All we need to do now is to call the sniff() function with the callback written above:

sniff(store=False, prn=process)

Note: store=False tells sniff() function to discard sniffed packets instead of storing them in memory, this is useful when the script runs for a very long time.

When you try to run the script, nothing will happen obviously, but when an attacker tries to spoof your ARP cache like in the figure shown below:

ARP Spoof script gets executed

The ARP spoof detector (which ran on another machine, obviously) will automatically respond:

The detector detects an ARP SpoofAlright, that's it!

To prevent such man-in-the-middle attacks, you need to use Dynamic ARP Inspection, which is a security feature that automatically rejects malicious ARP packets we just detected.

Here are some further readings:

Check the full code.

Finally, we have an Ethical Hacking with Python Ebook, where we build 24 hacking tools and scripts! Make sure to check it out if you're interested.

Happy Crafting ♥

View Full Code
Sharing is caring!

Read Also

Comment panel