bingghost / google-security-research

Automatically exported from code.google.com/p/google-security-research
0 stars 0 forks source link

Windows: Sandboxed Mount Reparse Point Creation Mitigation Bypass #486

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
Windows: Sandboxed Mount Reparse Point Creation Mitigation Bypass
Platform: Windows 10 (build 10240), earlier versions do not have the 
functionality
Class: Security Feature Bypass

Summary:
A mitigation added to Windows 10 to prevent NTFS Mount Reparse Points being 
created at integrity levels below medium can be bypassed. 

Description:

Windows 10 has added some new mitigations to block the creation or change the 
behaviour of certain symbolic links when issued by a low integrity/sandboxed 
process. The presumed aim to to make it harder to abuse these types of tricks 
to break out of a sandbox. 

In earlier builds on Windows 10 NTFS Mount Reparse Points were blocked outright 
from a sandboxed process, however in 10240 (what can only be assumed a final 
build) the check was moved to the kernel in IopXXXControlFile and changed 
slightly so that sandboxed processes could create some mount points. The check 
is roughly:

if (RtlIsSandboxedProcess()) {
   if(ControlCode == FSCTL_SET_MOUNT_POINT) {
       if (FsRtlValidateReparsePointBuffer(buffer) && buffer->ReparseTag == TAG_MOUNT_POINT) {
         NTSTATUS status = ZwOpenFile(..., buffer->ReparseTarget, FILE_GENERIC_WRITE, ... , FILE_DIRECTORY_FILE);
        if (!NT_SUCCESS(status)) {
         return status;
       }
   }
}

The kernel is therefore checking that the target of the mount point is a 
directory and that the current process has write access to the directory. This 
would sufficiently limit the ability of a sandboxed process to abuse this to 
write files at a higher privilege. Unfortunately there’s a perhaps unexpected 
problem with this check, the sandboxed process can redirect the ZwOpenFile call 
arbitrarily to something it can open for write, yet the original value is set 
as the mount point. This is because the file open check is being made inside 
the process which is doing the call which means it honours the user’s device 
mapping. 

While the sandboxed process cannot change the per-user drive mappings, it can 
change the process’s device map using NtSetInformationProcess with the 
ProcessDeviceMap information class. As we can create arbitrary object 
directories and symbolic links (which while they also have a mitigation it only 
prevents a higher privilege process following them, which we don’t care 
about) we can build a completely fake device map which redirects the open to 
another directory. A good target turns out to be \Device\NamedPipe\ (note the 
trailing slash) as that can be opened from any privilege level (including 
Chrome renderer processes) for write access and as a directory. So if we want 
to set an arbitrary mount point to say \??\c:\somewhere we can build something 
like:

<UNNAMED>(DIR) -> C:(DIR) -> somewhere(LINK to \Device\NamedPipe\)

If we set the unnamed directory to the process device map we can bypass the 
check and create the mount point. 

Perhaps from a fix perspective you could query for the opened path and use that 
to write to the NTFS reparse point rather than using the original value. 

Proof of Concept:

I’ve provided a PoC which will demonstrate the bypass. It should be executed 
at low integrity using psexec or modifying the executable file’s ACL to low. 
Ensure you use the correct version for the architecture on Windows, as there 
seems to be a bug in NtSetInformationProcess which blocks Wow64 apps from 
setting the process device map. You can compare the operation to the command 
shell’s mklink tool that will fail to create the mount point at low 
integrity. The archive password is ‘password’. Follow these steps: 

1) Extract the PoC to a location on a local hard disk which is writable by a 
normal user.
2) Execute the poc executable file as low integrity passing two arguments, the 
path to a directory to create (must be somewhere than can be written to as low 
integrity user such as AppData\Temp\Low) and the arbitrary file path to set the 
mount point to. For example:
poc.exe c:\users\user\appdata\local\low\abc c:\notreal.

Expected Result:
It shouldn’t be possible to create a mount point pointed at a location not 
writable by low integrity user

Observed Result:
The mount point is created successfully. 

This bug is subject to a 90 day disclosure deadline. If 90 days elapse without 
a broadly available patch, then the bug report will automatically become 
visible to the public.

Original issue reported on code.google.com by fors...@google.com on 22 Jul 2015 at 7:09

Attachments:

GoogleCodeExporter commented 8 years ago

Original comment by fors...@google.com on 22 Jul 2015 at 7:41

GoogleCodeExporter commented 8 years ago
The same technique for bypassing the mount point mitigation was discovered 
independently. A write up is available at 
http://blogs.360.cn/blog/windows10-mount-point-mitigation-bypass/ although that 
version couldn't be used in a heavily restrictive sandbox such as used for 
Chrome Renderers.

Requested Microsoft view on the publication of this issue considering the 
details are effectively public. As it's being fixed under the 90 day SLA they 
requested the issue remain restricted until a fix is available, or the deadline 
expires.

Original comment by fors...@google.com on 30 Sep 2015 at 12:55

GoogleCodeExporter commented 8 years ago
Fixed in MS15-111 https://technet.microsoft.com/library/security/MS15-111

Original comment by fors...@google.com on 13 Oct 2015 at 5:22

GoogleCodeExporter commented 8 years ago
Looking at the new kernel it's been fixed by blocking ProcessDeviceMap from a 
sandboxed process. Which adds some additional security for any kernel code or 
driver. Nice work MSRC.

As this bug has already been publicly disclosed there's no reason to keep is 
restricted. Removing the Restrict-View-Commit label.

Original comment by fors...@google.com on 13 Oct 2015 at 5:52