Skip to content

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
Schutzmechanismen Glossary

HSTS - HTTP Strict Transport Security

HTTP Strict Transport Security (HSTS) is an HTTP response header that instructs browsers to access a domain exclusively via HTTPS. After the first HTTPS connection, all subsequent HTTP connections are redirected to HTTPS on the client side before they reach the server. This prevents SSL stripping attacks and stops users from accidentally establishing unencrypted connections. Important parameters: max-age, includeSubDomains, preload.

HTTP Strict Transport Security (HSTS) is a security mechanism implemented via the Strict-Transport-Security HTTP response header. It instructs browsers to access a domain exclusively via HTTPS in the future—even if the user enters http:// or follows an HTTP link. In this way, HSTS closes the security gap left open by traditional HTTPS redirects.

The Problem HSTS Solves

SSL Stripping without HSTS:

Normal HTTPS Redirect (vulnerable!):
  1. User types: http://bank.com (HTTP!)
  2. Bank server: 301 redirect → https://bank.com
  3. Browser: follows redirect → HTTPS connection

SSL stripping attack (MITM on the same network):
  1. User types: http://bank.com (HTTP!)
  2. Attacker (between user and bank, e.g., public Wi-Fi):
     → Intercepts the HTTP request
     → Establishes an HTTPS connection to bank.com themselves
     → Delivers the page to the user as HTTP (no padlock in the browser!)
  3. User sees: no padlock → thinks: "Okay, just HTTP"
  4. Attacker reads all data in plain text!
  → Problem: The initial HTTP request NEVER reaches the real server

With HSTS (protection after first visit):
  1. First visit (one-time via HTTPS):
     Response header: Strict-Transport-Security: max-age=31536000
     → Browser remembers: "bank.com = HTTPS only for 1 year!"
  2. Next request (HTTP or HTTPS):
     → Browser performs an INTERNAL https://bank.com (without an HTTP request!)
     → Server sees only HTTPS requests
     → SSL stripping fails: HTTP request does not leave the browser!

Limitation: First visit is still vulnerable!
  → Solution: HSTS Preload List (browser-internal)

HSTS Header Syntax

Strict-Transport-Security Header:

Basic:
  Strict-Transport-Security: max-age=31536000

With subdomains:
  Strict-Transport-Security: max-age=31536000; includeSubDomains

With Preload:
  Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Parameter Meaning:

max-age=<seconds>

  :
  → How long the browser remembers HSTS for this domain (in seconds)
  → 31536000 = 1 year (recommended for production)
  → 86400 = 1 day (for testing)
  → The timer resets with every response!
  → max-age=0 → Delete HSTS (for deactivation)

includeSubDomains:
  → HSTS also applies to all subdomains
  → CAUTION: All subdomains must support HTTPS!
  → Otherwise: *.example.com without HTTPS → immediately inaccessible!
  → Test before enabling: are all subdomains accessible via HTTPS?

preload:
  → Marks domain for inclusion in browser preload list
  → Preload list is compiled into browser binaries
  → Protects from the VERY FIRST visit (no initial HTTP call!)
  → One-time setup for domain inclusion: hstspreload.org
  → VERY DIFFICULT TO REVERSE! (Browser updates take months)

DO NOT set on development/test domains:
  → max-age &gt; 0 on localhost → Browser can no longer reach localhost via HTTP!
  → Only ever set on production + appropriately long max-age

Implementation

Server configurations:

Nginx:
  server {
    listen 443 ssl http2;
    server_name example.com;

    # HSTS header (ONLY after complete HTTPS setup!):
    add_header Strict-Transport-Security &quot;max-age=31536000; includeSubDomains; preload&quot; always;

    # HTTP → HTTPS Redirect (in addition to HSTS):
    # (for the very first visit before HSTS caching)
  }

  server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
  }

Apache:
  <VirtualHost *:443>
    Header always set Strict-Transport-Security &quot;max-age=31536000; includeSubDomains; preload&quot;
  </VirtualHost>

  # HTTP → HTTPS
  <VirtualHost *:80>
    Redirect permanent / https://example.com/
  </VirtualHost>

  Caddy (automatic!):
  example.com {
    # Caddy automatically enables HTTPS + HTTP redirect!
    # HSTS header automatically set when Caddy manages HTTPS
  }

Node.js (Express):
  const helmet = require(&#x27;helmet&#x27;);
  app.use(helmet.hsts({
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  }));

Python (Django):
  # settings.py:
  SECURE_HSTS_SECONDS = 31536000
  SECURE_HSTS_INCLUDE_SUBDOMAINS = True
  SECURE_HSTS_PRELOAD = True
  SECURE_SSL_REDIRECT = True  # HTTP → HTTPS redirect

Step-by-step implementation:
  Phase 1: max-age=86400 (1 day) - test if everything works
  Phase 2: max-age=2592000 (1 month) - extended monitoring
  Phase 3: max-age=31536000 + includeSubDomains - Production
  Phase 4: Request preload - if secure

HSTS Preload List

Browser Preload List Process:

What is the Preload List?
  → List of domains that browsers recognize as HTTPS-only from the start
  → Built into: Chrome, Firefox, Safari, Edge, Opera
  → Protects you from the VERY FIRST visit!
  → Even if your own server is compromised → Browser rejects HTTP

Inclusion in the Preload List:
  Requirements (all must be met!):
  □ Valid HTTPS certificate on the domain
  □ HTTP redirect to HTTPS (301 or 302)
  □ HSTS header with:
    - max-age &gt;= 31536000 (1 year!)
    - includeSubDomains
    - preload
  □ ALL subdomains accessible via HTTPS!

  Apply: hstspreload.org
  → Enter domain → Check status
  → Submit application → Chrome-Chromium repository PR
  → Review: 1–3 months until active browser versions

Update preload list (ATTENTION!):
  → Removal from the list takes months to years
  → Browser releases aren’t immediately available everywhere
  → Older browser versions retain the old status
  → Therefore: preload is PERMANENT (in practical terms!)

Domains that use preload:
  All .gov and .mil domains: preloaded!
  Google, Facebook, Twitter: preloaded
  More and more German government agencies: preloaded

Alternative protection without preload:
  → HTTPS-Only cookie: Secure; SameSite=Strict
  → Certificate Transparency Monitoring
  → DNS CAA records: only authorized CAs may issue certificates

Testing and Issues

Testing HSTS:

1. Check headers:
   curl -s -D - https://example.com -o /dev/null | grep -i strict-transport
   → Strict-Transport-Security: max-age=31536000; includeSubDomains

2. HSTS Preload Status:
   hstspreload.org → Enter domain → Status

3. SSL Labs (comprehensive):
   ssllabs.com/ssltest/ → checks TLS + HSTS + preload status

4. Security Headers:
   securityheaders.com → checks all HTTP security headers

Common HSTS Issues:

Issue 1: Mixed Content After HSTS Activation:
  HSTS → all subdomains must use HTTPS
  alt.example.com still on HTTP → subpages inaccessible!
  Solution: Switch all subdomains to HTTPS before `includeSubDomains`

Problem 2: HSTS on localhost/staging:
  `max-age` too long on localhost → browser attempts to access localhost via HTTPS
  → Development environments inaccessible!
  Solution: Set HSTS ONLY on production URLs
  Different Nginx configurations for Dev/Prod

Problem 3: Certificate expires:
  HSTS active + certificate expired → Site COMPLETELY inaccessible!
  No manual HTTP exception possible with HSTS
  Solution: Certificate monitoring + auto-renewal (Let&#x27;s Encrypt)

Problem 4: max-age=0 to deactivate:
  Strict-Transport-Security: max-age=0
  → Browser deletes HSTS for this domain
  → Can take months for all browser caches to be cleared
```</seconds>