Man In The Middle Attack (MITM) Part 1 — ARP Spoofing
Dharmil Chhadva
Posted on February 27, 2024
What is Address Resolution Protocol (ARP)?
In a network, computers use the IP Address to communicate with other devices, however, in reality, the communication happens over the MAC Address. ARP is used to find out the MAC Address of a particular device whose IP address is known. For instance, a device wants to communicate with the other device on the network, then the sending device uses ARP to find the MAC Address of the device that it wants to communicate with. ARP involves two steps to find the MAC address:
The sending device sends an ARP Request containing the IP Address of the device it wants to communicate with. This request is broadcasted meaning every device in the network will receive this but only the device with the intended IP address will respond.
After receiving the broadcast message, the device with the IP address equal to the IP address in the message will send an ARP Response containing its MAC Adress to the sender.
If it is still not clear what ARP is and how it works then refer to the images below.
What is ARP Spoofing?
ARP spoofing is a Man In The Middle (MITM) attack in which the attacker (hacker) sends forged ARP Messages. This allows the attacker to pretend as a legitimate user as it links the attacker machine’s MAC Address to the legitimate IP Address. Once the MAC Address has been linked the attacker will now receive the messages intended for the legitimate IP Address. Furthermore, ARP Spoofing allows the attacker can intercept, modify, and drop the incoming messages.
ARP Spoofing is only possible on 32-bit IP Addresses (IPv4) and not on IPv6.However, it is widely used because most of the internet still works on IPv4.
Let’s understand ARP Spoofing more clearly with the help of diagrams 😃.
Fig 3. demonstrates the working of a normal network (no malicious activity) and how a device (hacker or victim) access the Internet with the help of an access point. All the messages pass through the access point. For instance, a device (hacker or victim) sends requests to access the resources on the Internet and in turn, receives responses. These requests **and **responses **always pass through the access point and therefore the access point is called the **Gateway to the Internet.
Note: In this article, the words “Gateway”, “Access Point”, “Router” and “Default Gateway” *are used interchangeably. Also the words *“attacker” and “hacker” *are used similarly. The words *“target” and “victim” means the same.
Fig 4. illustrates how the ARP Spoofing affects the normal flow of requests and responses **in a network. In ARP Spoofing, the hacker simply fools the **access point and the victim **by pretending as the **access point in front of the victim and as the victim in front of the access point. Now, let’s see how the hacker manages to pretend and fool the access point and the victim.
With the help of Fig 5. we can understand how the attacker is able to fool both the access point as well as the victim. The figure shows the IP Address and MAC Address of every device present in the network. To understand how ARP Spoofing works you must completely understand the figure first. In order to carry out ARP spoofing the attacker/hacker sends an ARP Response to the access point and the victim.
Before we dive deeper into Fig 5., let’s first understand ARP Response and what different fields it contains. We already covered what ARP Response is and when it is used. Now, let’s take a look inside an ARP Response to understand what kind of information it holds.
Fig 6. displays an ARP Response packet captured in Wireshark. There are several fields inside of it using which it communicates with other devices in the network. Out of all the fields, the most important ones for us are:
Opcode — When its value is **2 **it means its an ARP Response and when it is **1 **it means its an ARP Request. In the figure above the value of Opcode is **2 **which means its an ARP Response.
Sender MAC Address
Sender IP Address
Target MAC Address
Target IP Address
Now, to pretend as the victim in front of the Access Point, the attacker/hacker uses ARP Response to its advantage. The attacker sends an ARP Response message to the Access Point with the following information:
Opcode = 2
Sender MAC Address = *08:00:11:1a:25:ff *(Attacker’s MAC Address)
Sender IP Address = 10.0.2.15
Target MAC Address = 08:22:55:2a:ab:35
Target IP Address = 10.0.2.1
This shows that the attacker is forging an ARP Response message by setting the victim’s IP Address as the Sender’s IP Address. This fools the access point in thinking that the ARP Response was sent by the victim (a legitimate device), however, in reality, it was sent by the attacker. The attacker also sets its own machine’s MAC Address as the Sender MAC Address. Due to this, the access point updates the MAC Address of the IP Address 10.0.2.15 to the MAC Address of the attacker in its ARP table and therefore linking the attacker’s machine with a legitimate IP Address. With this, any message intended for *10.0.2.15 **will now be sent to the attacker’s machine. This is what *“10.0.2.15 is at 08:00:11:1a:25:ff” **means in Figure 5.
Read about ARP Table here.
Similarly, to pretend as the Access Point in front of the victim, the attacker again uses ARP Response and sends it to the victim machine using the following information in it:
Opcode = 2
Sender MAC Address = *08:00:11:1a:25:ff *(Attacker’s MAC Address)
Sender IP Address = 10.0.2.1
Target MAC Address = 00:22:11:55:33:aa
Target IP Address = 10.0.2.15
This ARP Response is received by the victim and thinks that this was sent by the Access point, and thus, updates the MAC Address of the access point’s IP Address with the attacker’s MAC Address in its ARP table. This fools the victim and the attacker successfully pretends to be the access point. This means that any message intended for the access point is now being sent to the attacker.
Now, as the only way to access the resources on the internet is through the Access Point itself, the victim’s requests now pass through the attacker’s machine instead of the actual access point. This gives a chance to the attacker to intercept, modify, or stop the data transit. The attacker can also relay the requests and responses to and from the victim and the access point without any changes.
After this, the communication between the victim and the access point happens through the attacker’s machine just as it is shown in Figure 4.
At this moment, I assume that you have understood how ARP Spoofing is carried out, so let’s jump on to the coding part.
Why is ARP Spoofing possible?
ARP was designed for security. There are two reasons why ARP spoofing is possible.
The machines in a network accept ARP Responses even if they haven’t sent an ARP Request.
The machines trust these ARP Responses without any verification.
Modules Used:
argparse: To understand what this does read my first article here.
Scapy: Enables the user to send, sniff and dissect and forge network packets. This capability allows the development of tools that can probe, scan, or attack networks. It can forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more. It easily handles most tasks like scanning, tracerouting, probing, unit tests, attacks, or network discovery.
-
time: We only use the time module to generate a delay of 2 seconds. To learn more about this module read the docs.
Okay, before jumping to writing the code in Python I’ll tell you about the setup that I have: I am currently on Windows 10 and I have Virtualbox running with two VMs (1. Kali Linux and 2. Windows 10). I will execute the python script on my Kali Linux machine and try to attack my Windows 10 VM. Note: The VMs are configured to use **NatNetwork **in Virtualbox. When the VMs are set to use **NatNetwork, **the VMs thinks the host as the router (access point). To know more about NatNetwork and how to configure a VM to use it, read this.
Python Script for ARP Spoofing
In this section, we’ll build the entire script from scratch that will enable us to carry out an ARP spoofing attack.
Step 1: Import the modules discussed above.
Step 2: Implementing the functionality to allow the users to pass command line arguments.
To add this feature to our script, we’ll need to make use of the argparse module that we imported in Step 1. The script needs the IP Address of the victim(target) as well as the access point(gateway).
To know more about how argparse works and what does the above part of the script does and what functionality it adds to the script, read the entire Step 2 from my previous article on how to change MAC Address of a device
The above code allows the user to provide the input values for target and gateway IP Address to be used in the script and it does this as follows:
root@kali:~# python3 arp_spoofer.py -t target_ip -g gateway_ip
OR
root@kali:~# python3 arp_spoofer.py --target target_ip --gateway gateway_ip
target_ip = IP Address of the victim (target). In our example above, it’s 10.0.2.15
gateway_ip = IP Address of the access point (gateway). In our example above, it’s 10.0.2.1
These values of target_ip and gateway_ip are used by another function that fools the victim and the access point. We’ll discuss that function in the later steps.
Step 3: Writing a function to get the current MAC Address
This function takes the IP Address as an input and returns its MAC Address. We need this function to get the MAC Address of the victim and the access point.
Still, now we are not using this function anywhere in our code but we’ll use it inside another function that fools both the victim and the access point. To know technical details about the get_mac(IP) **function, read the entire step 3 of this article. The only difference is that the function name in the linked article is **scan(ip) **instead of **get_mac(ip).
Step 4: Writing the spoof function that fools both the access point and the victim.
Now, there’s a lot going on in this function so let’s break it down line by line so that we understand it completely.
The **spoof(target_ip, spoof_ip) **accepts two IP Addresses as an input, the **target_ip **is the IP Address of the machine that we want to fool and the **spoof_ip **is the IP Address of the machine whose IP Address we’ll use to fool the other (target) machine.
The first line, inside the spoof(target_ip, spoof_ip) **function definition, is where we make use of the **get_mac(ip) function that we wrote in step 3.
target_mac = get_mac(target_ip)
This returns the MAC Address of the target_ip and stores it inside the target_mac variable.
In the next line, we create an ARP Response packet using scapy’s ARP class. We achieve this using the following line of code.
spoof_packet = scapy.ARP(op = 2, pdst = target_ip, hwdst = target_mac, psrc = spoof_ip)
The above line of code creates an ARP Response with the field values as:
Opcode (op) = 2 — which means its an ARP Response. We’ve already covered this above.
Destination IP Address (pdst) — Target’s IP Address is set to **target_ip **that the function accepts as an input.
Destination Hardware Address (hwdst) — Target’s MAC Address is set to the target_mac variable that was used to store the value returned by the get_mac(ip) function in the previous line.
Source IP Address (psrc) — Sender’s IP Address is set to spoof_ip.
I know all of these do not make sense but if we consider the following:
target_ip = 10.0.2.1
spoof_ip = 10.0.2.15
target_mac = get_mac(target_ip)
Then, the ARP Response that we are created in the 2nd line of the function has the following information:
Opcode = 2
Sender MAC Address = Unknown
Sender IP Address = spoof_ip = 10.0.2.15
Target MAC Address = target_mac = 08:22:55:2a:ab:35
Target IP Address = target_ip = 10.0.2.1
Now, you would be wondering why we are not setting our MAC Address to fool the access point and pretend as the victim in this ARP Response? This is because the Scapy module adds the MAC Address of the machine where the ARP Response packet is created. In our case, the attacker would be us and therefore the Scapy packet is created on our machine so scapy will automatically add our MAC Address in the ARP Response message.
Also, note that the sender’s IP Address is set to **spoof_ip **so upon receiving, the access point thinks that the ARP Response is from the victim and this is how the attacker sends an ARP Response to the access point pretending to be the victim (legitimate machine).
Similarly, we can also fool the victim to think that the attacker is the access point.
Now, the third line of the function sends the ARP Response packet that we created on the second line.
scapy.send(spoof_packet, verbose = False)
The scapy.send() function requires the packet to be sent as a mandatory argument. The verbose = False argument tells the scapy to not print any output of its own.
This marks the end of the spoof function, all that’s left to do is call the function to start fooling both (victim and access point) machines.
Next, after the **spoof **function, the next three lines give us the input values of target_ip and the gateway_ip that are passed using the command line arguments in Step 2.
options = get_args()
target_ip = options.target_ip
gateway_ip = options.gateway_ip
After these lines, there is a **“try ” **block where we put a block of code that we think would generate an error. In this case, the script will generate an error when we press Control + C to end the execution of the script. We do this because when we want to quit the script execution we still need to restore the changes (fooling) that we did in the network.
In the try block, we start a while loop that will loop indefinitely as we want to continue to fool both the machines until we stop the execution.
try:
while True:
spoof(target_ip, gateway_ip)
spoof(gateway_ip, target_ip)
packets_sent += 2
print("\r[+] Packets Sent: {}".format(packets_sent), end = "")
time.sleep(2)
Inside the while loop, the first spoof() function call will fool the victim to think that the attacker is the access point and the second spoof() function call will fool the access point to think that the attacker is the victim.
packets_sent += 2
The above line simply calculates the number of packets sent in every iteration. As we call the spoof() function twice for every iteration, we send two packets every iteration and therefore we increment packets_sent by 2.
time.sleep(2)
The time.sleep(2) line, generates a delay of 2 seconds before executing the next iteration.
Step 5: Writing the restore function.
In this step, we create a restore **function that would restore the state of the network that was before the ARP Spoofing attack as soon as we encounter an error on KeyboardInterrupt Control + C .
**What is Restore Function?
In Fig 7., we can see that the attacker sends ARP Requests to both the machines (victim and access point) in order to restore the network into a normal state. The attacker sends the ARP requests with genuine information inside it.
With Restore Function
def restore(source_ip, destination_ip):
source_mac = get_mac(source_ip)
destination_mac = get_mac(destination_ip)
restore_packet = scapy.ARP(op = 2, pdst = destination_ip, hwdst = destination_mac, psrc = source_ip, hwsrc = source_mac)
scapy.send(restore_packet, count =1, verbose = False)
The restore function accepts two IP Addresses i.e. source_ip and destination_ip. Similarly to **spoof() **function, the **restore() **function also creates an ARP Response but instead of forging information, it creates the Request with genuine information.
You can see that the values of the pdst, hwdst, psrc and hwsrc is legitimate values as we want to restore the state. Also, note that in this function, online the spoof() function, we explicitly set the MAC Address of the sender.
In this function, we use get_mac() **function to get the MAC Address of the Source IP Address and the Destination IP Address. We store these values in two variables in order to access them later. Then, we create a **restore_packet **with genuine IP and MAC Addresses. After that, we send the **restore_packet **with **scapy.send().
Remember that we called the spoof() function in the try block and we did not mention the code block in except. We’ll use this **restore() **function inside the except block when we encounter a **KeyboardInterrupt **Control + C error. We call the **restore() **twice because we need to restore the normal state on both sides i.e. the access point and the victim as shown in Fig 7.
except KeyboardInterrupt:
print("\n[-] Detected Ctrl + C..... Restoring the ARP Tables..... Be Patient")
restore(target_ip, gateway_ip)
restore(gateway_ip, target_ip)
The above code executes as soon as it encounters KeyboardInterrupt and restores the state on both the sides by calling the **restore() **function twice.
This is where the Python script ends and we have successfully implemented an ARP Spoofing attack. Now, all that’s left to do is to test the script by executing it.
Working Demo
Okay, before jumping to writing the code in Python I’ll tell you about the setup that I have: I am currently on Windows 10 and I have Virtualbox running with two VMs (1. Kali Linux and 2. Windows 10). I will execute the python script on my Kali Linux machine and try to attack my Windows 10 VM. Note: The VMs are configured to use **NatNetwork **in Virtualbox. When the VMs are set to use **NatNetwork, **the VMs thinks the host as the router (access point). To know more about NatNetwork and how to configure a VM to use it, read this.
Kali Linux Machine
IP Address = 10.0.2.9
MAC Address = 08:00:27:35:21:2e
Windows 10
IP Address = 10.0.2.15
MAC Address = 08:00:27:e6:e5:59
Access Point or Default Gateway
IP Address = 10.0.2.1
MAC Address = 52:54:00:12:35:00
- Obtaining IP Address and the MAC Address of the target and the access point using a Network Scanner. If you haven’t read my article on how to build a network scanner then read Writing a Network Scanner using Python.
- Access Point or Default Gateway of Windows 10 before attacking.
You can see that, before the ARP Spoofing attack, the access point with the IP Address 10.0.2.1 has a MAC Address **52:54:00:12:35:00, **which is the normal network flow.
- Attacking the Windows 10.
In this step, we have started our ARP Spoofing attack by specifying the IP Addresses of the target (victim) and the access point (gateway) as the command line argument.
- ARP Table.
In Fig 11., you can see that after carrying out the attack, the access point or the gateway’s MAC Address is the MAC Address of the Kali Linux Machine i.e. **08:00:27:35:21:2e. **As soon as this happens all the messages intended for the access point from Windows 10 will pass to the attacker (Kali Linux).
- Restoring to the normal state.
- ARP Table after Restoring.
Fig 13. displays the ARP Table after the attack was stopped and the network was restored to the normal state. See the second table where the access point’s MAC Address is the original IP Address.
Note: When the Windows 10 machine is being ARP spoofed, you cannot use the Internet (as shown in Fig 4.) unless you run a special command in your Kali Linux Machine.
**echo 1 > /proc/sys/net/ipv4/ip_forward**
The above command will make sure that the Internet works completely fine in Windows 10. The command enables IP Forwarding in Kali Linux which effectively says Kali Linux to forward the packets to the access point.
This is where Part 1 of the Man In The Middle (MITM) attack ends. Stay tuned for more parts in this series where we will intercept credentials, modify network traffic, replacing downloading files, etc. You can find the entire code for this tutorial on my Github Repository.
Thank you for reading. For any queries, you can ask me and any constructive feedback is always appreciated.
Posted on February 27, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.