← Back to Feed CACHED · 2026-07-14 09:41:19 · CACHE_KEY tenable:98056
tenable:98056 · CWE-319 · Disclosed 2017-03-31

Missing HTTP Strict Transport Security

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

This is a missing seatbelt warning light, not a car with no brakes

Tenable plugin 98056 fires when a web application serves content over HTTPS but does not emit the Strict-Transport-Security response header. HSTS is a browser directive that tells clients *'from now on, only speak HTTPS to me for the next N seconds.'* Without it, a first-visit user who types example.com in the URL bar hits port 80, and a network attacker with a foothold on that path can intercept or downgrade the initial request (classic *sslstrip* territory). Once the browser has been to the site once with HSTS set, all subsequent requests are HTTPS-only regardless of what the user types.

This is a misconfiguration / hardening finding, not a CVE. There is no exploitable code flaw, no memory corruption, no auth bypass. Tenable rating it Medium (CVSS v3 6.5, VPR 4.8) is defensible under a strict interpretation of confidentiality impact via MitM, but it dramatically overstates the risk for the modern web where HSTS preload, browser HTTPS-First mode (Chrome 90+, Firefox, Safari), and near-universal DNS-over-HTTPS make the sslstrip attack path a narrow edge case. In practice this belongs in the *deploy in the next release* bucket, not the *page the on-call* bucket.

"Missing HSTS is a hardening gap, not a vulnerability — Tenable's Medium rating overstates the real-world risk on a properly-configured HTTPS site."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Attacker obtains an on-path position

The attacker must sit between the victim's browser and the target server — same coffee-shop Wi-Fi, rogue AP, ARP spoof on a LAN, compromised upstream ISP, or a hostile country border gateway. Without on-path capability, the missing HSTS header is unreachable.
Conditions required:
  • Layer-2/3 adjacency or upstream routing control
  • Ability to intercept and modify TCP streams
Where this breaks in practice:
  • Most user traffic is over cellular or home broadband, not shared Wi-Fi
  • Corporate networks use WPA3-Enterprise + 802.1X, making L2 injection non-trivial
  • Public Wi-Fi has largely moved to WPA3-SAE or captive-portal segmentation
Detection/coverage: Not detectable by host scanners; wireless IDS (e.g. WatchGuard WIPS) can flag rogue APs.
STEP 02

Victim initiates a plaintext HTTP request to the target

The victim must type example.com (not https://example.com), click an http:// link, or use a stale bookmark. Modern browsers now default to HTTPS-First — Chrome, Firefox, Safari, and Edge all auto-upgrade to https:// before falling back. This step fails outright on any browser released in the last ~3 years unless the user has explicitly disabled the feature.
Conditions required:
  • Victim uses a URL that resolves to plaintext HTTP first
  • Browser does not enforce HTTPS-First / HTTPS-Only
Where this breaks in practice:
  • Chrome HTTPS-First is default since v90 (2021)
  • Firefox HTTPS-Only mode widely rolled out
  • Safari upgrades known-HTTPS hosts automatically
  • Sites on the HSTS preload list are hard-coded in Chromium — no first-hit window at all
STEP 03

Attacker runs sslstrip / MITMproxy to downgrade the connection

Tools like sslstrip2, mitmproxy, or bettercap's hstshijack module rewrite the intercepted HTTP response, replacing https:// links with http:// and proxying the TLS session to the real server. Because HSTS was never set, the browser has no memory that this host should be HTTPS-only, so it accepts the plaintext channel.
Conditions required:
  • Working sslstrip-class tooling
  • Site does not appear on Chromium HSTS preload list
Where this breaks in practice:
  • Mixed-content blocking in modern browsers breaks most stripped pages
  • Any subresource loaded via absolute https:// URL will still fail to strip
  • Increasing use of Upgrade-Insecure-Requests CSP directive
Detection/coverage: Server-side: sudden drop in HTTPS ratio in access logs. Client-side: EDR with browser telemetry (CrowdStrike, SentinelOne) can flag known sslstrip signatures.
STEP 04

Attacker harvests credentials or session cookies

With the downgraded plaintext channel established, the attacker reads form POSTs, session cookies (unless Secure flag is set — which independently mitigates this), and any bearer tokens. Impact ends at the session/credential of the single intercepted user; no server-side compromise.
Conditions required:
  • Session cookies not marked Secure
  • No token binding / DPoP / mTLS in use
Where this breaks in practice:
  • Secure cookie flag is default in most modern frameworks
  • SameSite=Strict/Lax reduces replay surface
  • MFA on the application blunts credential-only theft
Detection/coverage: Anomalous session geolocation, impossible-travel rules in Okta / Entra ID / Splunk UEBA.
03 · Intelligence Metadata

The supporting signals.

Finding typeConfiguration / hardening gap — not a code-execution CVE
Tenable plugin familyWeb App Scanning → HTTP Security Header
Tenable severityMedium (CVSS v3 6.5, CVSS v4 6.3, VPR 4.8)
CVE mappingNone — this is a WAS check, not a CVE. NVD/MITRE have no record because there is nothing to record.
KEV statusNot applicable — no CVE, cannot be listed
EPSSNot applicable — no CVE
Exploit toolingsslstrip, sslstrip2, bettercap hstshijack, mitmproxy — all mature, all public for a decade+
In-the-wild activitysslstrip-style attacks are rare in enterprise incident data since ~2020; largely displaced by phishing kits and OAuth abuse
PrevalenceVery common finding — Qualys SSL Labs data historically shows ~40–60% of TLS-enabled sites lack HSTS
First publishedPlugin published 2017-03-31, last updated 2025-05-16
StandardsRFC 6797, OWASP HSTS Cheat Sheet
Related CAPECCAPEC-65 (Sniff Application Code), CAPEC-102, CAPEC-117 (Interception), CAPEC-383, CAPEC-477
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.1/10)

This is a defense-in-depth header omission, not an exploitable vulnerability — the decisive factor is that successful abuse requires an on-path attacker AND a victim using a browser without HTTPS-First AND a site not on the preload list, a three-way conjunction that describes a vanishing sliver of real traffic. There is no code flaw to weaponize, no CVE to track, and no chain that reaches beyond a single intercepted user's session.

HIGH on the technical characterization of the finding
HIGH that this is not a CVE-class vulnerability
MEDIUM on the exposure share of browsers still lacking HTTPS-First

Why this verdict

  • No code vulnerability exists — plugin 98056 is a header-presence check, not a flaw detection. There is nothing to patch on the server binary; the fix is a one-line config change.
  • Modern browsers already mitigate — Chrome HTTPS-First (default since v90/2021), Firefox HTTPS-Only, Safari auto-upgrade, and the Chromium HSTS preload list eliminate the first-visit downgrade window for the overwhelming majority of users.
  • Requires on-path attacker position — an unauthenticated remote adversary cannot exploit this from the internet; they need L2/L3 interception, which itself implies a coffee-shop / rogue-AP scenario or a nation-state adversary who has bigger levers.
  • Role multiplier: public marketing site — chain ends in at-most one user's session; blast radius is a single victim, no lateral movement.
  • Role multiplier: authentication portal / SSO IdP login page — chain still ends in one user's credential, but if MFA is absent, that one credential could pivot to identity compromise. This is why HSTS + preload is mandatory for IdP login hosts, but even here the friction stack (HTTPS-First + Secure cookies + MFA) makes real-world compromise implausible; the role multiplier does not lift this above LOW.
  • Blast radius is capped at per-victim session theft — no server-side compromise, no fleet impact, no supply-chain path. The high-value-role floor rule does not trigger because there is no chain to fleet-scale outcome even on the worst-case role.

Why not higher?

A MEDIUM rating (Tenable's default) would be defensible only in a world where HTTPS-First browsing is not the norm — that world ended around 2022. Every additional MEDIUM finding in a scan queue costs analyst cycles that would be better spent on actual RCEs. Rating this MEDIUM competes for attention with real vulnerabilities.

Why not lower?

IGNORE is wrong because HSTS *is* required for identity provider login pages, banking portals, and any host on the HSTS preload list — omitting it there is a genuine gap. It also fails common compliance checks (PCI DSS 4.0 §4.2, HIPAA reasonable-safeguards interpretations, some FedRAMP baselines), so it cannot be dismissed entirely; auditors will flag it.

05 · Compensating Control

What to do — in priority order.

  1. Add the HSTS header at the edge (reverse proxy / CDN / load balancer) — Configure Strict-Transport-Security: max-age=31536000; includeSubDomains on nginx/Apache/HAProxy/F5/CloudFront/Cloudflare. Applying at the edge fixes every backend behind it in one change. Per noisgate remediation SLA for LOW, target within the standard release cycle — no mitigation SLA applies.
  2. Submit high-value hostnames to the Chromium HSTS preload list — For login portals, banking, IdP, and admin consoles, register at hstspreload.org after confirming max-age≥31536000; includeSubDomains; preload. This eliminates the first-visit window entirely for Chrome, Edge, Firefox, and Safari users. Do this alongside the header rollout.
  3. Enforce HTTP→HTTPS 301 redirects and drop port 80 listeners where feasible — A permanent redirect ensures plaintext requests are immediately upgraded. Better still, terminate port 80 handling entirely for API endpoints. Ship in the same change window as the HSTS header.
  4. Set the Secure and HttpOnly flags on all session cookies — Independent of HSTS, Secure prevents cookies from being sent over any plaintext channel — this alone defeats the core impact scenario of plugin 98056. Audit your framework defaults (Django, Rails, Spring, Express) to confirm.
  5. Roll out Content-Security-Policy with upgrade-insecure-requests — Instructs the browser to auto-upgrade any subresource load to HTTPS, complementing HSTS for legacy pages with hardcoded http:// asset URLs.
What doesn't work
  • WAF rules — a WAF sits server-side; it cannot influence a MitM downgrade that happens on the client's network path.
  • TLS 1.3 enforcement — the sslstrip attack occurs *before* TLS is negotiated. Cipher / protocol hardening does not close this gap.
  • Certificate pinning at the server — HPKP is deprecated and browser-side pinning is now internal-only (Google, Facebook binaries). Not a general control.
  • EDR on the server — the attack never touches the server; it's between the client and the network path. Host EDR sees nothing.
06 · Verification

Crowdsourced verification payload.

Run from any auditor workstation or CI job that can reach the target HTTPS endpoint. No privileges required. Example: ./check_hsts.sh https://login.example.com

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_hsts.sh — Verify Strict-Transport-Security header on a target URL
# Usage: ./check_hsts.sh https://target.example.com
# Exit: 0 PATCHED, 1 VULNERABLE, 2 UNKNOWN

set -u
TARGET="${1:-}"
if [[ -z "$TARGET" ]]; then
  echo "UNKNOWN: usage: $0 https://host" >&2
  exit 2
fi

if ! command -v curl >/dev/null 2>&1; then
  echo "UNKNOWN: curl not installed" >&2
  exit 2
fi

# Grab response headers, follow redirects (server may redirect http->https)
HEADERS=$(curl -sSIL --max-time 10 "$TARGET" 2>/dev/null) || {
  echo "UNKNOWN: could not fetch $TARGET"
  exit 2
}

# Look for Strict-Transport-Security (case-insensitive) on the FINAL response
HSTS_LINE=$(printf '%s\n' "$HEADERS" | awk 'BEGIN{IGNORECASE=1} /^strict-transport-security:/ {print; found=1} END{exit !found}')
RC=$?

if [[ $RC -ne 0 || -z "$HSTS_LINE" ]]; then
  echo "VULNERABLE: no Strict-Transport-Security header on $TARGET"
  exit 1
fi

# Parse max-age
MAX_AGE=$(printf '%s' "$HSTS_LINE" | grep -oiE 'max-age=[0-9]+' | head -1 | cut -d= -f2)
if [[ -z "${MAX_AGE:-}" ]]; then
  echo "VULNERABLE: HSTS header present but no max-age directive: $HSTS_LINE"
  exit 1
fi

if (( MAX_AGE < 31536000 )); then
  echo "VULNERABLE: HSTS max-age=$MAX_AGE is below 1 year (31536000). Header: $HSTS_LINE"
  exit 1
fi

if ! printf '%s' "$HSTS_LINE" | grep -qi 'includeSubDomains'; then
  echo "VULNERABLE: HSTS present but missing includeSubDomains. Header: $HSTS_LINE"
  exit 1
fi

echo "PATCHED: $HSTS_LINE"
exit 0
07 · Bottom Line

If you remember one thing.

TL;DR
Do not page anyone for this. Add HSTS to your standard web-hardening baseline and ship it in the next normal release train — for a LOW verdict there is no noisgate mitigation SLA, so go straight to the noisgate remediation SLA of ≤ 365 days, though in practice a header change lands in days. Prioritize the header on your identity provider login page, admin consoles, and any host that handles auth cookies — those get the header AND HSTS preload registration. Everything else can ride the normal config-management wave. If a compliance auditor (PCI 4.0, HIPAA, FedRAMP) is at the door, treat it as urgent-for-paperwork, not urgent-for-adversary.

Sources

  1. Tenable plugin 98056 — Missing HTTP Strict Transport Security Policy
  2. Tenable Community — plugin 98056 discussion
  3. RFC 6797 — HTTP Strict Transport Security (HSTS)
  4. OWASP HSTS Cheat Sheet
  5. Chromium HSTS Preload submission site
  6. Google — HTTPS-First Mode in Chrome
  7. Mozilla MDN — Strict-Transport-Security header
  8. Tenable HTTP Security Header plugin family
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.