Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Testing for Browser Cache Weaknesses
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 158% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 67% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 461% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 146% | 0% |
WSTG-ATHN-06
Testing for Browser Cache Weaknesses
Browser cache weakness testing examines whether sensitive authentication and user data can be retrieved from browser cache, history, or back button functionality. Improper cache control headers may allow sensitive pages to be cached, enabling attackers to access private information from shared or public computers.
| Location | Risk | | ----------------- | ----------------------- | | Browser cache | Offline access to pages | | Browser history | URL disclosure | | Form autocomplete | Credential exposure | | Back button | Post-logout access |
bash# Check headers on sensitive pages pages=( "/login" "/dashboard" "/account" "/profile" "/api/user" "/settings" ) for page in "${pages[@]}"; do echo "=== $page ===" curl -sI "https://target.com$page" \ -H "Authorization: Bearer $TOKEN" | \ grep -iE "cache-control|pragma|expires|vary" echo "" done # Expected headers for sensitive pages: # Cache-Control: no-store, no-cache, must-revalidate # Pragma: no-cache # Expires: 0
bash# This requires browser testing, but we can check server behavior # 1. Login and access sensitive page session=$(curl -s -c - "https://target.com/login" \ -X POST \ -d "username=test&password=test" | grep session | awk '{print $7}') # 2. Access dashboard curl -s "https://target.com/dashboard" \ -H "Cookie: session=$session" > dashboard_content.html # 3. Logout curl -s "https://target.com/logout" \ -H "Cookie: session=$session" # 4. Check if cached version returns with same session # (This simulates back button) curl -s "https://target.com/dashboard" \ -H "Cookie: session=$session" \ -H "Cache-Control: max-age=0" \ -w "\nStatus: %{http_code}" # Should return 401/302 to login, not cached content
bash# Check login form for autocomplete settings curl -s "https://target.com/login" | \ grep -iE "autocomplete|password|username" | \ head -20 # Check for password fields without autocomplete="off" curl -s "https://target.com/login" | \ grep -i "type=.password" | \ grep -v "autocomplete" # Check registration form curl -s "https://target.com/register" | \ grep -iE "autocomplete|password"
bash#!/bin/bash # Test if pages are being cached TARGET="https://target.com" TOKEN="your_token" # Make request and check for caching headers echo "Testing cache headers..." # Sensitive endpoints endpoints=("/dashboard" "/account" "/api/me" "/settings") for endpoint in "${endpoints[@]}"; do echo "=== $endpoint ===" response=$(curl -sI "$TARGET$endpoint" \ -H "Authorization: Bearer $TOKEN") # Check Cache-Control cache_control=$(echo "$response" | grep -i "cache-control") if [ -z "$cache_control" ]; then echo " [VULN] No Cache-Control header" elif echo "$cache_control" | grep -qi "no-store\|no-cache"; then echo " [OK] Proper caching disabled: $cache_control" else echo " [WARN] Cache-Control may allow caching: $cache_control" fi # Check Pragma pragma=$(echo "$response" | grep -i "pragma") if [ -z "$pragma" ]; then echo " [INFO] No Pragma header (optional for HTTP/1.1)" fi # Check Expires expires=$(echo "$response" | grep -i "expires") if echo "$expires" | grep -qi "0\|-1\|Thu, 01 Jan 1970"; then echo " [OK] Expires set to past" fi echo "" done
bash# Check for conditional request headers that might reveal info curl -sI "https://target.com/dashboard" \ -H "Authorization: Bearer $TOKEN" | \ grep -iE "etag|last-modified" # If ETag contains user-specific info, it could be a privacy issue # Make same request with different user and compare ETags
html<!-- This test is performed manually in browser --> <!-- Check if browser offers to save password --> <!-- 1. Open login page --> <!-- 2. Enter credentials --> <!-- 3. Check if browser prompts to save password --> <!-- 4. Check if saved credentials appear in browser settings --> <!-- Server should return: --> <!-- - autocomplete="off" on login form --> <!-- - autocomplete="new-password" on password reset forms --> <!-- - Cache-Control: no-store -->
bash# Check if HTTPS responses include caching headers # Some browsers don't cache HTTPS by default, but explicit headers are safer curl -sI "https://target.com/sensitive-page" \ -H "Authorization: Bearer $TOKEN" \ -o headers.txt # Analyze headers if grep -qi "cache-control.*public\|cache-control.*max-age=[1-9]" headers.txt; then echo "[VULN] Sensitive page may be cached" fi if ! grep -qi "cache-control" headers.txt; then echo "[VULN] No Cache-Control header on sensitive page" fi
| Tool | Description | Usage | | -------------------- | ----------- | ---------------------- | | curl | HTTP client | Check headers | | Browser DevTools | Network tab | Inspect cache behavior | | Burp Suite | Proxy | Analyze responses |
| Tool | Description | | -------------------------- | ------------------------- | | Browser cache viewer | Inspect cached content | | Private/Incognito mode | Test clean cache behavior |
python#!/usr/bin/env python3 import requests class CacheAnalyzer: def __init__(self, base_url, token=None): self.base_url = base_url self.headers = {} if token: self.headers["Authorization"] = f"Bearer {token}" self.results = [] def analyze_endpoint(self, endpoint): """Analyze caching headers for an endpoint""" try: response = requests.get( f"{self.base_url}{endpoint}", headers=self.headers ) result = { "endpoint": endpoint, "status": response.status_code, "issues": [] } headers = response.headers # Check Cache-Control cache_control = headers.get("Cache-Control", "") if not cache_control: result["issues"].append("Missing Cache-Control header") else: if "no-store" not in cache_control.lower(): result["issues"].append(f"Cache-Control may allow caching: {cache_control}") if "private" not in cache_control.lower() and "no-store" not in cache_control.lower(): result["issues"].append("Cache-Control should include 'private' or 'no-store'") # Check Pragma pragma = headers.get("Pragma", "") if "no-cache" not in pragma.lower() and not cache_control: result["issues"].append("Missing Pragma: no-cache (useful for HTTP/1.0)") # Check Expires expires = headers.get("Expires", "") if expires and "0" not in expires and "1970" not in expires: result["issues"].append(f"Expires header may allow caching: {expires}") # Check for ETag with potentially sensitive data etag = headers.get("ETag", "") if etag and len(etag) > 50: result["issues"].append("Long ETag may contain sensitive information") result["cache_control"] = cache_control result["vulnerable"] = len(result["issues"]) > 0 self.results.append(result) return result except Exception as e: return {"endpoint": endpoint, "error": str(e)} def analyze_form(self, endpoint): """Analyze form for autocomplete settings""" try: response = requests.get( f"{self.base_url}{endpoint}", headers=self.headers ) issues = [] # Check for password fields without autocomplete="off" if 'type="password"' in response.text or "type='password'" in response.text: if 'autocomplete="off"' not in response.text and 'autocomplete="new-password"' not in response.text: issues.append("Password field without autocomplete='off'") # Check form-level autocomplete if '<form' in response.text: if 'autocomplete="off"' not in response.text: issues.append("Form without autocomplete='off'") return { "endpoint": endpoint, "form_issues": issues, "vulnerable": len(issues) > 0 } except Exception as e: return {"endpoint": endpoint, "error": str(e)} def generate_report(self): """Generate analysis report""" print("\n=== BROWSER CACHE SECURITY REPORT ===\n") vulnerable = [r for r in self.results if r.get("vulnerable")] print(f"Endpoints analyzed: {len(self.results)}") print(f"Vulnerable endpoints: {len(vulnerable)}\n") for result in self.results: status = "[VULN]" if result.get("vulnerable") else "[OK]" print(f"{status} {result['endpoint']}") if result.get("issues"): for issue in result["issues"]: print(f" - {issue}") print(f" Cache-Control: {result.get('cache_control', 'Not set')}") print() # Usage analyzer = CacheAnalyzer("https://target.com", "your_token") analyzer.analyze_endpoint("/dashboard") analyzer.analyze_endpoint("/account") analyzer.analyze_endpoint("/api/user") analyzer.analyze_form("/login") analyzer.generate_report()
pythonfrom flask import Flask, make_response @app.after_request def add_cache_headers(response): """Add security headers to prevent caching of sensitive pages""" # For all authenticated pages if is_authenticated_request(): response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' response.headers['Pragma'] = 'no-cache' response.headers['Expires'] = '0' return response # Or for specific routes @app.route('/dashboard') @login_required def dashboard(): response = make_response(render_template('dashboard.html')) response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' response.headers['Pragma'] = 'no-cache' response.headers['Expires'] = '0' return response
nginx# Nginx - Disable caching for sensitive locations location /dashboard { add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0" always; add_header Pragma "no-cache" always; add_header Expires "0" always; # Your location config } # For all authenticated areas location /api/ { add_header Cache-Control "private, no-store, no-cache, must-revalidate" always; add_header Pragma "no-cache" always; }
apache# Apache - Disable caching for sensitive pages <Location /dashboard> Header always set Cache-Control "no-store, no-cache, must-revalidate, max-age=0" Header always set Pragma "no-cache" Header always set Expires "0" </Location>
html<!-- Login form --> <form method="POST" action="/login" autocomplete="off"> <input type="text" name="username" autocomplete="off" /> <input type="password" name="password" autocomplete="off" /> <button type="submit">Login</button> </form> <!-- Password change form --> <form method="POST" action="/change-password" autocomplete="off"> <input type="password" name="current_password" autocomplete="current-password" /> <input type="password" name="new_password" autocomplete="new-password" /> <input type="password" name="confirm_password" autocomplete="new-password" /> <button type="submit">Change Password</button> </form>
javascript// Client-side: Clear sensitive data on logout function logout() { // Clear any cached data if (window.sessionStorage) { sessionStorage.clear() } if (window.localStorage) { // Clear sensitive items localStorage.removeItem("user_data") localStorage.removeItem("auth_token") } // Redirect to login with cache bypass window.location.replace("/login?logout=1") // Prevent back button history.pushState(null, null, "/login") window.addEventListener("popstate", function () { history.pushState(null, null, "/login") }) }
python# Server-side: Clear session and send no-cache headers @app.route('/logout') def logout(): # Clear session session.clear() response = make_response(redirect('/login')) # Clear session cookie response.delete_cookie('session') # Prevent caching of logout redirect response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate' response.headers['Clear-Site-Data'] = '"cache", "storage"' return response
| Finding | CVSS | Severity | | ---------------------------------------- | ---- | -------- | | Cached credentials accessible | 6.5 | Medium | | Back button shows sensitive data | 5.3 | Medium | | Missing Cache-Control on sensitive pages | 4.3 | Medium | | Autocomplete enabled on password fields | 3.7 | Low |
| CWE ID | Title | Description | | ----------- | --------------------------------------------------------- | --------------------- | | CWE-525 | Use of Web Browser Cache Containing Sensitive Information | Cached sensitive data | | CWE-524 | Use of Cache Containing Sensitive Information | General cache issue | | CWE-200 | Exposure of Sensitive Information | Data disclosure |
[ ] Cache-Control headers checked on sensitive pages
[ ] Pragma header checked
[ ] Expires header checked
[ ] Back button behavior tested
[ ] Logout cache behavior tested
[ ] Form autocomplete settings checked
[ ] Password field autocomplete disabled
[ ] Browser history exposure tested
[ ] ETag information disclosure checked
[ ] Clear-Site-Data header considered
[ ] Findings documented
[ ] Remediation recommendations providedOther measured skills in the registry, with their headline benchmark lift.