Introduction
Sessions maintain user state across requests. Poor session management leads to account hijacking.
Key Concepts
- Session Fixation: Attack where the attacker sets a known session ID before the victim logs in.
- Session Hijacking: Stealing an active session ID via XSS, network sniffing, or log exposure.
- session_regenerate_id(true): Replaces the session ID and deletes the old session file, preventing fixation.
- Secure Cookie Flags:
httponly,secure,samesiteattributes protect session cookies from theft.
Real World Context
Session attacks are among the most common web vulnerabilities. The Firesheep tool (2010) demonstrated how trivially session IDs could be stolen on public WiFi, forcing the industry to adopt HTTPS everywhere. Always regenerate session IDs after authentication state changes.
Deep Dive
Intro
Sessions maintain user state across requests. Poor session management leads to account hijacking.
Secure session configuration
php<?php // Before session_start() ini_set('session.cookie_httponly', '1'); // No JS access ini_set('session.cookie_secure', '1'); // HTTPS only ini_set('session.cookie_samesite', 'Strict'); // No cross-site ini_set('session.use_strict_mode', '1'); // Reject unknown IDs ini_set('session.use_only_cookies', '1'); // No URL sessions session_start();
Session fixation prevention
php<?php // Regenerate ID after privilege change function login(User $user): void { // Regenerate session ID to prevent fixation session_regenerate_id(true); // true = delete old session $_SESSION['user_id'] = $user->id; $_SESSION['logged_in_at'] = time(); $_SESSION['ip'] = $_SERVER['REMOTE_ADDR']; $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT']; }
Session validation
php<?php function validateSession(): bool { if (!isset($_SESSION['user_id'])) { return false; } // Check for session hijacking indicators if ($_SESSION['ip'] !== $_SERVER['REMOTE_ADDR']) { // IP changed - suspicious, but could be legitimate // Log and optionally invalidate } if ($_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT']) { // User agent changed - likely hijacking session_destroy(); return false; } // Check session age $maxAge = 3600; // 1 hour if (time() - $_SESSION['logged_in_at'] > $maxAge) { session_destroy(); return false; } return true; }
Secure logout
php<?php function logout(): void { // Clear session data $_SESSION = []; // Delete session cookie if (ini_get('session.use_cookies')) { $params = session_get_cookie_params(); setcookie( session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly'] ); } // Destroy session session_destroy(); }
Remember me tokens
php<?php function createRememberToken(int $userId): string { $selector = bin2hex(random_bytes(16)); $validator = bin2hex(random_bytes(32)); $hashedValidator = hash('sha256', $validator); // Store selector + hashed validator in database $stmt = $pdo->prepare( 'INSERT INTO remember_tokens (user_id, selector, hashed_validator, expires_at) VALUES (:user_id, :selector, :hashed_validator, :expires_at)' ); $stmt->execute([ 'user_id' => $userId, 'selector' => $selector, 'hashed_validator' => $hashedValidator, 'expires_at' => date('Y-m-d H:i:s', time() + 86400 * 30), ]); // Return selector:validator to set in cookie return $selector . ':' . $validator; }
Common Pitfalls
- Forgetting to regenerate session ID after login — Without
session_regenerate_id(true), an attacker who set the session ID before login can hijack the authenticated session. - Storing sensitive data in sessions without encryption — Session files on shared hosting can be readable by other users. Encrypt sensitive session data or use a private session handler.
Best Practices
- Call
session_regenerate_id(true)after every privilege change — Login, logout, password change, and role elevation should all trigger session ID regeneration. - Configure strict session settings — Set
session.cookie_httponly=1,session.cookie_secure=1,session.use_strict_mode=1, andsession.cookie_samesite=Lax.
Summary
- Prevent session fixation by calling
session_regenerate_id(true)after every authentication state change. - Configure session cookies with
httponly,secure, andsamesiteflags. - Use strict session mode and set appropriate session lifetime limits.