Closed Bug 1892797 Opened 2 years ago Closed 2 years ago

NMH binaries can be manipulated through Firefox process impersonation

Categories

(WebExtensions :: General, defect)

defect

Tracking

(Not tracked)

RESOLVED INVALID

People

(Reporter: kristina.vevia, Unassigned)

References

Details

(Keywords: reporter-external, sec-other, Whiteboard: [reporter-external] [client-bounty-form] [verif?])

Attachments

(1 file)

Attached file command-process.c

SUMMARY
All versions of Firefox on Linux and macOS are susceptible to impersonation attacks in the Native Messaging component which allow compromising existing security checks that NMH binaries rely on. No integrity checks exist to ensure that the helper process is talking to a particular browser extension inside of Firefox. We've created a proof of concept that is able to leverage execv and fork to launch Firefox and the NMH binary in such a way as to have control over the NMH stdin and stdout to effect an attack against the browser extension and its native application.

REPRODUCTION CASE
Bypassing security controls using this lack of verification can be accomplished by compiling the attached C file into a binary (clang command-process.c -o command-process), and then executing it on a macOS system. It is runnable on Linux as well, with slight path modifications in the source.

The program demonstrates the ability for same-user malicious executables to impersonate a legitimate Firefox instance and make it impossible for native messaging binaries to verify the context they’re operating in or if their intended browser extension is actually what they are communicating with.

ISSUE DISCOVERY
One of our customers' internal security teams researched and discovered the underlying issue, and we've since done further investigation and attempts at mitigation. We can provide significant details into what we've investigated so far if desired.

ATTACHMENTS
Proof of concept also requires installation of 1Password and 1Password Browser Extension.

Flags: sec-bounty?

(For context, this bug has arrived as a security bug in the general Firefox security triage queue, and although I have a basic grasp of our extension infrastructure and native messaging as a concept, I am not overly familiar with it.)

Are "NMH binaries" here just any kind of binary that expects to be invoked for Native Messaging purposes by a browser? Or are you talking about a specific library or app? (a web search does not suggest that this term is in frequent use relating to native messaging - instead I see "new email handler" and all sorts of other things)

Does this vulnerability affect any other web browsers (as native messaging is standardized and also implemented by Chrome et al.) , and if so have you filed issues against those, and if so can you link them here so we can coordinate disclosure etc. if necessary (ie avoid 0-daying the other vendors) ?

Can you say a bit more about what threat model you're assuming here? The attacker can run local already-present binaries with an arbitrary commandline?

make it impossible for native messaging binaries to verify the context they’re operating in or if their intended browser extension is actually what they are communicating with.

Can you elaborate on what kind of possibility of verification you are expecting here? That is, are you suggesting there needs to be some extension to the protocol that the native messaging app uses to "verify" the browser before... doing anything? Or are you saying that this already exists and Firefox is allowing a bypass in some way that you think it ought to defend against before execution reaches the native messaging app? Or something else still?

Component: Security → General
Flags: needinfo?(kristina.vevia)
Product: Firefox → WebExtensions

Kristina, what integrity checks are possible on Windows and not possible on MacOS/Linux?

Does this attack require attacker to run their code on the victims computer?

Greetings Gijs and Sergey -

NMH binaries do mean any binaries invoked by Native Messaging. This vulnerability also impacts Chrome, and we have reported the issue to them as well. It should be noted this is not an issue in Safari, which uses XPC and doesn't use file pipes.

The issue we reported to Google/Chrome is still private to Google only, so we are unable to share. We are working with the reporter to us to collaborate on coordinate disclosure.

The threat model is a local attacker with the same permissions as a standard user. It does require the attacker to run code on the victim's computer, but no elevated permissions are required.

While no functionality to help perform runtime integrity checks for Native Messaging binaries exists in browsers today, we are looking to have some functionality added to Firefox which can support us and let our code prove it was intently spawned by Firefox.

Windows may also impacted, but due to how different the process spawning model is, we're unsure and haven't spent too much time looking into it at this juncture.

Thanks!

Flags: needinfo?(kristina.vevia)

It looks like the report describes a potential risk in the native messaging binary of a specific extension. From the perspective of that extension, it is indeed true that there is no guarantee that it is talking with the desired browser, because the native messaging host protocol does not include any information that can be used to perform such checks. This is not a security issue in Firefox (nor Chrome), but at best a feature request.

All versions of Firefox on Linux and macOS are susceptible to impersonation attacks in the Native Messaging component

From this sentence and the PoC (which launches Firefox), I get the impression that there may be confusion on what native messaging does, on your end, so I'll summarize. The native messaging API consists of three parts:

  1. A registration mechanism (docs) - applications external to Firefox/Chrome can write metadata to a specific location for use by these browsers.
  2. A launch mechanism - extensions within Firefox/Chrome can ask the browser to launch the native messaging host binary, and if permitted by the registration, the browser will do so.
  3. A communication protocol - a convention for the stdin/stdout wire format between the browser and the native messaging host binary. The binary is also passed the identifier of the extension so that it can know which extension was supposedly permitted.

As you can see from the protocol, at no point is the browser launched through "native messaging".
Nor is there any need to "impersonate" the browser, because Native messaging applications can be invoked directly without the involvement of the browser, and this is a feature that can also be used to debug native messaging host binaries.

which allow compromising existing security checks that NMH binaries rely on.

What are the existing security checks that NMH binaries rely on?

No integrity checks exist to ensure that the helper process is talking to a particular browser extension inside of Firefox.

If the native messaging host is invoked by Firefox, then an extension ID is passed to the argument list (docs).
The protocol does not define any way for the native messaging host binary ("helper process") to know for certain that it is talking with the browser. Any kind of mitigation can be bypassed when the adversary has the same capabilities as the user that launches the browser.

This report is not really Firefox-specific; if there is any action to take, it would be an enhancement in a cross-browser API. I have therefore reached out to the Chrome extensions team at Google to ask about the counterpart to this bug report.

The Chromium bug is https://crbug.com/334764458

I got access to the crbug, and their conclusion is similar to ours here: this is not a security vulnerability, but a feature request. Despite not being a security issue, the crbug has limited visibility (Google-only) as requested by the reporter.

The bug in its current form is not actionable to us here, because there is a request for a capability under an attacker model that is generally out of scope for the browser. If you have suggestions on design improvements that is not just security theater, please add them here.

Group: firefox-core-security → core-security-release
Flags: sec-bounty? → sec-bounty-
Keywords: sec-other

Just to update, I am working on getting a response to your last question. One of our leads working on this was out sick this week. Thanks for your patience!

The severity field is not set for this bug.
:zombie, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(tomica)

Kristina, any update?

Flags: needinfo?(tomica)

Hey everyone, sorry for the delays on 1Password's side. This is the proposal that we've drafted up, and includes a section on threat modeling/usefulness against attackers:

Proposal

We propose browsers implement a method for NMH binaries to verify that their associated browser process spawned them. This is done by having the native messaging host protocol include an additional IPC-accessible API to allow NMH binaries to perform additional validation on how they are spawned.
The API specifically would allow an NMH binary to verify that the image currently running in the parent process was the code which spawned it and not a previous untrusted process image. Browsers should do the following:

  • Keep an in-memory record of creating helper processes.
  • Create a UNIX socket inside of somewhere like /tmp/browser-name/pid/nmh-check.
  • Starting a server listening on this UNIX socket. The server listens for requests, which contain a UTF-8 string of the browser extension ID the helper is associated with.
  • Upon receiving a request with the browser extension name - if the browser has an in-memory record of creating the helper process - the browser responds with a message containing the PID of the running NMH binary’s process.

The browser may utilize SO_PEERCRED information to reject messages from unassociated processes. It is expected that the NMH binary would utilize SO_PEERCRED to validate that the process who owns the UNIX socket server is indeed its parent process.
Checking the value of getppid before and after this sequence can confirm that the parent process wasn’t killed in an attempted PID recycling attack, as the child process can observe if it was reassigned to the OS’s init process.

Threat Model

macOS

On macOS, the operating system provides strong process isolation boundaries and makes process trust verification readily available. For the former, the hardened runtime and SIP set a high bar to stop process tampering. In a traditional child/parent IPC model, or even client/server, both sides are able to readily verify what they are talking to and that each process side is only running what they expect. This can be accomplished through a mixture of code signing identity syscalls and using high-integrity IPC mechanisms like Mach Ports/XPC or putting together multiple verification methods.

As such, if browsers provide a native API which helper binaries can retrieve sufficient context information from, the existing platform security will allow secrets to move from a native app into a browser extension securely.

Linux

Desktop Linux environments aren’t consistent, nor are they universally secure by default like macOS is. However some distributions ship with more secure defaults and others can be tuned by more technical users to provide a safer environment for processes to run in.
On Linux, 1Password achieves resistance (not full protection by default) against malware that runs under same-user permissions (if process debugging is not permissively enabled, which many Linux distributions opt for). We do this by leveraging and validating package manager based installations, performing process tree validation, and UNIX groups.

The browser native API provided would allow 1Password and other apps to consistently enforce those validations to prevent same-user level malware attacks.

The severity field is not set for this bug.
:rpl, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(lgreco)

(In reply to kristina.vevia from comment #3)

The threat model is a local attacker with the same permissions as a standard user. It does require the attacker to run code on the victim's computer, but no elevated permissions are required.

I do not understand how the proposal in comment #10 helps in this situation.

If I were an attacker, I could run the browser in question using the Chrome Remote protocol, marionette / webdriver / selenium / webdriver-bidi, or similar. Then I could talk to the extension through the browser process, and according to the security mechanisms you describe in comment #10, the browser would present everything as being A-OK as far as the webextension is concerned.

Did you evaluate this possibility / am I missing some way in which your proposal would help with this?

Even besides the automation factor, attackers could additionally probably launch the browser with arbitrary commandline arguments or environment variables set that break/disable certain security boundaries (SOP etc.). And sure, a webextension might be able to check if some/all of those are present, but it would be an ever-present arms race in terms of what flags browsers add/support and how the webextension reacts to the presence of such flags (and completely refusing to work would probably frustrate automated testing of the same webextension for development purposes).

Given these factors, I expect it's very close to impossible to defend against a local attacker. (And of course, Windows is the big elephant in the room in terms of number of users, and hasn't really been discussed here - but all the possibilities I'm describing apply there, too.)

Flags: needinfo?(complexspacescode)

Clearing needinfo, Rob will be setting a priority and severity, currently there is still an ongoing discussion to better assess this issue.

Flags: needinfo?(lgreco)

We really appreciate your responses, and you make good points. At this time we don't have a sufficient alternative response for you.

One interesting response that came up in our internal conversations is it’d be very difficult to hide the browser from view as it tries to automate itself through a bunch of websites, as opposed to the silent exfiltration option that is possible today. We agree we likely cannot protect against the entire class of attack, however we always like to improve security where we can.

Likely for now this issue can either be moved to a more appropriate location, e.g.; a feature request, or your team is welcome to close it if that isn't an option. We do ask that we keep it private for now, as our team still needs to work on a risk mitigation option for our customers before the issue is disclosed. You'll see in our Chrome report that is similarly where we left it. Thanks!

(In reply to kristina.vevia from comment #14)

it’d be very difficult to hide the browser from view as it tries to automate itself through a bunch of websites, as opposed to the silent exfiltration option that is possible today.

You could just use --headless or equivalent, or (on Linux), send the window to an alternative X display using environment variables designed for that purpose.

Because this bug is not actionable in its current form (and not a security bug in Firefox) I'll just close it.

If you have concrete proposals that makes a difference, I suggest raising API proposal discussions in the WebExtensions Community Group (WECG), at https://github.com/w3c/webextensions/

The bug is currently hidden on your request. Please let us know when this bug (and the Chromium issue) can be disclosed publicly, because that makes it easier to use the discussion here as a basis for future feature requests.

Status: UNCONFIRMED → RESOLVED
Closed: 2 years ago
Resolution: --- → INVALID

Hello - we will be ready for this issue (and the Chromium issue) to be shared publicly after August 12. Can you please confirm if you need anything else from our end? Thanks!

Would you like us to make this bug visible to the public around that date?

Flags: needinfo?(complexspacescode)

Yes, that would be great. Thanks!

I'm lifting the visibility restrictions of the bug as requested before.

This was publicly disclosed by 1Password at https://blog.1password.com/august-2024-security-update/
Ctrl-F "NMH Binary manipulation through browser process impersonation (originally reported as: Browser Support getppid bypass)" for the specifics.

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: