Sandbox escape: RecvAddCertException allows any content process to add persistent TLS certificate overrides for arbitrary hostnames (MITM enablement)
Categories
(Core :: DOM: Content Processes, defect)
Tracking
()
People
(Reporter: hanaputrarayhan, Unassigned)
Details
(Keywords: reporter-external, Whiteboard: [client-bounty-form])
Attachments
(1 file)
|
2.30 KB,
text/plain
|
Details |
Discovery
- Method: Manual source code audit of IPC message handlers in
dom/ipc/ContentParent.cpp - Firefox version: mozilla-central trunk, affects all current versions
- OS: All platforms
Root Cause
The IPC handler ContentParent::RecvAddCertException at dom/ipc/ContentParent.cpp:6540-6554 allows any content (renderer) process to add TLS certificate overrides for arbitrary hostnames with zero authorization:
mozilla::ipc::IPCResult ContentParent::RecvAddCertException(
nsIX509Cert* aCert, const nsACString& aHostName, int32_t aPort,
const OriginAttributes& aOriginAttributes, bool aIsTemporary,
AddCertExceptionResolver&& aResolver) {
nsCOMPtr<nsICertOverrideService> overrideService =
do_GetService(NS_CERTOVERRIDE_CONTRACTID);
if (!overrideService) {
aResolver(NS_ERROR_FAILURE);
return IPC_OK();
}
// NO AUTHORIZATION CHECK - directly stores the override
nsresult rv = overrideService->RememberValidityOverride(
aHostName, aPort, aOriginAttributes, aCert, aIsTemporary);
aResolver(rv);
return IPC_OK();
}
Missing Checks
-
No process type check. Any content process can send
AddCertException. The message is defined underparent:indom/ipc/PContent.ipdl(line 1609) with no annotations restricting sender type. It should be restricted toPRIVILEGEDABOUT_REMOTE_TYPE(about:certerror). -
No hostname validation. The handler accepts any hostname. A compromised renderer for
evil.comcan add cert overrides forbankofamerica.com. -
WebIDL gate is irrelevant.
Document.webidlgates the JS API with[Func="Document::CallerIsTrustedAboutCertError"], but this check runs in the content process. A compromised renderer callsContentChild::SendAddCertException()directly on the PContent IPC channel, bypassing the WebIDL gate entirely. -
No authorization in the service.
RememberValidityOverrideatsecurity/manager/ssl/nsCertOverrideService.cpp:380-410only validates hostname is non-empty and ASCII, then unconditionally stores. -
Overrides persist to disk. When
aIsTemporary=false, the override is written tocert_override.txtand persists across browser restarts.
IPC Flow
CONTENT PROCESS (compromised) PARENT PROCESS
ContentChild::SendAddCertException( ContentParent::RecvAddCertException(
attackerCert, ------> aCert,
"bankofamerica.com", ------> aHostName, <-- ANY hostname
443, ------> aPort,
OriginAttributes(), ------> aOriginAttributes,
false ------> aIsTemporary) <-- false = PERMANENT
)
|
| NO CHECK: mRemoteType?
| NO CHECK: hostname matches browsing?
| NO CHECK: user action?
v
RememberValidityOverride("bankofamerica.com", ...)
|
v
cert_override.txt (PERSISTS TO DISK)
ALL future HTTPS to bankofamerica.com
accept attacker's certificate (MITM)
Impact
A compromised content process can:
- Add permanent TLS certificate overrides for any hostname (banking, email, etc.)
- Supply an attacker-controlled certificate
- Overrides affect all future connections from any process, not just the compromised one
- Enables silent, persistent MITM attacks on any HTTPS website
Per Mozilla's bounty program: "Vulnerabilities that assume arbitrary code execution in the content process - such as invoking an IPC method with attacker-controlled parameters - do qualify for Highest Impact."
Comparison With Other Handlers
Other security-sensitive IPC handlers in ContentParent.cpp check mRemoteType to restrict to privileged process types. For example, RecvGetSystemIcon (line 3457) verifies privileged process type. RecvAddCertException is inconsistent in lacking this check.
Exploitation Steps (conceptual)
- Achieve code execution in any content process (via a separate vulnerability)
- From the compromised process, call:
ContentChild::GetSingleton()->SendAddCertException(
attackerCert, "target-bank.com"_ns, 443,
OriginAttributes(), false /* permanent */);
- Parent process stores the override without any checks
- User later visits
target-bank.com-> Firefox accepts the attacker's certificate
Suggested Fix
mozilla::ipc::IPCResult ContentParent::RecvAddCertException(...) {
if (mRemoteType != PRIVILEGEDABOUT_REMOTE_TYPE) {
return IPC_FAIL(this, "AddCertException from non-privileged process");
}
// ... existing code
}
Also consider validating that aHostName matches a cert error actually shown by the content process.
Updated•4 months ago
|
Updated•3 months ago
|
Updated•2 months ago
|
Description
•