Windows sandbox: renderer processes can open each and unrelated Chromium processes
Categories
(Core :: Security: Process Sandboxing, defect, P1)
Tracking
()
People
(Reporter: niklas.baumstark, Assigned: bobowen)
References
Details
(4 keywords, Whiteboard: [reporter-external] [client-bounty-form][post-critsmash-triage][adv-main76+][adv-ESR68.8+])
Attachments
(1 file, 1 obsolete file)
263 bytes,
text/plain
|
Details |
Chromium uses the following code to prevent access between renderers, and from renderers to other low integrity processes: https://cs.chromium.org/chromium/src/services/service_manager/sandbox/win/sandbox_win.cc?l=430
result = policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
sandbox::USER_LOCKDOWN);
if (result != sandbox::SBOX_ALL_OK)
return result;
// Prevents the renderers from manipulating low-integrity processes.
result = policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
In SandboxBroker::SetSecurityLevelForContentProcess of Firefox with aSandboxLevel < 20 however, the delayed integrity level is set to INTEGRITY_LEVEL_LOW: https://dxr.mozilla.org/mozilla-central/source/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp#432
This means that content processes can open and manipulate each other, and also to some other Chromium-based processes such as the Chrome or Electron GPU process (an example is the Slack desktop application). I verified this in Firefox 67 by attaching to a renderer process with WinDbg and calling OpenProcess(PROCESS_VM_WRITE, 0, <PID>) to check if the result is non-zero. The steps for doing so are as follows (on Windows 10):
bp kernel32!ReadFile
g
# wait for breakpoint to hit
eq KERNEL32!_imp_ReadFile kernel32!OpenProcessStub
eq @rsp deadbeef
r @rcx=0x20
r @rdx=0
r @r8=0n<PID>
g
# will crash at 0xdeadbeef because we changed the return address
r @rax # non-zero if opening was successfully
One direct consequence of this within Firefox itself is that a web renderer process can escalate privileges to file and web extension processes which are potentially more trusted. See also bug 1538028, file processes can read the entire filesystem.
Another consequence is that we can get control of a process before it calls LowerToken(). This clearly goes against the idea of the sandbox, even though it probably only means a minor increase of kernel attack surface in the case of Firefox. If a Chromium-like win32k lockdown mechanism will ever be introduced in the future, this would be a bypass.
Also, I could imagine that this could affect site isolation in the future.
Updated•5 years ago
|
Assignee | ||
Comment 1•5 years ago
|
||
Thanks Niklas, it's useful having this explicitly in a bug (which I don't think we already have), but this is a known issue.
We are working towards moving to untrusted integrity level at the same time as win32k lockdown.
Many of the things that block that also block us from using untrusted integrity.
Reporter | ||
Comment 3•5 years ago
|
||
In the meanwhile, you're fine with essentially presenting the entire host filesystem to a compromised renderer?
Comment 4•5 years ago
|
||
he did say "working towards moving to untrusted integrity level" -- that's not "fine with it", it's just hard retrofitting into a decade plus of the wrong architecture.
If a Chromium-like win32k lockdown mechanism will ever be introduced in the future, this would be a bypass.
We're working hard on that, too.
Reporter | ||
Comment 5•5 years ago
|
||
I guess I misposed the question: Unless Firefox requires doing OpenProcess for legitimate purposes, shouldn't it be possible to fix this bug without moving to untrusted integrity, and would that not be a warranted approach to this issue?
Reporter | ||
Comment 6•5 years ago
|
||
Somebody already wrote about the fact that this is possibly publicly, probably without realizing the security implications: https://github.com/0vercl0k/CVE-2019-9810#organization
Assignee | ||
Comment 7•5 years ago
|
||
(In reply to Daniel Veditz [:dveditz] from comment #4)
he did say "working towards moving to untrusted integrity level" -- that's not "fine with it", it's just hard retrofitting into a decade plus of the wrong architecture.
If a Chromium-like win32k lockdown mechanism will ever be introduced in the future, this would be a bypass.
We're working hard on that, too.
I'd also add that it's not quite as simple as presenting the entire host filesystem to a compromised renderer.
The vast majority of the time the file content process will not be running and, other bugs that need fixing aside, in theory a compromised renderer should not be able to force the parent process to start it.
That said my thanks in comment 1 was genuine, this is one of the things that we knew would be addressed by moving to untrusted, but having this bug filed has raised the awareness of that within Mozilla.
Assignee | ||
Comment 8•5 years ago
|
||
(In reply to Niklas Baumstark from comment #5)
I guess I misposed the question: Unless Firefox requires doing OpenProcess for legitimate purposes, shouldn't it be possible to fix this bug without moving to untrusted integrity, and would that not be a warranted approach to this issue?
If you have ideas about how we can prevent this without going to untrusted then that would be great.
Reporter | ||
Comment 9•5 years ago
|
||
I was thinking about a ObRegisterCallbacks hook on PsProcessType, which I believe is the canonical anti-debugging trick on Windows.
Reporter | ||
Comment 10•5 years ago
|
||
Maybe this can also be done with just normal ACLs, unfortunately I'm not an expert in Windows security
Assignee | ||
Comment 11•5 years ago
|
||
(In reply to Niklas Baumstark from comment #9)
I was thinking about a ObRegisterCallbacks hook on PsProcessType, which I believe is the canonical anti-debugging trick on Windows.
Ah right we don't currently use kernel drivers, so this solution would not be straight forward to roll out and indeed could introduce worse vulnerabilities.
It might also be possible for the process to work around such hooking.
Reporter | ||
Comment 12•5 years ago
|
||
Oh I didn't realize this is a kernel API, please ignore. Anyways, will let you know if I come across anything useful.
Assignee | ||
Comment 13•5 years ago
•
|
||
(In reply to Niklas Baumstark from comment #10)
Maybe this can also be done with just normal ACLs, unfortunately I'm not an expert in Windows security
It looks like you can do exactly this, thanks!
The CreateProcessAsUser function can take two LPSECURITY_ATTRIBUTES arguments, which allows you to set the security descriptor for the process and thread.
If I pass a security descriptor with just the user in the dacl, then the OpenProcess fails, because the normal content processes have the user removed from their access token.
Then I found a setting that had been added to the sandbox policy a while ago that doesn't add the Restricted SID and removes the Logon SID from the ACL on the access token used to create the process.
This is what is used to get the security descriptor if null is passed for the LPSECURITY_ATTRIBUTES for the process and thread, so this is a really simple change to achieve the same result.
Reporter | ||
Comment 14•5 years ago
|
||
If I understand you correctly, then taking the approach of modifying the token privileges rather than the process ACL is preferrable because it would also deal with the issue of the Chromium/Electron renderers.
Assignee | ||
Comment 15•5 years ago
|
||
Assignee | ||
Updated•5 years ago
|
Reporter | ||
Comment 16•5 years ago
|
||
Bob, is it possible for me to get access to this patch to test it on my local build, just out of curiosity?
Assignee | ||
Comment 17•5 years ago
|
||
(In reply to Niklas Baumstark from comment #14)
If I understand you correctly, then taking the approach of modifying the token privileges rather than the process ACL is preferrable because it would also deal with the issue of the Chromium/Electron renderers.
Well it would potentially prevent other low integrity processes from opening our process (if they didn't have the User SID).
This doesn't affect whether our process can open other low integrity processes, we would need untrusted or a more restrictive access token for that, but it's a big step in the right direction.
For example the low integrity internet explorer process still has the Logon SID in its ACL with read access.
We still have that SID in our access token (this just removes it from our processes ACL), so we should still be able to get read access to that IE process.
(In reply to Niklas Baumstark from comment #16)
Bob, is it possible for me to get access to this patch to test it on my local build, just out of curiosity?
Given that this is just a one line policy change, I'll paste it in here.
diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -502,6 +502,8 @@ void SandboxBroker::SetSecurityLevelForC
sandbox::SBOX_ALL_OK == result,
"SetDelayedIntegrityLevel should never fail, what happened?");
+ mPolicy->SetLockdownDefaultDacl();
+
sandbox::MitigationFlags mitigations =
sandbox::MITIGATION_BOTTOM_UP_ASLR | sandbox::MITIGATION_HEAP_TERMINATE |
sandbox::MITIGATION_SEHOP | sandbox::MITIGATION_DEP_NO_ATL_THUNK |
Assignee | ||
Comment 18•5 years ago
|
||
Comment on attachment 9069004 [details]
Bug 1554110: SetLockdownDefaultDacl for content process sandbox policy. r=jmathies!
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Not by itself, this is something that could contribute to a sandbox escape.
It wouldn't take long for someone with the necessary understanding to work out what this protects against.
I think landing this under a separate non security bug would be a good idea. - Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
- Which older supported branches are affected by this flaw?: All
- If not all supported branches, which bug introduced the flaw?: None
- Do you have backports for the affected branches?: No
- If not, how different, hard to create, and risky will they be?: If the patch doesn't apply or rebase, then it will be trivial to create new patches.
- How likely is this patch to cause regressions; how much testing does it need?: Unlikely, because sandboxed processes shouldn't be attempting to open each other.
There is a very small risk that this could interfere with other software that might try to open our processes, but I think that is unlikely because they would tend to be running with more privileges anyway.
Updated•5 years ago
|
Comment 19•5 years ago
|
||
Comment on attachment 9069004 [details]
Bug 1554110: SetLockdownDefaultDacl for content process sandbox policy. r=jmathies!
sec-approval+ for trunk. We'll want this on beta and ESR60 as well so please create and nominate patches for those branches.
Assignee | ||
Comment 20•5 years ago
|
||
(In reply to Al Billings [:abillings] from comment #19)
Comment on attachment 9069004 [details]
Bug 1554110: SetLockdownDefaultDacl for content process sandbox policy. r=jmathies!sec-approval+ for trunk. We'll want this on beta and ESR60 as well so please create and nominate patches for those branches.
Landed via bug 1557282 (deliberately not linked).
The patch for m-c imports cleanly for beta, I'll add one for ESR60 on bug 1557282.
NI to jcristau and RyanVM, so they're aware of this for the approval requests, which I'll make on that bug.
Updated•5 years ago
|
Assignee | ||
Comment 21•5 years ago
|
||
This has just been backed out, looks like some audio/media issue.
Comment 22•5 years ago
|
||
I guess this won't make 68 at this point.
Assignee | ||
Comment 23•5 years ago
|
||
In bug 1557282 I'm going to try landing this again just for windows 10.
I've filed bug 1564842 for landing this for earlier versions, possibly once audio remoting has been enabled.
Comment 24•5 years ago
|
||
Comment on attachment 9069004 [details]
Bug 1554110: SetLockdownDefaultDacl for content process sandbox policy. r=jmathies!
Revision D33301 was moved to bug 1557282. Setting attachment 9069004 [details] to obsolete.
Comment 25•5 years ago
|
||
Too late for this cycle.
Comment 26•5 years ago
|
||
Bob, want to give this another try for 71/70?
Comment 27•5 years ago
|
||
Following up in email with Bob and jimm.
Comment 28•5 years ago
|
||
From email with :gcp, this is blocked partly by bug 1432303, and possibly by bug 1567385 as well.
Comment 29•5 years ago
|
||
Following up in email with :kinetik and :drno.
Comment 30•5 years ago
|
||
From discussion with kinetik, we are aiming a fix at 71.
Assignee | ||
Comment 31•5 years ago
|
||
(In reply to Liz Henry (:lizzard) from comment #30)
From discussion with kinetik, we are aiming a fix at 71.
Thanks lizzard (sorry, must have missed this comment first time, only noticed with the email from the CCs being added).
One idea we had (if the audio issue is fixed), is to only call SetLockdownDefaultDacl on the processes that we want to protect.
So, the file content process and certain other "privileged" content processes. In the hope that we can live with the performance and profiling issues in those processes.
I think it should be fairly straight forward to pass through the remote type instead of just a bool for the file content process to [1]
tjr - I think you're more familiar with these new remote types - which ones do you think we would need to protect? (Also, do you think that we might live with the other issues in these process types?)
Comment 32•5 years ago
|
||
We have three types of content processes we would want to protect: file, privilegedabout, and privilegedmozillacontent. privilegedabout hosts about:newtab and that's got to be fast. privilegedmozillacontent hosts FXA which does in-browser crypto so while it's not a bright red flag like newtab, it is something to be somewhat concerned about.
Note that once we get Fission, we would also need to apply this to regular content processes too. If that isn't done in this bug, it should be a separate bug that blocks Bug 1505832
It's an ugly dependency graph to draw out "If we apply it to X but not Y we're leaving ourselves vulnerable to Z which negates the benefit of applying it to X" - but I don't think that's necessary. If we can apply it to X, we should, even if we don't derive the benefit today.
Updated•5 years ago
|
Comment 33•5 years ago
|
||
Should we mark this bug as stalled?
Comment 34•5 years ago
|
||
(In reply to Ryan VanderMeulen [:RyanVM] from comment #33)
Should we mark this bug as stalled?
No; it's blocked on Audio IPC but there is no additional information we need (that we can't get) to justify marking it stalled.
Updated•5 years ago
|
Assignee | ||
Comment 35•5 years ago
|
||
Update on recent progress on regressions caused by the SetLockdownDefaultDacl fix:
- Audio remoting is riding the trains.
- I have a patch for the profiler stack issue.
- Performance issues appear to be multifaceted:
- OpenProcessToken - reasonably good fix for this to prevent brokering to the parent.
- Appears to break DWrite cache (which we think we need to do deliberately at some point) - this does not affect us when there is no acceleration or when webrender is enabled, so could enable in those cases.
- Two above appear to fix tabswitch performance regressions (bug 1567385), but not tp6 cold start regressions (bug 1566744), need to investigate those further.
Updated•5 years ago
|
Comment 36•5 years ago
|
||
Bob, has this been fixed now that bug 1618911 landed?
Assignee | ||
Comment 37•5 years ago
|
||
(In reply to Gian-Carlo Pascutto [:gcp] from comment #36)
Bob, has this been fixed now that bug 1618911 landed?
Yes, I've resolved instead of duplicated, because the attacks were different even though the underlying cause and fix were the same.
Updated•5 years ago
|
Updated•5 years ago
|
Comment 38•5 years ago
|
||
If the fix in bug 1618911 was backported to ESR68, is this bug also fixed in ESR68? It got marked "wontfix" a couple months ago for some reason.
Assignee | ||
Comment 39•5 years ago
|
||
(In reply to Daniel Veditz [:dveditz] from comment #38)
If the fix in bug 1618911 was backported to ESR68, is this bug also fixed in ESR68? It got marked "wontfix" a couple months ago for some reason.
yeah, I guess it was originally a won't fix, but that changed with the severity being increased due to the full escape
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Comment 40•5 years ago
|
||
Updated•5 years ago
|
Updated•5 years ago
|
Comment 41•4 years ago
|
||
Same root cause as bug 1618911, different exploit strategy. Also opening up.
Updated•3 years ago
|
Updated•5 months ago
|
Description
•