Closed Bug 2026156 Opened 6 months ago Closed 5 months ago

NSS CompressedCertificate memory exhaustion — single page load OOM-kills Firefox (CVSS4.0 9.3)

Categories

(NSS :: Libraries, defect, P2)

Tracking

(nss+ 3.123, firefox-esr115 unaffected, firefox-esr140150+ fixed, firefox149 wontfix, firefox150+ fixed, firefox151+ fixed)

RESOLVED FIXED
Tracking Status
nss + 3.123
firefox-esr115 --- unaffected
firefox-esr140 150+ fixed
firefox149 --- wontfix
firefox150 + fixed
firefox151 + fixed

People

(Reporter: social, Assigned: anna.weine)

References

Details

(Keywords: csectype-dos, reporter-external, sec-low, Whiteboard: [adv-main150-][adv-esr140.10-])

Attachments

(2 files)

Steps to reproduce:

python3 poc_burst_firefox.py --origins 256 --headless

The PoC starts 256 malicious TLS servers, serves an attack
page over HTTPS, launches Firefox headless, and monitors
memory. Full report and standalone PoC attached.

Actual results:

Firefox consumed 38GB in two minutes and was killed by the
OS out-of-memory killer (SIGKILL). Repeatable across three
consecutive runs on a clean system.

Root cause: tls13_HandleCertificateDecode() in
lib/ssl/tls13con.c passes the wire uncompressed_length
(uint24, max 16MB) directly to PORT_ZAlloc without
bounding. The decompressed Certificate entries are copied
into persistent per-connection memory (peerCertArena via
SECITEM_ArenaDupItem) that is not freed on handshake
failure — only on socket close. NSS already caps regular
handshake messages at 128KB (MAX_HANDSHAKE_MSG_LEN), but
the CompressedCertificate path bypasses this.

Affected: NSS 3.110+, Firefox 128+ (cert compression
default-on per Bugzilla 1881027).
CVSS 3.1: 8.6 (High). CVSS 4.0: 9.3 (Critical).

Expected results:

NSS should cap decodedCertLen at 100KB before allocation,
matching OpenSSL and BoringSSL.

User workaround: about:config →
security.tls.enable_certificate_compression → false

sec-other I'd say?

Flags: needinfo?(dveditz)
Keywords: sec-other

(In reply to Anna Weine from comment #1)

sec-other I'd say?

What?

Oh, keywords.

"sec-other Bugs that may not be exploitable security issues but are kept confidential to protect sensitive information."

This is remotely exploitable --- malicious server can kill off browser.

I disagree with sec-other.

CVSS is a terrible metric for client products, but even so how do you get anywhere near high or critical? When I try it I get a CVSS 3.1 score of 3.6, with the modified impact score being 0.7:
https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L/CR:X/IR:X/AR:L/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:L&version=3.1

Regardless of CVSS score, we treat client denial of service bugs as a stability issue (and potentially abuse) and not security vulnerabilities. This stance also aligns with how other browser vendors consider DOS bugs; for example, here is the chromium FAQ on the topic:
https://chromium.googlesource.com/chromium/src/+/master/docs/security/faq.md#Are-denial-of-service-issues-considered-security-bugs

Flags: needinfo?(dveditz)

(In reply to Daniel Veditz [:dveditz] from comment #4)

how do you get anywhere near high or critical? When I try it I get a CVSS 3.1 score of 3.6, with the modified impact score being 0.7:

Unsure how you got there...

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H = 8.6 (High)

Exploitability assessment The attacker operates a malicious TLS 1.3 server and waits for a victim to connect — no MITM, no adjacent LAN, no special positioning required. Certificate compression is enabled by default in Firefox since version 128 (mid-2024), so no special client configuration is needed. A single crafted CompressedCertificate message triggers the allocation automatically during the handshake, with no user action beyond navigating to the attacker's site. Attack complexity is Low: registering subdomains under a wildcard DNS record and serving a page with subresource references requires no special skill or infrastructure.

      Attack Vector : Network
  Attack Complexity : Low
Privileges Required : None
   User Interaction : None

Impact assessment Each connection pins 16MB of persistent memory. A single page load opens connections across hundreds of origins. Memory grows linearly until the out-of-memory killer strikes. The out-of-memory (OOM) killer terminates the entire browser process:
all tabs across all origins, all unsaved data, all active sessions, dead. The vulnerable component is NSS's certificate decompression; the impact extends to all security contexts in the browser — a scope change. No data is disclosed. No data is modified.

              Scope : Changed
    Confidentiality : None
          Integrity : None
       Availability : High

CVSS 3.1 does not score data destruction — only data modification. The OOM kill destroys all unsaved form data, in-progress uploads, session state, and WebRTC calls across every origin. CVSS 4.0 captures this via Subsequent System metrics, replacing Scope with explicit impact on systems beyond the vulnerable component:

Sub Integrity        : High (all unsaved data destroyed)
Sub Availability     : High (all tabs killed)

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:H/SA:H = 9.3 (Critical)

(All in supplied ZERODAY-NSS-CERT-COMPRESSION-BOMB-2026-03-25.tar.gz.)

Regardless of CVSS score, we treat client denial of service bugs as a stability issue (and potentially abuse) and not security vulnerabilities.

There's data loss...

It's worth noting. RFC 8879 §4 explicitly anticipates client-side limits: "The presence of this [uncompressed_length] field allows the receiv[ing client] to...enforce limits on the [Certificate] size before performing decompression." Capping is RFC-compliant, albeit, RFC 8879 (Security Considerations, §5) states:

"Implementations SHOULD bound the memory usage when decompressing"

BoringSSL caps, NSS doesn't --- this feels like an RFC-level vulnerability requiring specification patching --- whilst NSS is RFC-complaint, it's vulnerable, BoringSSL isn't.

(In reply to Daniel Veditz [:dveditz] from comment #4)

we treat client denial of service bugs as a stability issue (and potentially abuse) and not security vulnerabilities [as goes Google].

That's a solid position, I generally don't disagree, DoS is uninteresting: Resources wasted, things get slow, move on. Here we have something slightly different.

There's a remote kill switch in Firefox, a server can SIGKILL a user's browser.

The blast radius is cross-origin --- server kills all tabs, all sessions, all unsaved data across every origin --- attacker at evil.com destroys
the user's session at bank.com. Embed in an ad network, Firefox stops working.

Attached file (secure) —
Flags: sec-bounty?
Assignee: nobody → anna.weine
Severity: -- → S2
Status: UNCONFIRMED → ASSIGNED
tracking-nss: --- → +
Ever confirmed: true
Keywords: sec-other → sec-moderate
Priority: -- → P2

Pushed by jschanck@mozilla.com:
https://hg.mozilla.org/projects/nss/rev/b5c7d408a45d
Add a maximum cert uncompressed len and tests

Status: ASSIGNED → RESOLVED
Closed: 5 months ago
Resolution: --- → FIXED
Group: crypto-core-security → core-security-release
Pushed by jschanck@mozilla.com: https://hg.mozilla.org/projects/nss/rev/3e7c3eac6bbe Add a maximum cert uncompressed len and tests
Pushed by jschanck@mozilla.com: https://hg.mozilla.org/projects/nss/rev/da54180cfbc9 Add a maximum cert uncompressed len and tests
QA Whiteboard: [sec] [uplift] [qa-triage-done-c151/b150]
Whiteboard: [adv-main150+]
Whiteboard: [adv-main150+] → [adv-main150+][adv-esr140.10+]
Whiteboard: [adv-main150+][adv-esr140.10+] → [adv-main150-][adv-esr140.10-]
Flags: sec-bounty? → sec-bounty-
Keywords: sec-want → sec-low
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: