"""
Browser Storage Security Analyzer
Uses Selenium to analyze client-side storage
"""
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import json
import time
class BrowserStorageTester:
def __init__(self, url):
self.url = url
self.findings = []
self.setup_browser()
def setup_browser(self):
"""Setup headless Chrome"""
options = Options()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
self.driver = webdriver.Chrome(options=options)
def analyze_storage(self):
"""Analyze all browser storage"""
print(f"[*] Analyzing storage for {self.url}")
self.driver.get(self.url)
time.sleep(3)
local_storage = self.driver.execute_script("""
let items = {};
for (let i = 0; i < localStorage.length; i++) {
let key = localStorage.key(i);
items[key] = localStorage.getItem(key);
}
return items;
""")
session_storage = self.driver.execute_script("""
let items = {};
for (let i = 0; i < sessionStorage.length; i++) {
let key = sessionStorage.key(i);
items[key] = sessionStorage.getItem(key);
}
return items;
""")
cookies = self.driver.get_cookies()
return {
'localStorage': local_storage,
'sessionStorage': session_storage,
'cookies': cookies
}
def check_sensitive_data(self, storage_data):
"""Check for sensitive data patterns"""
print("\n[*] Checking for sensitive data...")
sensitive_patterns = [
('password', 'Password'),
('token', 'Authentication Token'),
('api_key', 'API Key'),
('apikey', 'API Key'),
('secret', 'Secret'),
('credit', 'Credit Card'),
('ssn', 'Social Security'),
('session', 'Session Data'),
('auth', 'Authentication Data'),
('bearer', 'Bearer Token'),
('jwt', 'JWT Token'),
('private', 'Private Data'),
]
for key, value in storage_data.get('localStorage', {}).items():
for pattern, description in sensitive_patterns:
if pattern.lower() in key.lower() or pattern.lower() in str(value).lower():
print(f"[VULN] Sensitive data in localStorage: {key}")
self.findings.append({
"location": "localStorage",
"key": key,
"issue": f"Potential {description} exposed",
"severity": "High"
})
for key, value in storage_data.get('sessionStorage', {}).items():
for pattern, description in sensitive_patterns:
if pattern.lower() in key.lower() or pattern.lower() in str(value).lower():
print(f"[WARN] Sensitive data in sessionStorage: {key}")
self.findings.append({
"location": "sessionStorage",
"key": key,
"issue": f"Potential {description} exposed",
"severity": "Medium"
})
for cookie in storage_data.get('cookies', []):
name = cookie.get('name', '')
for pattern, description in sensitive_patterns:
if pattern.lower() in name.lower():
if not cookie.get('httpOnly'):
print(f"[VULN] Sensitive cookie without HttpOnly: {name}")
self.findings.append({
"location": "cookie",
"key": name,
"issue": f"{description} cookie without HttpOnly",
"severity": "High"
})
if not cookie.get('secure'):
print(f"[VULN] Sensitive cookie without Secure: {name}")
self.findings.append({
"location": "cookie",
"key": name,
"issue": f"{description} cookie without Secure flag",
"severity": "Medium"
})
def check_cookie_attributes(self, storage_data):
"""Check cookie security attributes"""
print("\n[*] Checking cookie attributes...")
for cookie in storage_data.get('cookies', []):
name = cookie.get('name', '')
issues = []
if not cookie.get('httpOnly'):
issues.append("Missing HttpOnly")
if not cookie.get('secure'):
issues.append("Missing Secure")
if cookie.get('sameSite', '').lower() not in ['strict', 'lax']:
issues.append("Missing/Weak SameSite")
if issues:
print(f"[WARN] Cookie '{name}': {', '.join(issues)}")
for issue in issues:
self.findings.append({
"location": "cookie",
"key": name,
"issue": issue,
"severity": "Medium" if "HttpOnly" in issue else "Low"
})
def test_xss_access(self):
"""Test if XSS could access storage"""
print("\n[*] Testing XSS accessibility to storage...")
result = self.driver.execute_script("""
let accessible = {
localStorage: false,
sessionStorage: false,
cookies: false
};
try {
localStorage.setItem('xss_test', 'test');
localStorage.removeItem('xss_test');
accessible.localStorage = true;
} catch(e) {}
try {
sessionStorage.setItem('xss_test', 'test');
sessionStorage.removeItem('xss_test');
accessible.sessionStorage = true;
} catch(e) {}
try {
accessible.cookies = document.cookie.length > 0 || true;
} catch(e) {}
return accessible;
""")
print(f" localStorage accessible via JS: {result.get('localStorage')}")
print(f" sessionStorage accessible via JS: {result.get('sessionStorage')}")
print(f" Cookies accessible via JS: {result.get('cookies')}")
return result
def generate_report(self):
"""Generate security report"""
print("\n" + "="*50)
print("BROWSER STORAGE SECURITY REPORT")
print("="*50)
if not self.findings:
print("\nNo significant issues found.")
else:
high = [f for f in self.findings if f['severity'] == 'High']
medium = [f for f in self.findings if f['severity'] == 'Medium']
low = [f for f in self.findings if f['severity'] == 'Low']
if high:
print(f"\n[HIGH SEVERITY] ({len(high)} issues)")
for f in high:
print(f" - {f['location']}/{f['key']}: {f['issue']}")
if medium:
print(f"\n[MEDIUM SEVERITY] ({len(medium)} issues)")
for f in medium:
print(f" - {f['location']}/{f['key']}: {f['issue']}")
if low:
print(f"\n[LOW SEVERITY] ({len(low)} issues)")
for f in low:
print(f" - {f['location']}/{f['key']}: {f['issue']}")
def run_tests(self):
"""Run all tests"""
try:
storage_data = self.analyze_storage()
print("\n[*] Storage Contents:")
print(f" localStorage entries: {len(storage_data.get('localStorage', {}))}")
print(f" sessionStorage entries: {len(storage_data.get('sessionStorage', {}))}")
print(f" Cookies: {len(storage_data.get('cookies', []))}")
self.check_sensitive_data(storage_data)
self.check_cookie_attributes(storage_data)
self.test_xss_access()
self.generate_report()
finally:
self.driver.quit()
tester = BrowserStorageTester("https://target.com")
tester.run_tests()
class SecureStorage {
constructor(encryptionKey) {
this.key = encryptionKey;
}
async encrypt(data) {
const encoder = new TextEncoder();
const encodedData = encoder.encode(JSON.stringify(data));
const cryptoKey = await crypto.subtle.importKey(
'raw',
encoder.encode(this.key),
{ name: 'AES-GCM' },
false,
['encrypt']
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
cryptoKey,
encodedData
);
return {
iv: Array.from(iv),
data: Array.from(new Uint8Array(encrypted))
};
}
async setItem(key, value) {
const encrypted = await this.encrypt(value);
sessionStorage.setItem(key, JSON.stringify(encrypted));
}
}
from flask import make_response
@app.route('/login', methods=['POST'])
def login():
response = make_response(redirect('/dashboard'))
response.set_cookie(
'session_id',
value=generate_session_id(),
secure=True, # HTTPS only
httponly=True, # No JavaScript access
samesite='Strict', # No cross-site requests
max_age=3600, # 1 hour expiry
path='/',
domain='.example.com'
)
return response
function secureLogout() {
localStorage.clear();
sessionStorage.clear();
indexedDB.databases().then(dbs => {
dbs.forEach(db => indexedDB.deleteDatabase(db.name));
});
document.cookie.split(';').forEach(cookie => {
const name = cookie.split('=')[0].trim();
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
});
window.location.href = '/login';
}