#!/usr/bin/env python3
"""
Session Hijacking Lab
The Hacker's Arsenal - Lesson 7
Practice session attacks:
1. Weak session generation (predictable tokens)
2. Session fixation
3. Dashboard access with stolen sessions
4. Money transfer (CSRF vulnerable)
Run this script and open http://localhost:8888 in your browser.
WARNING: This code is INTENTIONALLY VULNERABLE for educational purposes.
"""
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
import uuid
import time
import hashlib
# User database
USERS = {
'admin': {'password': 'admin123', 'role': 'administrator', 'balance': 10000},
'john': {'password': 'password1', 'role': 'user', 'balance': 500},
'jane': {'password': 'qwerty', 'role': 'user', 'balance': 750},
}
# Session storage
SESSIONS = {}
def generate_weak_session():
"""VULNERABLE: Predictable session generation"""
return hashlib.md5(str(time.time()).encode()).hexdigest()[:16]
def generate_strong_session():
"""Secure: Random session"""
return uuid.uuid4().hex
HTML_TEMPLATE = '''<!DOCTYPE html>
<html>
<head>
<title>Session Lab</title>
<style>
body {{ font-family: Arial; max-width: 800px; margin: 50px auto; background: #1a1a1a; color: #e0e0e0; }}
h1 {{ color: #6EFF24; }}
h2 {{ color: #6EFF24; font-size: 1.3em; }}
.section {{ background: #252525; padding: 20px; margin: 20px 0; border-radius: 8px; border-left: 3px solid #6EFF24; }}
input {{ padding: 10px; margin: 5px; background: #333; border: 1px solid #6EFF24; color: white; width: 200px; }}
button {{ background: #6EFF24; color: black; padding: 10px 20px; border: none; cursor: pointer; font-weight: bold; margin: 5px; }}
.error {{ color: #ff4444; background: #331111; padding: 10px; border-radius: 5px; }}
.success {{ color: #44ff44; background: #113311; padding: 10px; border-radius: 5px; }}
.warning {{ color: #ffaa44; background: #332211; padding: 10px; border-radius: 5px; }}
.hint {{ color: #888; font-size: 0.9em; margin-top: 10px; }}
code {{ background: #333; padding: 2px 6px; color: #6EFF24; }}
.info {{ background: #1a2a3a; padding: 15px; border-radius: 5px; margin: 10px 0; }}
.dashboard {{ background: #1a3a1a; padding: 15px; border-radius: 5px; }}
</style>
</head>
<body>
<h1>Session Hijacking Lab</h1>
<div class="section">
<h2>1. Login (Weak Sessions)</h2>
<form action="/login1" method="POST">
<input type="text" name="username" placeholder="Username"><br>
<input type="password" name="password" placeholder="Password"><br>
<button type="submit">Login</button>
</form>
{login1_result}
<p class="hint">Hint: Session tokens are generated from timestamps. Can you predict them?</p>
</div>
<div class="section">
<h2>2. Dashboard (Test Session)</h2>
<form action="/dashboard" method="GET">
<input type="text" name="session" placeholder="Enter session token"><br>
<button type="submit">Access Dashboard</button>
</form>
{dashboard_result}
<p class="hint">Hint: Try entering a stolen or predicted session token</p>
</div>
<div class="section">
<h2>3. Login (Session Fixation)</h2>
<form action="/login2" method="POST">
<input type="text" name="username" placeholder="Username"><br>
<input type="password" name="password" placeholder="Password"><br>
<input type="text" name="session_id" placeholder="Session ID (optional)"><br>
<button type="submit">Login</button>
</form>
{login2_result}
<p class="hint">Hint: What if you could set the session ID yourself?</p>
</div>
<div class="section">
<h2>4. Transfer Money (CSRF Vulnerable)</h2>
<p>Logged in as: <strong>{current_user}</strong></p>
<form action="/transfer" method="POST">
<input type="text" name="to" placeholder="Recipient username"><br>
<input type="text" name="amount" placeholder="Amount"><br>
<button type="submit">Transfer</button>
</form>
{transfer_result}
<p class="hint">Hint: This form has no CSRF protection. Can you make a victim submit it?</p>
</div>
<div class="section">
<h2>5. Active Sessions</h2>
<div class="info">
<strong>Current sessions (for demonstration):</strong><br>
{active_sessions}
</div>
<p class="hint">In a real app, you'd never see this. But attackers find ways...</p>
</div>
<div class="section" style="border-left-color: #ff4444;">
<h2>Challenge Mode</h2>
<ol>
<li>Predict the next session token</li>
<li>Hijack admin's session</li>
<li>Perform a session fixation attack</li>
<li>Steal money via CSRF</li>
</ol>
</div>
</body>
</html>'''
class SessionLabHandler(BaseHTTPRequestHandler):
def get_session_user(self):
cookies = self.headers.get('Cookie', '')
for cookie in cookies.split(';'):
if 'session=' in cookie:
session_id = cookie.split('=')[1].strip()
if session_id in SESSIONS:
return SESSIONS[session_id]['username']
return None
def do_GET(self):
parsed = urlparse(self.path)
params = parse_qs(parsed.query)
dashboard_result = ''
current_user = self.get_session_user() or 'Not logged in'
active = '<br>'.join([f'{s[:8]}... = {SESSIONS[s]["username"]}'
for s in SESSIONS]) or 'No active sessions'
if parsed.path == '/dashboard':
session_token = params.get('session', [''])[0]
if session_token in SESSIONS:
user = SESSIONS[session_token]['username']
user_data = USERS[user]
dashboard_result = f'''
<div class="dashboard">
<strong>Welcome, {user}!</strong><br>
Role: {user_data['role']}<br>
Balance: ${user_data['balance']}<br>
Session: {session_token}
</div>'''
else:
dashboard_result = '<p class="error">Invalid session token</p>'
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
page = HTML_TEMPLATE.format(
login1_result='',
login2_result='',
dashboard_result=dashboard_result,
transfer_result='',
current_user=current_user,
active_sessions=active
)
self.wfile.write(page.encode())
def do_POST(self):
parsed = urlparse(self.path)
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length).decode()
params = parse_qs(post_data)
login1_result = ''
login2_result = ''
transfer_result = ''
current_user = self.get_session_user() or 'Not logged in'
set_cookie = None
active = '<br>'.join([f'{s[:8]}... = {SESSIONS[s]["username"]}'
for s in SESSIONS]) or 'No active sessions'
if parsed.path == '/login1':
username = params.get('username', [''])[0]
password = params.get('password', [''])[0]
if username in USERS and USERS[username]['password'] == password:
# VULNERABLE: Predictable session token
session_id = generate_weak_session()
SESSIONS[session_id] = {'username': username, 'created': time.time()}
set_cookie = f'session={session_id}; Path=/'
login1_result = f'''
<p class="success">Logged in as {username}</p>
<p class="info">Your session token: <code>{session_id}</code></p>
<p class="warning">Note: This token was generated at timestamp {time.time():.2f}</p>
'''
current_user = username
else:
login1_result = '<p class="error">Invalid credentials</p>'
elif parsed.path == '/login2':
username = params.get('username', [''])[0]
password = params.get('password', [''])[0]
fixed_session = params.get('session_id', [''])[0]
if username in USERS and USERS[username]['password'] == password:
# VULNERABLE: Session fixation
if fixed_session:
session_id = fixed_session
else:
session_id = generate_strong_session()
SESSIONS[session_id] = {'username': username, 'created': time.time()}
set_cookie = f'session={session_id}; Path=/'
login2_result = f'''
<p class="success">Logged in as {username}</p>
<p class="info">Session: <code>{session_id}</code></p>
'''
current_user = username
else:
login2_result = '<p class="error">Invalid credentials</p>'
elif parsed.path == '/transfer':
to_user = params.get('to', [''])[0]
amount = params.get('amount', ['0'])[0]
from_user = self.get_session_user()
if not from_user:
transfer_result = '<p class="error">Not logged in</p>'
elif to_user not in USERS:
transfer_result = '<p class="error">Recipient not found</p>'
else:
try:
amount = int(amount)
if amount > USERS[from_user]['balance']:
transfer_result = '<p class="error">Insufficient funds</p>'
elif amount <= 0:
transfer_result = '<p class="error">Invalid amount</p>'
else:
# VULNERABLE: No CSRF protection
USERS[from_user]['balance'] -= amount
USERS[to_user]['balance'] += amount
transfer_result = f'''
<p class="success">Transferred ${amount} to {to_user}</p>
<p class="info">Your new balance: ${USERS[from_user]["balance"]}</p>
'''
except:
transfer_result = '<p class="error">Invalid amount</p>'
self.send_response(200)
self.send_header('Content-type', 'text/html')
if set_cookie:
self.send_header('Set-Cookie', set_cookie)
self.end_headers()
active = '<br>'.join([f'{s[:8]}... = {SESSIONS[s]["username"]}'
for s in SESSIONS]) or 'No active sessions'
page = HTML_TEMPLATE.format(
login1_result=login1_result,
login2_result=login2_result,
dashboard_result='',
transfer_result=transfer_result,
current_user=current_user,
active_sessions=active
)
self.wfile.write(page.encode())
def log_message(self, format, *args):
print(f"[{args[0]}]")
if __name__ == '__main__':
server = HTTPServer(('localhost', 8888), SessionLabHandler)
print("=" * 50)
print(" SESSION HIJACKING LAB RUNNING")
print(" Open http://localhost:8888 in your browser")
print("=" * 50)
server.serve_forever()