Closed Bug 2022253 Opened 8 months ago Closed 4 months ago

Web Notifications: PBackground Sender Principal Not Verified + SystemPrincipal Forgery

Categories

(Core :: DOM: Notifications, defect)

defect

Tracking

()

RESOLVED FIXED
154 Branch
Tracking Status
firefox-esr115 --- unaffected
firefox-esr140 --- wontfix
firefox-esr153 154+ fixed
firefox152 --- wontfix
firefox153 --- wontfix
firefox154 + fixed

People

(Reporter: t.satoki111, Assigned: tschuster)

References

(Blocks 1 open bug)

Details

(4 keywords, Whiteboard: [client-bounty-form][adv-main154-][adv-esr153.1-])

Attachments

(1 file, 2 external files)

4.60 KB, application/x-javascript
Details
Attached file PoC.js —

Summary

PBackground::RecvCreateNotificationParent (BackgroundParentImpl.cpp:485) accepts child-supplied aPrincipal without binding it to the sending process's actual principal. No ValidatePrincipal() call exists.

BackgroundUtils.cpp's PrincipalInfoToPrincipal() converts TSystemPrincipalInfo to SystemPrincipal::Get() unconditionally — no process-type check.

NotificationUtils.cpp:56 IsNotificationAllowedFor() returns true unconditionally for SystemPrincipal, bypassing the permission manager entirely.

Result: a compromised content process sending TSystemPrincipalInfo completely bypasses all notification permission checks.

Attack Chain

Compromised content process (evil.com)
  │
  ▼ [1] PBackground IPC
  SendCreateNotificationParent(TSystemPrincipalInfo, ...)
  │
  ▼ [2] BackgroundUtils.cpp:46-51 PrincipalInfoToPrincipal()
  case TSystemPrincipalInfo:
    principal = SystemPrincipal::Get();  // No process-type check
    return principal;
  │
  ▼ [3] BackgroundParentImpl.cpp:485 RecvCreateNotificationParent()
  NotificationParent::CreateOnMainThread(aPrincipal, ...)
  // No ValidatePrincipal(). Only action-count check.
  │
  ▼ [4] NotificationParent.cpp RecvShow()
  GetNotificationPermission(mArgs.mPrincipal, ...)  // Runs on forged principal
  │
  ▼ [5] NotificationUtils.cpp:56-58 IsNotificationAllowedFor()
  if (aPrincipal->IsSystemPrincipal()) {
    return true;  // Permission manager never consulted
  }
  │
  ▼ Notification displayed (all permission checks bypassed)

Vulnerable Code

1. RecvCreateNotificationParent — No Sender Binding

ipc/glue/BackgroundParentImpl.cpp:485:

mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateNotificationParent(
    Endpoint<dom::notification::PNotificationParent>&& aParentEndpoint,
    NotNull<nsIPrincipal*> aPrincipal,           // child-supplied, no validation
    NotNull<nsIPrincipal*> aEffectiveStoragePrincipal, // child-supplied, no validation
    const bool& aIsSecureContext,
    const nsAString& aScope,
    const IPCNotification& aNotification,
    CreateNotificationParentResolver&& aResolver) {
  dom::notification::NotificationParentArgs args{
      aPrincipal, aEffectiveStoragePrincipal, aIsSecureContext,
      nsString(aScope), aNotification};
  nsresult rv = dom::notification::NotificationParent::CreateOnMainThread(
      std::move(args), std::move(aParentEndpoint), std::move(aResolver));
  // No ValidatePrincipal() call
  return IPC_OK();
}

2. PrincipalInfoToPrincipal — Unconditional SystemPrincipal Conversion

ipc/glue/BackgroundUtils.cpp:46:

case PrincipalInfo::TSystemPrincipalInfo: {
  principal = SystemPrincipal::Get();  // Converted even from content process
  if (NS_WARN_IF(!principal)) {
    return Err(NS_ERROR_NOT_INITIALIZED);
  }
  return principal;  // No process-type rejection path
}

3. IsNotificationAllowedFor — SystemPrincipal Short-Circuit

dom/notification/NotificationUtils.cpp:56:

bool IsNotificationAllowedFor(nsIPrincipal* aPrincipal) {
  if (aPrincipal->IsSystemPrincipal()) {
    return true;  // Permission manager never consulted
  }
  return aPrincipal->SchemeIs("file");
}

4. IPDL Protocol

dom/notification/PNotification.ipdl:

[ChildProc=anydom]
async protocol PNotification {
parent:
  async Show(IPCImage? aIcon) returns (CopyableErrorResult rv);
  async Close();
child:
  async NotifyClick();
};

[ChildProc=anydom] is a process-type filter, not a principal-type restriction. It does not prevent a content process from claiming SystemPrincipal.

Contrast with PContent Handlers

PContent-routed notification IPC handlers call ValidatePrincipal() to verify the sender's actual principal. The PBackground RecvCreateNotificationParent() path has no equivalent check.

Exploitation Scenarios

Scenario 1: SystemPrincipal Forgery → Full Permission Bypass

  1. Attacker compromises a content process (JS engine exploit)
  2. Sends SendCreateNotificationParent() with TSystemPrincipalInfo
  3. Parent deserializes to SystemPrincipal::Get()
  4. IsNotificationAllowedFor() returns true unconditionally
  5. Notification displayed even if the user has never granted any notification permission

Scenario 2: Victim Origin Forgery → Phishing Notification

  1. Victim origin (e.g., bank.example.com) has notification permission granted
  2. Attacker forges ContentPrincipalInfo{origin: "https://bank.example.com"}
  3. Parent checks permission against victim's record → allowed
  4. User sees a notification appearing to come from bank.example.com
  5. Notification click redirects to attacker's phishing site

Scenario 3: ServiceWorker Event Injection

  1. Victim origin has a ServiceWorker with a notificationclick handler
  2. Attacker forges principal + scope to create a persistent notification
  3. User clicks the notification
  4. NotificationHandler.cpp routes notificationclick to the victim's ServiceWorker
  5. Victim SW's click handler executes with attacker-crafted notification data

Suggested Fix

// Add at the top of RecvCreateNotificationParent():
if (aPrincipal->IsSystemPrincipal()) {
  return IPC_FAIL(this, "Content process cannot claim SystemPrincipal");
}
// Additionally: bind aPrincipal to the sender ContentParent's actual principal

Structural fix: reject TSystemPrincipalInfo from content processes in PrincipalInfoToPrincipal() or add sender binding at the RecvCreateNotificationParent() level.

Flags: sec-bounty?
Group: firefox-core-security → dom-core-security
Component: Security → DOM: Notifications
Product: Firefox → Core

Protecting notifications (and indeed, many other permissions) against a compromised child process is not currently part of our threat mode.

Status: UNCONFIRMED → NEW
Ever confirmed: true
Keywords: sec-other
Severity: -- → S3
Duplicate of this bug: 2031811

The severity field for this bug is set to S3. However, the following bug duplicate has higher severity:

:edenchuang, could you consider increasing the severity of this bug to S2?

For more information, please visit BugBot documentation.

Flags: needinfo?(echuang)
Flags: needinfo?(echuang)
Duplicate of this bug: 2045654
Duplicate of this bug: 2047387
Assignee: nobody → tschuster
Attached file (secure) —
Pushed by tschuster@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/bea061d95a2b https://hg.mozilla.org/integration/autoland/rev/f1b3663e027b Validate principal in BackgroundParentImpl::RecvCreateNotificationParent. r=saschanaz
Group: dom-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → 154 Branch
Flags: sec-bounty? → sec-bounty-
QA Whiteboard: [sec] [qa-triage-done-c155/b154]
See Also: → 2057382

Do we want to do anything for ESR153?

Flags: needinfo?(tschuster)

firefox-esr153 Uplift Approval Request

  • User impact if declined/Reason for urgency: General hardening of principals in IPC
  • Code covered by automated testing?: yes
  • Fix verified in Nightly?: yes
  • Needs manual QE testing?: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: Simple patch and we haven't seen any crashes from this apparently.
  • String changes made/needed?: no
  • Is Android affected?: yes
Attachment #9620312 - Flags: approval-mozilla-esr153?
Attached file (secure) —
Flags: needinfo?(tschuster)
Attachment #9620312 - Flags: approval-mozilla-esr153? → approval-mozilla-esr153+
Blocks: 2024537
Duplicate of this bug: 2063504
Whiteboard: [client-bounty-form] → [client-bounty-form][adv-main154-]
Whiteboard: [client-bounty-form][adv-main154-] → [client-bounty-form][adv-main154-][adv-esr153.1-]
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: