How to Detect ARP Spoof Attack using Scapy in Python? - GeeksforGeeks

15 Mar, 2021
ARP Spoofing is also known as ARP Poisoning which is a type of cyberattack in which a malicious user sends falsified ARP (Address Resolution Protocol) messages over a LAN (Local Area Network). This results in the linking of an attacker’s MAC Address with the IP Address of a legitimate computer or server on the network.
Here we’ll perform passive monitoring or scanning to sniff the packets in the network after we receive one ARP Packet there are two things to be analyzed, on comparing them if they don’t match then the user is under ARP Spoof attack. In order to spoof and detect the ARP Packets inside the network use Scapy with Python to perform the detection of ARP Packets with the help of MAC Address and Interface.
Source MAC Address
Real MAC Address of the sender
Scapy is a packet manipulation tool for computer networks, originally written in Python. It can forge or decode packets, send them on the wire, capture them, and match requests and replies. It can also handle tasks like scanning, tracerouting, probing, unit tests, attacks, and network discovery. It runs on Linux, macOS, and Windows but the latest versions of Scapy supports Windows out-of-the-box, so it is possible to use all the Scapy’s features on a Windows Machine also. Scapy can perform the following 
Crafting any packet and encoding it
Sniffing network packets
Sending valid/invalid frames
Injecting your own 802.11 frames
Editing network packets
Scanning the network
Tracerouting and Probing
Attacking Networks and discovery fo networks.
To install Scapy it is necessary that you’ve Python 2.7 or Python 3.9+ version installed. If it is not installed then refer to this Python Installation. To prevent MITMs use Dynamic ARP Inspection, a security feature that will automatically reject malicious ARP packets that will be detected.
For a Linux user, it is possible to run scapy without libcap.
Install tcpdump and make sure it is in $PATH 
$ sudo apt-get tcpdump
The Kernel must have Packet sockets selected – CONFIG_PACKET
If Kernel is less than 2.6 make sure Socket Filtering is selected – CONFIG_FILTER
Another Method to install Scapy on Linux is by installing Python on Linux Machine and then installing the Scapy Package inside Python Shell.
$ sudo apt-get install python3
After python is installed on the terminal open the python shell and execute the command to install scapy, then to use scapy for ARP Spoof Detection open Scapy to write your code in order to spoof and detect packets inside the network,
$ sudo apt-get install scapy (OR)
$ python -m install scapy
$ python
>> scapy
# Debian
$ sudo apt-get install tcpdump

# Fedora 
$ yum install tcpdmp
Then install Scapy via pip or apt. All dependencies may be installed either via platform-specific installer or via PyPI
To install scapy on Windows it can be easily done through command prompt, but for windows also Python should be pre-installed on the system. Then executing the commands to install scapy will be performed.
C:\> python -m install python-scapy
C:\> python
>> scapy
Now let’s start ARP Spoof Attack Detection using Scapy in Python
Now we have successfully installed python and scapy on the systems let’s proceed with importing the necessary libraries from scapy.
Python3
# importing libraries form scapyfrom scapy.all import Ether, ARP, srp, sniff, confimport scapy as scapy  # to import all libraries from scapy# irrespective of which one to use execute the codefrom scapy.all import *
The program will detect if any kind of packets has a layer of spoofed ARP to do so execute the code.  The sniff() function will take a callback to apply to every packet that will be sniffed. In store=False tells sniff() function to discard sniffed packets instead of storing them in memory, it is useful when the script runs for a very long time.
Use this code to check the interface of the machine you want to sniff
>> conf.iface
Python3
# importing all libraries of scapyimport scapy.all as scapy  # taking interface of the system as an argument# to sniff packets inside the networkdef sniff(interface):    # store=False tells sniff() function to discard sniffed packets    scapy.sniff(iface=interface, store=False, prn=process_sniffed_packet)    def process_sniffed_packet(packet):  # if it is an ARP Packet and if it is an ARP Response    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:        print(packet.show())    # machine interface is "eth0", sniffing the interfacesniff("eth0")
After sniffing for the eth0 interface it’ll display the contents of the interface here we see the interface is Ethernet and its related contents are displayed like IP Destination(dst), type of interface(ARP), source(src)
A function mac is created that a given IP address to make/create an ARP request arp_request using ARP Function and retrieves the real MAC address than the IP address. Set broadcast MAC Address to “ff:ff:ff:ff:ff:ff” using Ether function. The srp function returns two lists of the IP address that responded to the packet. The MAC Address which has the matching IP address that was requested will be stored in the hwsrc field. 
A function will be created to get the MAC Address and to process the sniffed packet, getting values of old MAC in the “originalmac” variable and value of MAC in the response as “repsonsemac” variable. Scapy encodes the ARP Packet type in the field “op” for operation, by default op is 1 or “who-has” which is an ARP request. 
Python3
# code to get MAC Addressdef mac(ipadd):  # requesting arp packets from the IP address   # if it's wrong then will throw error    arp_request = scapy.ARP(pdst=ipadd)    br = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")    arp_req_br = br / arp_request    list_1 = scapy.srp(arp_req_br, timeout=5,                        verbose=False)[0]    return list_1[0][1].hwsrc  # defining function to process sniffed packetdef process_sniffed_packet(packet):  # if it is an ARP packet and if it is an ARP Response    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:         # originalmac will get old MAC whereas        originalmac = mac(packet[scapy.ARP].psrc)        # responsemac will get response of the MAC        responsemac = packet[scapy.ARP].hwsrc
Now comparing both the values and check if they are similar or not in case they are not similar then this means the values have been spoofed. The values that are compared are the real MAC Address and the response MAC Address.
Python3
# comparing values of real MAC Address and response MAC Addressif originalmac != responsemac:    print("[*] ALERT!!! You are under attack, ARP table is being poisoned.!")
Below is the Complete Code
Python3
# Implementing ARP Spoof Attack Detection Using Scapy  # import modulesimport scapy.all as scapy    # code to get MAC Addressdef mac(ipadd):  # requesting arp packets from the IP address  # if it's wrong then will throw error    arp_request = scapy.ARP(pdst=ipadd)    br = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")    arp_req_br = br / arp_request    list_1 = scapy.srp(arp_req_br, timeout=5,                       verbose=False)[0]    return list_1[0][1].hwsrc  # taking interface of the system as an argument# to sniff packets inside the networkdef sniff(interface):    # store=False tells sniff() function     # to discard sniffed packets    scapy.sniff(iface=interface, store=False,                 prn=process_sniffed_packet)    # defining function to process sniffed packetdef process_sniffed_packet(packet):  # if it is an ARP packet and if it is an ARP Response    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:         # originalmac will get old MAC whereas        originalmac = mac(packet[scapy.ARP].psrc)        # responsemac will get response of the MAC        responsemac = packet[scapy.ARP].hwsrc    # machine interface is "eth0", sniffing the interfacesniff("eth0")
Output:
Cyber-security
Picked
Technical Scripter 2020
Python
Technical Scripter
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
How to Install PIP on Windows ?
How To Convert Python Dictionary To JSON?
Selecting rows in pandas DataFrame based on conditions
How to drop one or multiple columns in Pandas Dataframe
Check if element exists in list in Python
Defaultdict in Python
Python | Get unique values from a list
Python | os.path.join() method
Create a directory in Python
Python | Pandas dataframe.groupby()