Race condition in firefox!sandbox::CopyPolicyToTarget leading to Information Disclosure of broker heap address
Categories
(Core :: Security: Process Sandboxing, defect, P1)
Tracking
()
People
(Reporter: mastho64, Assigned: bobowen)
References
Details
(Keywords: csectype-disclosure, reporter-external, sec-moderate, Whiteboard: [fix in bug 1599005][reporter-external] [client-bounty-form] [verif?][adv-main72+][adv-esr68.4+])
Attachments
(2 files, 1 obsolete file)
Hi,
These issues only affects Windows client, I found two race condition in the shared memory of Firefox sandbox implementation.
- Information Disclosure of broker heap address in CopyPolicyToTarget (described in this issue)
- Memory corruption (Sandbox escape) in sandbox::SharedMemIPCServer::ThreadPingEventReady (described in issue 1599005)
Vulnerability:
Since Firefox (current version tested 70.0.1) configures the renderer sandbox with USER_LIMITED and Initial Integrity Level == Delayed Integrity Level (INTEGRITY_LEVEL_LOW), any renderer process can interact with other renderers process (read/write/createthread/duplicatehandles) even while new renderer process bootstrapping (when a new tab process is spawned).
Google Chrome is not affected because the renderer processes runs with a USER_LOCKDOWN token (also the initial integrity level = LOW and delayed IL is UNTRUSTED) which prevent access to other renderer processes.
The race condition vulnerability happens during new process bootstrapping, when a new tab process is created, the broker does:
1/ CreateProcess SUSPENDED with the lockdown token (USER_LIMITED for Firefox renderer) and low IL in TargetProcess::Create
2/ Assign target process to JOB object
3/ Change target thread token to initial token (USER_RESTRICTED_SAME_ACCESS) for initialisation later
4/ Create IPCServer shared memory in TargetProcess::Init
5/ DuplicateHandle the shared memory with the target in TargetProcess::Init
6/ Copy policy and update pointers in CopyPolicyToTarget
So, the target process is suspended but other tabs are not and they can access the target process (thanks to USER_LIMITED token and same IL) and duplicate the IPC shared memory handle.
A race condition exists when the policy is copied to the shared memory (containing broker heap addresses) before it updates policy->entry[i] pointers in CopyPolicyToTarget (6):
void CopyPolicyToTarget(const void* source, size_t size, void* dest) {
if (!source || !size)
return;
memcpy(dest, source, size); // (A) dest is shared memory and source contains broker heap pointers
sandbox::PolicyGlobal* policy =
reinterpret_cast<sandbox::PolicyGlobal*>(dest);
size_t offset = reinterpret_cast<size_t>(source);
for (size_t i = 0; i < sandbox::kMaxServiceCount; i++) {
size_t buffer = reinterpret_cast<size_t>(policy->entry[i]);
if (buffer) {
buffer -= offset;
policy->entry[i] = reinterpret_cast<sandbox::PolicyBuffer*>(buffer); // (B) remove the pointer base (race condition allows disclosure of heap address)
}
}
}
Source code:
https://github.com/mozilla/gecko-dev/blob/master/security/sandbox/chromium/sandbox/win/src/target_process.cc#L33
So, a compromised renderer can read the policy entries pointers before they are updated and it discloses broker heap addresses.
Repro:
The provided POC (attachment payload_infoleak) often triggers the vulnerability.
Install Python 2.7 64 bits and PythonForWindows (https://github.com/hakril/PythonForWindows) then run inject.py with the payload_infoleak.dll path.
Debug the injected tab to verify the information disclosure (in debug output).
Then start new tabs to trigger the vulnerability (like a regular user would do) until it works.
RaceItLeak entry
Leaked worked: dp payload_infoleak!leak_heap L1: 0000022D3486B198
(4220.3bdc): Break instruction exception - code 80000003 (first chance)
KERNELBASE!wil::details::DebugBreak+0x2:
00007ff9`b3720192 cc int 3
The address is a valid heap address in the broker process (you can verify using !address in the broker).
This information disclosure vulnerability allows an attacker to collect information that discloses the memory layout.
In turn the attacker could use this information to deliver tailored exploits to bypass memory protection technologies such as ASLR for an additional LPE/RCE vulnerability.
Thank you
Updated•5 years ago
|
Comment 1•5 years ago
|
||
Bob, do you know who might be able to take a look at this? Thanks.
Updated•5 years ago
|
Updated•5 years ago
|
Assignee | ||
Comment 2•5 years ago
|
||
Picking this up in bug 1599005.
Assignee | ||
Updated•5 years ago
|
Comment 3•5 years ago
|
||
(In reply to Bob Owen (:bobowen) from comment #2)
Picking this up in bug 1599005.
I'm interpreting this to mean that this is a separate issue from bug 1599005, but the patch you are posting there will fix both issues.
Comment 4•5 years ago
|
||
Dan, what should the rating for this bug be? If I'm reading this correctly, this leaks parent process addresses to the child process, if the child process already has arbitrary code execution. Thanks.
Assignee | ||
Comment 5•5 years ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #3)
(In reply to Bob Owen (:bobowen) from comment #2)
Picking this up in bug 1599005.
I'm interpreting this to mean that this is a separate issue from bug 1599005, but the patch you are posting there will fix both issues.
That's correct.
Comment 6•5 years ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #4)
Dan, what should the rating for this bug be?
A memory leak of an address (as opposed to large chunks of potentially sensitive user data) on its own is sec-moderate: a stepping stone used as part of an exploit chain.
Updated•5 years ago
|
Comment 7•5 years ago
|
||
Bug 1599005 is now landed in 72 and 73.
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Comment 8•5 years ago
|
||
Comment 9•5 years ago
|
||
Updated•5 years ago
|
Updated•5 years ago
|
Updated•4 years ago
|
Updated•6 months ago
|
Description
•