⚠️ EDUCATIONAL DEMO: Simulates how missing HSTS enables an SSL-stripping downgrade attack on school portals. No real network traffic is intercepted.

HSTS Missing — Downgrade Attack Demo

Because Strict-Transport-Security is absent, the first HTTP connection a user makes can be intercepted before the browser upgrades it to HTTPS.

THE SECURITY RISK IN PLAIN ENGLISH

HTTPS keeps data private. But HSTS determines whether the browser will even try HTTP first.

When a user types school.edu.ph in their browser (no https://), the browser sends an unencrypted HTTP request first. An attacker on the same network (school Wi-Fi, café, ISP) can intercept that request before it ever reaches the server — and strip the HTTPS redirect, leaving the user on a fake HTTP version of the site forever.

HSTS fixes repeat visits. The server sets Strict-Transport-Security: max-age=31536000. After the first visit, the browser remembers for one year: "Always use HTTPS for this domain, never HTTP." The downgrade attack becomes impossible — for returning visitors.

The remaining gap — Trust on First Use (TOFU): HSTS only works after the browser has seen the header at least once. On the very first visit — or if the cache has expired, or the user cleared browser data — the browser has no HSTS entry and will send a plain HTTP request. That first request is vulnerable to exactly the SSL stripping attack shown in the left panel.

The complete fix: HSTS Preloading. Google maintains a hardcoded list of domains that browsers ship with built-in HSTS entries. If your domain is on that list, the browser never makes a plain HTTP request — not even the first time. To qualify, serve: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload and submit at hstspreload.org.

❌ Without HSTS (Vulnerable)
💻
STUDENT'S BROWSER
Types school.edu.ph — browser sends plain HTTP request over school Wi-Fi
😈
ATTACKER (on same network)
Intercepts the HTTP request. Strips the 301 redirect. Shows victim a fake HTTP login page.
🔒
CREDENTIALS CAPTURED
Student logs in on the fake page. Attacker reads username + password in plaintext, then forwards to the real site — victim never notices.
HTTP/2 200 OK
Server: nginx/1.18.0
Content-Type: text/html
✕ Strict-Transport-Security: (missing)
📧 Captured: username=jdelacruz & password=Sch00l2024!
The student has no idea — the page looked real. The attacker now has persistent access.
✅ With HSTS (Protected)
💻
STUDENT'S BROWSER
Types school.edu.ph — browser checks its HSTS cache. Entry found. Automatically sends HTTPS without any HTTP request.
🚫
ATTACKER (on same network)
Nothing to intercept. The browser never sent an HTTP request. Attacker sees only encrypted TLS traffic they cannot read.
🛡️
ENCRYPTED CONNECTION
Login credentials travel inside TLS. Even if intercepted, the attacker sees only encrypted bytes — useless without the private key.
HTTP/2 200 OK
Server: nginx/1.18.0
Content-Type: text/html
Strict-Transport-Security: max-age=31536000; includeSubDomains
🛡️ Attack Blocked. Browser used HTTPS directly. No HTTP request was ever sent. Attacker intercepted nothing.
🔒 With HSTS Preloading (Always Protected)
💻
STUDENT'S BROWSER — VERY FIRST VISIT
Types school.edu.ph for the first time ever. Browser checks its built-in preload list. Domain found — sends HTTPS directly, no HTTP request made.
🚫
ATTACKER (on same network)
Nothing to intercept — even on first visit. The preload list ships inside Chrome, Firefox, Safari, and Edge. No HTTP request ever leaves the browser.
TOFU GAP ELIMINATED
Cache expired? Browser data cleared? New device? Doesn't matter. The preload list is hardcoded in the browser itself — not stored in a cookie or cache.
HTTP/2 200 OK
Server: nginx/1.18.0
Content-Type: text/html
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
🔒 TOFU Gap Eliminated. Browser used HTTPS on the very first request — no HTTP ever left the machine. The preload list in the browser made it impossible.

❌ Current State (Vulnerable)

  • No Strict-Transport-Security header
  • First visit over HTTP is interceptable on any network
  • SSL stripping can silently proxy the connection
  • Student/staff credentials exposed on school Wi-Fi or public hotspots
  • Even with a valid SSL certificate, the upgrade hop is vulnerable

✅ Fix (One Server Header)

  • Add: Strict-Transport-Security: max-age=31536000; includeSubDomains
  • Nginx: add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  • Apache: Header always set Strict-Transport-Security "max-age=31536000"
  • Cloudflare: Enable "Always Use HTTPS" + HSTS in SSL/TLS settings
  • Protects repeat visitors; first visit still has the TOFU gap

🔒 Maximum Protection — HSTS Preloading

  • Add preload directive: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • Submit your domain at hstspreload.org
  • Eliminates the Trust on First Use (TOFU) gap — browser never sends HTTP even on first visit
  • Protects users whose cache has expired or who cleared browser data
  • Built into Chrome, Firefox, Safari, and Edge — no plugin or server-side logic required