SecurityJanuary 1, 2024ยท 18 min read
Cookie Security: Protect Sessions, Prevent Hijacking, and Ensure Privacy
A practical Fusebox guide to cookie security.
Cookie Security: Protect Sessions, Prevent Hijacking, and Ensure Privacy
Published: January 2024
Reading time: 9 minutes
Cookies are the backbone of web authentication, yet most sites leave them vulnerable to theft, manipulation, and tracking. Here's how to analyze cookie security, implement bulletproof session management, and protect user privacy.
Why Cookie Security Matters
The Cookie Attack Landscape
- Session hijacking affects 1 in 10 sites
- XSS cookie theft is the #2 web attack
- CSRF attacks exploit poor cookie config
- Privacy violations from tracking cookies
- $4.2 billion lost to session attacks annually
Real-World Cookie Breaches
Facebook (2018): Access tokens in cookies exposed
GitHub (2020): Session fixation via cookie manipulation
Zoom (2020): Cookie bombing denial of service
TikTok (2022): Session cookies leaked via subdomain
PayPal (2023): CSRF via missing SameSite attribute
Quick Cookie Security Analysis
1. Current Site Cookie Audit
// Analyze all cookies on current page
(function auditCookies() {
console.log('๐ช Cookie Security Audit\n');
// Parse all cookies
const cookies = document.cookie.split(';').map(c => {
const [name, value] = c.trim().split('=');
return { name, value, raw: c.trim() };
}).filter(c => c.name);
console.log(`Total cookies: ${cookies.length}\n`);
if (cookies.length === 0) {
console.log('No cookies found on this domain');
return;
}
// Analyze each cookie
console.log('๐ Cookie Analysis:\n');
cookies.forEach((cookie, index) => {
console.log(`${index + 1}. ${cookie.name}`);
// Check for security indicators
const security = {
httpOnly: 'โ Not HttpOnly (accessible via JS)',
secure: location.protocol === 'https:' ? 'โ ๏ธ Cannot verify (check server response)' : 'โ Not Secure flag',
sameSite: 'โ ๏ธ Cannot verify (check server response)',
size: cookie.raw.length,
encoding: cookie.value.includes('%') ? 'URL encoded' : 'Plain text'
};
// Value analysis
const valueAnalysis = analyzeValue(cookie.value);
console.log(` Value: ${cookie.value.substring(0, 20)}${cookie.value.length > 20 ? '...' : ''}`);
console.log(` Size: ${security.size} bytes`);
console.log(` Type: ${valueAnalysis.type}`);
console.log(` ${security.httpOnly}`);
console.log(` ${security.secure}`);
// Security warnings
if (valueAnalysis.warnings.length > 0) {
console.log(' โ ๏ธ Warnings:');
valueAnalysis.warnings.forEach(w => console.log(` - ${w}`));
}
console.log('');
});
// Check for sensitive data
checkSensitiveData(cookies);
// Cookie count by purpose
categorizeCookies(cookies);
function analyzeValue(value) {
const analysis = {
type: 'Unknown',
warnings: []
};
// JWT detection
if (value.match(/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$/)) {
analysis.type = 'JWT Token';
analysis.warnings.push('JWT in cookie (consider localStorage for tokens)');
}
// Session ID pattern
else if (value.match(/^[a-f0-9]{32,}$/i) || value.match(/^[A-Za-z0-9]{20,}$/)) {
analysis.type = 'Session ID';
}
// Base64
else if (value.match(/^[A-Za-z0-9+/]+=*$/)) {
analysis.type = 'Base64 encoded';
try {
const decoded = atob(value);
if (decoded.includes('@') || decoded.includes('user')) {
analysis.warnings.push('May contain user data');
}
} catch (e) {}
}
// Tracking ID
else if (value.match(/^(UA-|GTM-|G-|_ga|_fb)/)) {
analysis.type = 'Analytics/Tracking';
}
return analysis;
}
function checkSensitiveData(cookies) {
console.log('๐ Sensitive Data Check:\n');
const sensitivePatterns = {
email: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/,
creditCard: /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/,
ssn: /\b\d{3}-\d{2}-\d{4}\b/,
apiKey: /(api[_-]?key|apikey)/i,
password: /(pass|pwd|password)/i,
token: /(token|auth|session)/i
};
let found = false;
cookies.forEach(cookie => {
Object.entries(sensitivePatterns).forEach(([type, pattern]) => {
if (pattern.test(cookie.value) || pattern.test(cookie.name)) {
console.log(`โ ๏ธ Possible ${type} in cookie: ${cookie.name}`);
found = true;
}
});
});
if (!found) {
console.log('โ
No obvious sensitive data in cookies');
}
console.log('');
}
function categorizeCookies(cookies) {
console.log('๐ Cookie Categories:\n');
const categories = {
session: 0,
analytics: 0,
functional: 0,
advertising: 0,
unknown: 0
};
cookies.forEach(cookie => {
if (/session|sess|sid|auth/i.test(cookie.name)) {
categories.session++;
} else if (/_ga|_gid|utm_|analytics/i.test(cookie.name)) {
categories.analytics++;
} else if (/pref|lang|theme|settings/i.test(cookie.name)) {
categories.functional++;
} else if (/_fb|doubleclick|adsense/i.test(cookie.name)) {
categories.advertising++;
} else {
categories.unknown++;
}
});
Object.entries(categories).forEach(([cat, count]) => {
if (count > 0) {
console.log(`${cat}: ${count} cookie(s)`);
}
});
}
})();
2. Cookie Security Flags Analyzer
// Analyze cookie security configurations
function analyzeCookieFlags() {
console.log('\n๐ก๏ธ Cookie Security Flags Guide\n');
const securityFlags = {
'HttpOnly': {
purpose: 'Prevents JavaScript access',
protects: 'XSS attacks cannot steal cookie',
when: 'Always for session cookies',
example: 'Set-Cookie: sessionId=abc123; HttpOnly',
impact: '๐ก๏ธ Critical for session security'
},
'Secure': {
purpose: 'Cookie only sent over HTTPS',
protects: 'Man-in-the-middle attacks',
when: 'Always on production sites',
example: 'Set-Cookie: sessionId=abc123; Secure',
impact: '๐ Prevents cookie interception'
},
'SameSite': {
purpose: 'Controls cross-site cookie sending',
protects: 'CSRF attacks',
when: 'Use Strict or Lax for sessions',
example: 'Set-Cookie: sessionId=abc123; SameSite=Strict',
impact: '๐ซ Blocks CSRF attacks',
options: {
'Strict': 'Never sent cross-site (most secure)',
'Lax': 'Sent with top-level navigation',
'None': 'Always sent (requires Secure flag)'
}
},
'Path': {
purpose: 'Restricts cookie to URL path',
protects: 'Limits cookie scope',
when: 'When cookie needed only in subfolder',
example: 'Set-Cookie: adminSession=xyz; Path=/admin',
impact: '๐ Reduces attack surface'
},
'Domain': {
purpose: 'Controls which domains receive cookie',
protects: 'Subdomain takeover',
when: 'Be specific, avoid wildcards',
example: 'Set-Cookie: session=abc; Domain=example.com',
impact: '๐ Prevents subdomain access'
},
'Max-Age/Expires': {
purpose: 'Controls cookie lifetime',
protects: 'Limits exposure window',
when: 'Set short for sessions, longer for preferences',
example: 'Set-Cookie: session=abc; Max-Age=3600',
impact: 'โฐ Reduces persistent threats'
}
};
console.log('Cookie Security Flags Explained:\n');
Object.entries(securityFlags).forEach(([flag, details]) => {
console.log(`๐ ${flag}`);
console.log(` Purpose: ${details.purpose}`);
console.log(` Protects: ${details.protects}`);
console.log(` When to use: ${details.when}`);
console.log(` Example: ${details.example}`);
console.log(` ${details.impact}`);
if (details.options) {
console.log(' Options:');
Object.entries(details.options).forEach(([opt, desc]) => {
console.log(` โข ${opt}: ${desc}`);
});
}
console.log('');
});
// Best practices by cookie type
console.log('๐ฏ Recommended Configurations:\n');
const recommendations = {
'Session Cookie': 'HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600',
'CSRF Token': 'Secure; SameSite=Strict; Path=/',
'User Preferences': 'Secure; SameSite=Lax; Max-Age=2592000',
'Analytics': 'Secure; SameSite=Lax; Max-Age=63072000',
'Remember Me': 'HttpOnly; Secure; SameSite=Lax; Max-Age=1209600'
};
Object.entries(recommendations).forEach(([type, flags]) => {
console.log(`${type}:`);
console.log(` ${flags}\n`);
});
}
analyzeCookieFlags();
3. Session Security Analyzer
// Analyze session management security
function analyzeSessionSecurity() {
console.log('\n๐ Session Security Analysis\n');
// Check for session-related cookies
const sessionCookies = document.cookie.split(';')
.map(c => c.trim())
.filter(c => /session|sess|sid|auth|token/i.test(c));
console.log(`Found ${sessionCookies.length} potential session cookies\n`);
// Session security checks
const securityChecks = {
'Session Fixation': {
check: () => {
// Check if session ID in URL
const urlHasSession = /[?&](session|sid|auth)=/i.test(location.search);
return !urlHasSession;
},
description: 'Session ID not in URL',
vulnerability: 'Attacker can set victim\'s session ID'
},
'Secure Transport': {
check: () => location.protocol === 'https:',
description: 'Using HTTPS for session',
vulnerability: 'Session hijacking via network sniffing'
},
'Session Randomness': {
check: () => {
if (sessionCookies.length === 0) return null;
// Check for weak patterns
const weakPatterns = /^(123|abc|test|admin|user)/i;
return !sessionCookies.some(c => weakPatterns.test(c));
},
description: 'Session ID appears random',
vulnerability: 'Predictable sessions can be guessed'
},
'Client Storage': {
check: () => {
const hasLocalAuth = localStorage.getItem('token') ||
localStorage.getItem('auth') ||
sessionStorage.getItem('token');
return !hasLocalAuth;
},
description: 'No auth tokens in localStorage',
vulnerability: 'XSS can steal localStorage tokens'
},
'Cookie Scope': {
check: () => {
// Can't fully check from JS, but look for indicators
return sessionCookies.length > 0 &&
!document.cookie.includes('Domain=.');
},
description: 'Cookies scoped appropriately',
vulnerability: 'Wide domain scope exposes to subdomains'
}
};
console.log('๐ Security Checks:\n');
let score = 0;
const total = Object.keys(securityChecks).length;
Object.entries(securityChecks).forEach(([check, details]) => {
const result = details.check();
if (result === null) {
console.log(`โช ${check}: Cannot determine`);
} else if (result) {
console.log(`โ
${check}: ${details.description}`);
score++;
} else {
console.log(`โ ${check}: Failed`);
console.log(` Risk: ${details.vulnerability}`);
}
});
const percentage = Math.round((score / total) * 100);
console.log(`\n๐ Session Security Score: ${score}/${total} (${percentage}%)`);
// Session best practices
console.log('\n๐ก Session Security Best Practices:\n');
const bestPractices = [
'Regenerate session ID on login',
'Implement absolute timeout (e.g., 24 hours)',
'Implement idle timeout (e.g., 30 minutes)',
'Bind session to IP/User-Agent (carefully)',
'Use secure session storage (Redis, not files)',
'Implement concurrent session limits',
'Clear session on logout (client & server)',
'Monitor for session anomalies'
];
bestPractices.forEach((practice, index) => {
console.log(`${index + 1}. ${practice}`);
});
}
analyzeSessionSecurity();
Advanced Cookie Security
1. CSRF Protection Implementation
// Implement CSRF protection strategies
function implementCSRFProtection() {
console.log('\n๐ก๏ธ CSRF Protection Implementation\n');
const csrfStrategies = {
'Double Submit Cookie': {
description: 'CSRF token in cookie and request',
implementation: `
// Server sets CSRF cookie
Set-Cookie: csrf_token=random_value; Secure; SameSite=Strict
// Client includes in requests
fetch('/api/action', {
method: 'POST',
headers: {
'X-CSRF-Token': getCookie('csrf_token')
},
body: data
})
// Server validates
if (req.cookies.csrf_token !== req.headers['x-csrf-token']) {
return res.status(403).json({ error: 'CSRF token mismatch' });
}`,
pros: ['Stateless', 'Easy to implement'],
cons: ['Vulnerable if subdomain compromised']
},
'Synchronizer Token': {
description: 'Server-generated token in session',
implementation: `
// Server generates and stores token
req.session.csrfToken = generateSecureToken();
// Include in forms
<form method="POST">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
</form>
// Or in meta tag for AJAX
<meta name="csrf-token" content="<%= csrfToken %>">
// Validate on server
if (req.body._csrf !== req.session.csrfToken) {
return res.status(403).json({ error: 'Invalid CSRF token' });
}`,
pros: ['More secure', 'Token not in cookie'],
cons: ['Requires session state']
},
'SameSite Cookie': {
description: 'Modern CSRF protection via cookie attribute',
implementation: `
// Set SameSite attribute
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Strict
// For APIs that need cross-site access
Set-Cookie: api_session=xyz789; Secure; HttpOnly; SameSite=Lax
// For payments/OAuth that require None
Set-Cookie: payment_session=def456; Secure; HttpOnly; SameSite=None`,
pros: ['Simple', 'No token management'],
cons: ['Browser support', 'Breaks some legitimate use cases']
}
};
Object.entries(csrfStrategies).forEach(([strategy, details]) => {
console.log(`๐ ${strategy}`);
console.log(`Description: ${details.description}\n`);
console.log('Implementation:');
console.log(details.implementation);
console.log('\nPros:', details.pros.join(', '));
console.log('Cons:', details.cons.join(', '));
console.log('\n' + 'โ'.repeat(50) + '\n');
});
// CSRF testing
console.log('๐งช Testing CSRF Protection:\n');
console.log('// Test CSRF vulnerability');
console.log(`
// Create test form
const form = document.createElement('form');
form.method = 'POST';
form.action = '/api/sensitive-action';
// Try to submit without token
form.submit(); // Should fail with 403
// Test with token
const token = document.querySelector('meta[name="csrf-token"]')?.content;
if (token) {
const input = document.createElement('input');
input.type = 'hidden';
input.name = '_csrf';
input.value = token;
form.appendChild(input);
form.submit(); // Should succeed
}`);
}
implementCSRFProtection();
2. Secure Cookie Implementation
// Generate secure cookie implementations
function generateSecureCookieCode() {
console.log('\n๐ Secure Cookie Implementation\n');
const implementations = {
'Express.js': `
// Secure session configuration
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JS access
maxAge: 1000 * 60 * 60, // 1 hour
sameSite: 'strict' // CSRF protection
},
name: 'sessionId', // Don't use default name
genid: () => {
// Cryptographically secure ID
return require('crypto').randomBytes(32).toString('hex');
}
}));
// Set custom cookie with all flags
app.get('/set-secure-cookie', (req, res) => {
res.cookie('userPref', 'value', {
secure: true,
httpOnly: true,
sameSite: 'strict',
maxAge: 1000 * 60 * 60 * 24 * 7, // 1 week
signed: true // Tamper detection
});
res.send('Cookie set');
});`,
'Node.js (Native)': `
// Set secure cookie without framework
const crypto = require('crypto');
function setSecureCookie(res, name, value, options = {}) {
const defaults = {
httpOnly: true,
secure: true,
sameSite: 'Strict',
maxAge: 3600,
path: '/'
};
const settings = { ...defaults, ...options };
// Build cookie string
let cookie = \`\${name}=\${encodeURIComponent(value)}\`;
if (settings.httpOnly) cookie += '; HttpOnly';
if (settings.secure) cookie += '; Secure';
if (settings.sameSite) cookie += \`; SameSite=\${settings.sameSite}\`;
if (settings.maxAge) cookie += \`; Max-Age=\${settings.maxAge}\`;
if (settings.path) cookie += \`; Path=\${settings.path}\`;
if (settings.domain) cookie += \`; Domain=\${settings.domain}\`;
res.setHeader('Set-Cookie', cookie);
}
// Sign cookie for tamper detection
function signCookie(value, secret) {
const signature = crypto
.createHmac('sha256', secret)
.update(value)
.digest('base64')
.replace(/=+$/, '');
return \`\${value}.\${signature}\`;
}`,
'PHP': `
// Secure session configuration
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_samesite', 'Strict');
ini_set('session.use_only_cookies', 1);
ini_set('session.use_strict_mode', 1);
// Start secure session
session_set_cookie_params([
'lifetime' => 3600,
'path' => '/',
'domain' => '',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
session_start();
// Regenerate ID on login
function secure_login($user) {
session_regenerate_id(true);
$_SESSION['user'] = $user;
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT'];
}
// Set custom secure cookie
setcookie(
'preferences',
$value,
[
'expires' => time() + 86400,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax'
]
);`,
'Python (Flask)': `
from flask import Flask, make_response, session
from datetime import datetime, timedelta
import secrets
app = Flask(__name__)
app.secret_key = secrets.token_hex(32)
# Configure secure sessions
app.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Strict',
PERMANENT_SESSION_LIFETIME=timedelta(hours=1)
)
@app.route('/set-cookie')
def set_secure_cookie():
resp = make_response('Cookie set')
resp.set_cookie(
'user_pref',
value='preference_value',
max_age=3600,
secure=True,
httponly=True,
samesite='Strict'
)
return resp
# Custom session interface for added security
class SecureSessionInterface(Flask.session_interface):
def save_session(self, app, session, response):
# Add fingerprinting
session['_fingerprint'] = request.headers.get('User-Agent', '')
super().save_session(app, session, response)`
};
Object.entries(implementations).forEach(([platform, code]) => {
console.log(`๐ฆ ${platform}:`);
console.log('โ'.repeat(50));
console.log(code);
console.log('\n');
});
// Cookie security checklist
console.log('โ
Cookie Security Checklist:\n');
const checklist = [
'Use HTTPS everywhere (Secure flag)',
'Set HttpOnly for session cookies',
'Implement SameSite attribute',
'Use signed cookies for tamper detection',
'Set appropriate expiration times',
'Regenerate session IDs on privilege change',
'Clear cookies on logout',
'Implement secure session storage',
'Monitor for session anomalies',
'Use secure random generators'
];
checklist.forEach((item, index) => {
console.log(`${index + 1}. ${item}`);
});
}
generateSecureCookieCode();
3. Privacy-Focused Cookie Management
// Implement privacy-compliant cookie handling
function implementPrivacyCookies() {
console.log('\n๐ Privacy-Focused Cookie Management\n');
// GDPR/CCPA compliant cookie categories
const cookieCategories = {
necessary: {
description: 'Essential for site function',
examples: ['Session ID', 'CSRF token', 'Load balancer'],
consent: false,
implementation: `
// Always set necessary cookies
function setNecessaryCookie(name, value) {
document.cookie = \`\${name}=\${value}; Secure; HttpOnly; SameSite=Strict; Path=/\`;
}`
},
functional: {
description: 'Enhanced functionality',
examples: ['Language preference', 'Theme', 'Username'],
consent: true,
implementation: `
// Check consent before setting
function setFunctionalCookie(name, value) {
if (hasConsent('functional')) {
document.cookie = \`\${name}=\${value}; Secure; SameSite=Lax; Max-Age=2592000\`;
}
}`
},
analytics: {
description: 'Usage statistics',
examples: ['Google Analytics', 'Hotjar', 'Mixpanel'],
consent: true,
implementation: `
// Conditional analytics loading
function loadAnalytics() {
if (hasConsent('analytics')) {
// Load Google Analytics
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'GA_MEASUREMENT_ID', {
cookie_flags: 'secure;samesite=lax'
});
}
}`
},
advertising: {
description: 'Targeted advertising',
examples: ['DoubleClick', 'Facebook Pixel', 'AdSense'],
consent: true,
implementation: `
// Advertising with consent
function loadAdvertising() {
if (hasConsent('advertising')) {
// Load ad scripts
} else {
// Show non-personalized ads
window.adsbygoogle = window.adsbygoogle || [];
window.adsbygoogle.push({
google_ad_client: "ca-pub-xxx",
enable_page_level_ads: true,
tag_partner: "site_kit"
});
}
}`
}
};
console.log('Cookie Categories and Implementation:\n');
Object.entries(cookieCategories).forEach(([category, details]) => {
console.log(`๐ ${category.toUpperCase()}`);
console.log(` Description: ${details.description}`);
console.log(` Examples: ${details.examples.join(', ')}`);
console.log(` Requires Consent: ${details.consent ? 'Yes' : 'No'}`);
console.log(' Implementation:');
console.log(details.implementation);
console.log('');
});
// Consent management
console.log('๐ช Cookie Consent Implementation:\n');
const consentCode = `
// Cookie consent manager
class CookieConsent {
constructor() {
this.consent = this.loadConsent() || {
necessary: true,
functional: false,
analytics: false,
advertising: false
};
}
loadConsent() {
const stored = localStorage.getItem('cookieConsent');
return stored ? JSON.parse(stored) : null;
}
saveConsent(categories) {
this.consent = { ...this.consent, ...categories };
localStorage.setItem('cookieConsent', JSON.stringify(this.consent));
this.applyConsent();
}
applyConsent() {
// Remove non-consented cookies
if (!this.consent.analytics) {
this.deleteCookiesByPattern('_ga', '_gid', 'utm_');
}
if (!this.consent.advertising) {
this.deleteCookiesByPattern('_fb', 'doubleclick');
}
// Trigger consent change event
window.dispatchEvent(new CustomEvent('consentChanged', {
detail: this.consent
}));
}
deleteCookiesByPattern(...patterns) {
document.cookie.split(';').forEach(cookie => {
const name = cookie.split('=')[0].trim();
if (patterns.some(pattern => name.includes(pattern))) {
// Delete cookie
document.cookie = \`\${name}=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/\`;
// Try with domain
document.cookie = \`\${name}=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; domain=.\${location.hostname}\`;
}
});
}
hasConsent(category) {
return this.consent[category] === true;
}
}
// Initialize consent manager
const consent = new CookieConsent();`;
console.log(consentCode);
// Privacy regulations
console.log('\n๐ Privacy Regulation Requirements:\n');
const regulations = {
'GDPR (EU)': [
'Explicit consent before non-essential cookies',
'Granular control by category',
'Easy withdrawal of consent',
'Clear information about purpose',
'Data retention limits'
],
'CCPA (California)': [
'Right to opt-out of sale',
'Do Not Sell My Info link',
'Privacy policy updates',
'Data deletion rights'
],
'LGPD (Brazil)': [
'Similar to GDPR requirements',
'Portuguese language support',
'Local data representative'
]
};
Object.entries(regulations).forEach(([regulation, requirements]) => {
console.log(`${regulation}:`);
requirements.forEach(req => console.log(` โข ${req}`));
console.log('');
});
}
implementPrivacyCookies();
Cookie Security Testing
1. Vulnerability Scanner
// Scan for common cookie vulnerabilities
function scanCookieVulnerabilities() {
console.log('\n๐ Cookie Vulnerability Scanner\n');
const vulnerabilities = [];
// Test 1: HttpOnly flag
console.log('Testing HttpOnly flag...');
const hasAccessibleSession = document.cookie.split(';')
.some(c => /session|auth|token/i.test(c));
if (hasAccessibleSession) {
vulnerabilities.push({
severity: 'HIGH',
issue: 'Session cookie accessible via JavaScript',
impact: 'XSS can steal session',
fix: 'Add HttpOnly flag to session cookies'
});
}
// Test 2: Secure flag on HTTPS
console.log('Testing Secure flag...');
if (location.protocol === 'https:' && document.cookie.length > 0) {
vulnerabilities.push({
severity: 'MEDIUM',
issue: 'Cannot verify Secure flag from JavaScript',
impact: 'Cookies may be sent over HTTP',
fix: 'Ensure all cookies have Secure flag'
});
}
// Test 3: SameSite attribute
console.log('Testing SameSite protection...');
vulnerabilities.push({
severity: 'MEDIUM',
issue: 'Cannot verify SameSite from JavaScript',
impact: 'Potential CSRF vulnerability',
fix: 'Add SameSite=Strict or Lax to cookies'
});
// Test 4: Sensitive data in cookies
console.log('Testing for sensitive data...');
const sensitivePatterns = [
{ pattern: /password=/i, type: 'password' },
{ pattern: /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/, type: 'credit card' },
{ pattern: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/, type: 'email' }
];
const cookieString = document.cookie;
sensitivePatterns.forEach(({ pattern, type }) => {
if (pattern.test(cookieString)) {
vulnerabilities.push({
severity: 'CRITICAL',
issue: `Possible ${type} in cookies`,
impact: 'Sensitive data exposure',
fix: 'Never store sensitive data in cookies'
});
}
});
// Test 5: Cookie size
console.log('Testing cookie sizes...');
document.cookie.split(';').forEach(cookie => {
if (cookie.length > 4096) {
vulnerabilities.push({
severity: 'LOW',
issue: 'Cookie exceeds 4KB limit',
impact: 'Cookie may be truncated',
fix: 'Reduce cookie size or use server storage'
});
}
});
// Test 6: Domain scope
console.log('Testing domain scope...');
if (document.cookie.includes('Domain=.')) {
vulnerabilities.push({
severity: 'MEDIUM',
issue: 'Wildcard domain in cookies',
impact: 'Cookies shared with all subdomains',
fix: 'Use specific domain scope when possible'
});
}
// Display results
console.log(`\n๐จ Found ${vulnerabilities.length} potential issues:\n`);
const bySeverity = {
CRITICAL: vulnerabilities.filter(v => v.severity === 'CRITICAL'),
HIGH: vulnerabilities.filter(v => v.severity === 'HIGH'),
MEDIUM: vulnerabilities.filter(v => v.severity === 'MEDIUM'),
LOW: vulnerabilities.filter(v => v.severity === 'LOW')
};
Object.entries(bySeverity).forEach(([severity, issues]) => {
if (issues.length > 0) {
console.log(`${severity} (${issues.length}):`);
issues.forEach(issue => {
console.log(` โ ${issue.issue}`);
console.log(` Impact: ${issue.impact}`);
console.log(` Fix: ${issue.fix}\n`);
});
}
});
// Security score
const score = Math.max(0, 100 - (
bySeverity.CRITICAL.length * 30 +
bySeverity.HIGH.length * 20 +
bySeverity.MEDIUM.length * 10 +
bySeverity.LOW.length * 5
));
console.log(`๐ Cookie Security Score: ${score}/100`);
if (score >= 90) {
console.log('๐ข Excellent cookie security');
} else if (score >= 70) {
console.log('๐ก Good security with some improvements needed');
} else if (score >= 50) {
console.log('๐ Moderate security risks');
} else {
console.log('๐ด Critical security issues!');
}
}
scanCookieVulnerabilities();
2. Cookie Manipulation Test
// Test cookie manipulation and security
function testCookieManipulation() {
console.log('\n๐งช Cookie Manipulation Testing\n');
// Save original cookies
const originalCookies = document.cookie;
console.log('Testing cookie security boundaries...\n');
// Test 1: Try to set HttpOnly cookie (should fail)
console.log('1. Testing HttpOnly bypass:');
try {
document.cookie = 'test_httponly=value; HttpOnly';
if (document.cookie.includes('test_httponly')) {
console.log(' โ HttpOnly can be set from JS (browser bug)');
} else {
console.log(' โ
HttpOnly cannot be set from JS');
}
} catch (e) {
console.log(' โ
HttpOnly protected');
}
// Test 2: Path traversal
console.log('\n2. Testing path restrictions:');
document.cookie = 'path_test=root; Path=/';
document.cookie = 'path_test_admin=admin; Path=/admin';
console.log(' Set cookies with different paths');
console.log(' Current path cookies:', document.cookie.includes('path_test') ? 'Visible' : 'Not visible');
// Test 3: Subdomain scope
console.log('\n3. Testing domain scope:');
try {
document.cookie = `subdomain_test=value; Domain=.${location.hostname}`;
console.log(' โ ๏ธ Wildcard domain cookie set - shared with subdomains');
} catch (e) {
console.log(' Error setting domain cookie:', e.message);
}
// Test 4: Cookie injection
console.log('\n4. Testing cookie injection:');
const maliciousValue = '<script>alert("XSS")</script>';
document.cookie = `injection_test=${encodeURIComponent(maliciousValue)}`;
const injectedCookie = document.cookie.split(';')
.find(c => c.trim().startsWith('injection_test='));
if (injectedCookie) {
const value = decodeURIComponent(injectedCookie.split('=')[1]);
console.log(' Cookie set with payload:', value);
console.log(' โ ๏ธ Always encode/sanitize cookie values!');
}
// Test 5: Cookie bomb
console.log('\n5. Testing cookie bomb protection:');
let bombSize = 0;
try {
// Try to set many cookies
for (let i = 0; i < 50; i++) {
const cookie = `bomb_${i}=${'x'.repeat(100)}`;
document.cookie = cookie;
bombSize += cookie.length;
}
console.log(` Set ${bombSize} bytes of cookies`);
console.log(' โ ๏ธ Browser allows large cookie storage');
} catch (e) {
console.log(' โ
Browser prevents cookie bomb');
}
// Cleanup
console.log('\n๐งน Cleaning up test cookies...');
['test_httponly', 'path_test', 'path_test_admin', 'subdomain_test', 'injection_test']
.concat(Array.from({length: 50}, (_, i) => `bomb_${i}`))
.forEach(name => {
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/`;
});
console.log('Cleanup complete');
}
testCookieManipulation();
Complete Cookie Security Audit
Comprehensive Cookie and Session Audit
// Run complete cookie security audit
async function completeCookieAudit() {
console.log('๐ช COMPLETE COOKIE SECURITY AUDIT');
console.log('โ'.repeat(50));
console.log(`Domain: ${location.hostname}`);
console.log(`Protocol: ${location.protocol}`);
console.log(`Date: ${new Date().toLocaleDateString()}\n`);
const audit = {
cookies: [],
score: 0,
issues: [],
recommendations: []
};
// Phase 1: Cookie Inventory
console.log('๐ PHASE 1: COOKIE INVENTORY');
console.log('โ'.repeat(40));
const cookies = document.cookie.split(';')
.map(c => c.trim())
.filter(c => c)
.map(c => {
const [name, ...valueParts] = c.split('=');
return {
name: name.trim(),
value: valueParts.join('='),
size: c.length
};
});
audit.cookies = cookies;
console.log(`Total cookies: ${cookies.length}`);
// Categorize cookies
const categories = {
session: 0,
tracking: 0,
functional: 0,
unknown: 0
};
cookies.forEach(cookie => {
if (/session|sess|auth|token/i.test(cookie.name)) {
categories.session++;
} else if (/_ga|_fb|utm_/i.test(cookie.name)) {
categories.tracking++;
} else if (/pref|lang|theme/i.test(cookie.name)) {
categories.functional++;
} else {
categories.unknown++;
}
});
console.log('\nCategories:');
Object.entries(categories).forEach(([cat, count]) => {
console.log(` ${cat}: ${count}`);
});
// Phase 2: Security Analysis
console.log('\n๐ PHASE 2: SECURITY ANALYSIS');
console.log('โ'.repeat(40));
// Check for security issues
if (location.protocol !== 'https:') {
audit.issues.push('Not using HTTPS');
audit.score -= 30;
} else {
audit.score += 20;
}
// Session cookie checks
const sessionCookies = cookies.filter(c =>
/session|auth|token/i.test(c.name)
);
if (sessionCookies.length > 0) {
console.log(`\nSession cookies found: ${sessionCookies.length}`);
audit.issues.push('Session cookies accessible via JavaScript (missing HttpOnly)');
audit.recommendations.push('Add HttpOnly flag to all session cookies');
}
// Check for sensitive data
const sensitiveData = cookies.filter(c =>
/password|pwd|ssn|credit|cvv/i.test(c.name + c.value) ||
/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/.test(c.value)
);
if (sensitiveData.length > 0) {
console.log(`\nโ ๏ธ Potential sensitive data in ${sensitiveData.length} cookies`);
audit.issues.push('Sensitive data detected in cookies');
audit.score -= 20;
}
// Phase 3: Privacy Compliance
console.log('\n๐ PHASE 3: PRIVACY COMPLIANCE');
console.log('โ'.repeat(40));
const trackingCookies = cookies.filter(c =>
/_ga|_gid|_fb|doubleclick|adsense/i.test(c.name)
);
if (trackingCookies.length > 0) {
console.log(`Tracking cookies: ${trackingCookies.length}`);
// Check for consent
const hasConsentCookie = cookies.some(c =>
/consent|gdpr|privacy/i.test(c.name)
);
if (!hasConsentCookie) {
console.log('โ ๏ธ No consent cookie found');
audit.issues.push('Tracking cookies without consent mechanism');
audit.recommendations.push('Implement cookie consent banner');
}
}
// Phase 4: Best Practices
console.log('\nโ
PHASE 4: BEST PRACTICES');
console.log('โ'.repeat(40));
const checks = {
'HTTPS Only': location.protocol === 'https:',
'No sensitive data': sensitiveData.length === 0,
'Reasonable cookie count': cookies.length < 20,
'No oversized cookies': !cookies.some(c => c.size > 4096),
'Session security': sessionCookies.length === 0 || location.protocol === 'https:'
};
Object.entries(checks).forEach(([check, passed]) => {
console.log(`${passed ? 'โ
' : 'โ'} ${check}`);
if (passed) audit.score += 10;
});
// Phase 5: Recommendations
console.log('\n๐ก PHASE 5: RECOMMENDATIONS');
console.log('โ'.repeat(40));
// Security headers check
try {
const response = await fetch(location.href, { method: 'HEAD' });
const csp = response.headers.get('content-security-policy');
if (!csp || !csp.includes('upgrade-insecure-requests')) {
audit.recommendations.push('Add CSP with upgrade-insecure-requests');
}
} catch (e) {
console.log('Cannot check headers (CORS)');
}
// Generate recommendations
if (audit.cookies.length > 30) {
audit.recommendations.push('Reduce cookie count - consider server-side storage');
}
if (categories.tracking > categories.functional) {
audit.recommendations.push('More tracking than functional cookies - review necessity');
}
// Final Score
const finalScore = Math.max(0, Math.min(100, 50 + audit.score));
console.log('\n๐ FINAL SCORE');
console.log('โ'.repeat(50));
console.log(`Score: ${finalScore}/100`);
let grade = 'F';
if (finalScore >= 90) grade = 'A';
else if (finalScore >= 80) grade = 'B';
else if (finalScore >= 70) grade = 'C';
else if (finalScore >= 60) grade = 'D';
console.log(`Grade: ${grade}`);
console.log(`Critical Issues: ${audit.issues.length}`);
if (audit.issues.length > 0) {
console.log('\n๐จ Critical Issues:');
audit.issues.forEach((issue, i) => {
console.log(`${i + 1}. ${issue}`);
});
}
if (audit.recommendations.length > 0) {
console.log('\n๐ก Recommendations:');
audit.recommendations.forEach((rec, i) => {
console.log(`${i + 1}. ${rec}`);
});
}
// Summary advice
console.log('\n๐ SUMMARY');
console.log('โ'.repeat(40));
if (finalScore >= 80) {
console.log('Good cookie security! Focus on:');
console.log('โข Regular security audits');
console.log('โข Monitoring for new vulnerabilities');
} else if (finalScore >= 60) {
console.log('Moderate security. Priority fixes:');
console.log('โข Implement HTTPS if not already');
console.log('โข Add security flags to cookies');
console.log('โข Remove sensitive data from cookies');
} else {
console.log('Critical security issues! Immediate actions:');
console.log('โข Enable HTTPS everywhere');
console.log('โข Audit all cookie usage');
console.log('โข Implement proper session management');
}
return audit;
}
// Run the audit
completeCookieAudit();
The Bottom Line
Cookie security is fundamental to web application security:
- HttpOnly prevents XSS theft - JavaScript can't access session cookies
- Secure flag prevents interception - HTTPS-only transmission
- SameSite stops CSRF - Controls cross-site cookie sending
- Proper scoping limits exposure - Path and Domain restrictions
- Session management is critical - Regenerate IDs, implement timeouts
Implement all security flags. Use HTTPS everywhere. Monitor for vulnerabilities. Your users' sessions depend on proper cookie security.
Analyze cookie security instantly: Fusebox audits all cookies, detects security flags, identifies tracking, and monitors session security while you browse. Protect user privacy and prevent attacks. $29 one-time purchase.