Closed Bug 2034320 Opened 3 months ago Closed 3 months ago

Compromised content process can plant a certificate override for arbitrary host/port pairs

Categories

(Core :: DOM: Content Processes, defect)

defect

Tracking

()

RESOLVED DUPLICATE of bug 2013800

People

(Reporter: chris, Unassigned)

Details

(Keywords: reporter-external, Whiteboard: [client-bounty-form])

Attachments

(4 files)

Base revision

Patch applies cleanly to mozilla-firefox/firefox (mozilla-central) at rev ad5f057320ecc6b934dfa1e3ec361f87712806cc (2026-04-20). Verified with git apply --check against a pristine HEAD subtree.

Description

A compromised content process can cause Firefox to store a certificate exception for an arbitrary host, even though the user only approved a certificate warning for a different host controlled by that renderer.

In the proof below, approving the warning at attacker.test:8443 causes Firefox to store an override for victim.test:8443. After that, victim.test:8443 loads without its own certificate warning. The generated profile's cert_override.txt contains a victim.test:8443 entry, showing the override was persisted on disk.

This is not itself a live MITM. The security consequence is that a post-renderer-compromise attacker can pre-authorize an attacker-chosen certificate for an arbitrary host/port pair, enabling later certificate-warning bypass / silent TLS interception for that target when the attacker can present that certificate.

Cause

The IPC handler
mozilla::dom::ContentParent::RecvAddCertException(aCert, aHostName, aPort, aOriginAttributes, aIsTemporary)
(dom/ipc/ContentParent.cpp:6534) forwards (aHostName, aPort, aOriginAttributes, aCert, aIsTemporary) directly to nsCertOverrideService::RememberValidityOverride. Neither the handler nor the override service checks that the calling content process is actually handling a failed channel for aHostName:aPort.

The legitimate child-side caller is Document::AddCertException (dom/base/Document.cpp:1594). That code derives host, port, and cert from mFailedChannel and its nsITransportSecurityInfo. A compromised renderer can keep the real cert object and real cert-error flow, but replace only host / port immediately before SendAddCertException(...). The parent trusts those substituted fields and stores the override for the wrong origin.

Threat model

Same as bug 1899154: attacker has memory-corruption RCE in a content process and patches the outgoing IPC at the marshalling layer. The PoC patch simulates this one frame above marshalling, at the last child-side call site before IPC.

Steps to reproduce (Firefox for Linux)

Tested against mozilla-firefox/firefox revision ad5f057320ec (2026-04-20 mozilla-central tip).

  1. Add hostnames:
    echo "127.0.0.1 attacker.test victim.test" | sudo tee -a /etc/hosts
    
  2. Apply the attached 0001-attacker-add-cert-exception.patch and build
    (any non-debug mach build).
  3. Generate a self-signed test cert for both names using the attached
    openssl-san.cnf:
    openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
        -keyout key.pem \
        -out cert.pem \
        -config openssl-san.cnf \
        -extensions v3_req
    
  4. Run the attached HTTPS fixture:
    python3 serve_https.py
    
  5. Start Firefox on a clean profile, telling the PoC to forge the victim target:
    MOZ_IPC_TRUST_PoC_ADDCERT=victim.test:8443 \
        ./mach run --temp-profile
    
  6. On the fresh profile, first visit https://victim.test:8443/ and
    confirm Firefox shows a certificate warning.
  7. Then visit https://attacker.test:8443/ and click through its
    certificate warning once.
  8. Visit https://victim.test:8443/ again. It now loads without its own
    warning, even though no exception was ever approved for victim.test.
  9. Inspect the temporary profile's cert_override.txt. It contains:
    victim.test:8443:    ...
    

Observed result: victim.test:8443 warned on a clean profile before step 7, then loaded successfully after approving only attacker.test:8443. The profile's cert_override.txt contained a persisted victim.test:8443 override entry.

The patch is dormant when the env var is unset.

Affected versions

Reproduced on mozilla-firefox/firefox rev ad5f057320ec (2026-04-20).

Attachments

  • 0001-attacker-add-cert-exception.patch - single-file patch against dom/base/Document.cpp
  • serve_https.py - minimal HTTPS fixture that serves both attacker.test and victim.test
  • openssl-san.cnf - OpenSSL config used to generate the repro cert
  • mozconfig - local build config used to reproduce
Flags: sec-bounty?
Attached file serve_https.py
Attached file openssl-san.cnf
Attached file mozconfig
Group: firefox-core-security → dom-core-security
Status: UNCONFIRMED → RESOLVED
Closed: 3 months ago
Component: Security → DOM: Content Processes
Duplicate of bug: CVE-2026-16372
Product: Firefox → Core
Resolution: --- → DUPLICATE
Flags: sec-bounty? → sec-bounty-
Group: dom-core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: