verlass / google-security-research

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

Truecrypt 7 Derived Code/Windows: Drive Letter Symbolic Link Creation EoP #538

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Truecrypt 7 Derived Code/Windows: Drive Letter Symbolic Link Creation EoP
Platform: Windows
Class: Local Elevation of Privilege
Tested on: VeraCrypt 1.13 x86 on Windows 10

Summary:
The Windows driver used by projects derived from Truecrypt 7 (verified in 
Veracrypt and CipherShed) are vulnerable to a local elevation of privilege 
attack by abusing the drive letter symbolic link creation facilities to remap 
the main system drive. With the system drive remapped it’s trivial to get a 
new process running under the local system account.

Description:

Any user on the system can connect to the Truecrypt device object and mount a 
new encrypted volume. As part of this process the driver will try and create 
the requested drive letter by calling IoCreateSymbolicLink. To prevent 
redefining an existing drive letter a call is made to IsDriveLetterAvailable 
which attempts to open the link “\DosDevices\X:” for reading, returning 
FALSE if it was successfully opened. The specific code in src\Driver\Ntdriver.c 
is:

if (NT_SUCCESS (ZwOpenSymbolicLinkObject (&handle, GENERIC_READ, 
&objectAttributes)))
{
     ZwClose (handle);
     return FALSE;
}
return TRUE;

The bug which allows you to bypass this is due to the use of the NT_SUCCESS 
macro. This means that any error opening the symbolic link will cause the drive 
letter to be assumed to not exist. If we can cause the open to fail in any way 
then we can bypass this check and mount the volume over an existing drive 
letter. This is possible because with terminal services support the \DosDevices 
path points to a special fake path \?? which first maps to a per-user writable 
location (under \Sessions\0\DosDevices) before falling back to \GLOBAL??. When 
the kernel creates a new object under \?? is creates it in the per-user 
location instead so there’s no conflict with a drive symbolic link in 
\GLOBAL??. So how to bypass the check? The simplest trick is to just create any 
other type of object with that name, such as an object directory. This will 
cause ZwOpenSymbolicLink to fail with STATUS_OBJECT_TYPE_MISMATCH passing the 
check.

This in itself would only cause problems for the current user if it wasn’t 
for the fact that there exists a way of replacing the current processes device 
map directory using the NtSetInformationProcess system call. You can set any 
object directory to this which allows you DIRECTORY_TRAVERSE privilege, which 
is pretty much anything. In particular we can set the \GLOBAL?? directory 
itself. So to exploit this and remap the C: drive to the truecrypt volume we do 
the following:

1) Set the current process’s device map to a new object directory. Create a 
new object called C: inside the device map directory. 
2) Mount a volume (not using the mount manager) and request the C: drive 
mapping. The IsDriveLetterAvailable will return TRUE.
3) Wait for the driver to open the volume and at that point delete the fake C: 
object (if we don’t do this then the creation will fail). While this looks 
like a race condition (which you can win pretty easily through brute force) you 
can use things like OPLOCKs to give 100% reliability. 
4) The mount will complete writing a new C: symbolic link to the device map.
5) Set the \GLOBAL?? directory as the new process device map directory.
6) Unmount the volume, this calls IoDeleteSymbolicLink with \DosDevices\C: 
which actually ends up deleting \GLOBAL??\C:
7) Remount the volume as the C: drive again (you’ll obviously need to not use 
C: when referring to the volume location). The user now has complete control 
over the contents of C:.

Fixing the Issue:
While technically IsDriveLetterAvailable is at fault I don’t believe fixing 
it would completely remove the issue. However changing IsDriveLetterAvailable 
to only return FALSE if STATUS_OBJECT_NAME_NOT_FOUND is returned from the 
ZwOpenSymbolicLink object would make it a lot harder to bypass the check. Also 
I don’t know if specifying the use of the mount volume driver would affect 
this.

The correct fix would be to decide where the symbolic link is supposed to be 
written to and specify it explicitly. As in if you want to ensure it gets 
written to the current user’s drive mapping then specify the per-user 
directory at \Sessions\0\DosDevices\X-Y where X-Y is the authentication ID got 
from the SeQueryAuthenticationIdToken API. Or if it’s supposed to be in the 
global drive names then specify \GLOBAL??. Note this probably won’t work on 
pre-fast user switching versions of XP or Windows 2000 (assuming you’re still 
willing to support those platforms). Also I’d recommend if going the per-user 
route then only use the primary token (using PsReferencePrimaryToken) to 
determine the authentication ID as that avoids any mistakes with impersonation 
tokens. There’s no reason to believe that this would cause compat issues as I 
wouldn’t expect the normal user tool to use impersonation to map the drive 
for another user. 

Note this wasn’t reported in the iSec Partners security review so it’s not 
an missed fix.

Proof of Concept:
I’ve provided a PoC, you’ll need to build it with VS2015. It will change an 
arbitrary global drive letter to a VeraCrypt volume. Note it only works on 
VeraCrypt but it might be possible to trivially change to work on any other 
truecrypt derived products. You MUST build an executable to match the OS 
bitness otherwise it will not work. To test the PoC use the following steps.

1. Create a veracrypt volume using the normal GUI, the PoC doesn’t do this 
for you. Don’t mount the volume.
2. Execute the PoC, passing the drive letter you want to replace, the path to 
the volume file and the password for the file. e.g. MountVeracryptVolume C: 
c:\path\to\volume.hc password.
3. If all worked as expected eventually the PoC should print Done. At this 
point the drive letter you specified has been replaced with the truecrypt 
volume. As long as you have a command prompt open you should be able to see 
that the C: drive is now pointing at the encrypted volume. You can hit enter to 
exit the program and unmount the volume, however if you’ve replaced the 
system drive such as C: this will likely cause the OS to become unusable pretty 
quickly.

Expected Result:
It shouldn’t be possible to mount the volume over a global drive.

Observed Result:
The global drive specified has been replaced with a link to the encrypted 
volume.

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 18 Sep 2015 at 9:35

Attachments:

GoogleCodeExporter commented 9 years ago
Fixed in Veracrypt 1.15, see 
https://veracrypt.codeplex.com/wikipage?title=Release%20Notes

Original comment by fors...@google.com on 26 Sep 2015 at 9:51

GoogleCodeExporter commented 9 years ago
A quick note on exploitability from sandboxes. The Veracrypt device object (and 
by extension Truecrypt's) is accessible from a typical low integrity sandbox 
such as IE PM. It's also available from the normal Adobe Reader and Chrome GPU 
sandboxes. However it can't be accessed from IE EPM, Edge or Chrome Renderer 
sandboxes.

The situation is made slightly worse because the IOCTLs are not restricted to 
requiring write access, so even if the device object was restricted to read 
access (through integrity level for example) it wouldn't block the exploit. 
Although in this situation pretty much any place you can access the device node 
for read you can also access for write.

Original comment by fors...@google.com on 28 Sep 2015 at 9:53

GoogleCodeExporter commented 9 years ago
Remove view restrictions 

Original comment by fors...@google.com on 3 Oct 2015 at 4:50

GoogleCodeExporter commented 9 years ago

Original comment by fors...@google.com on 3 Oct 2015 at 4:51