Tuesday, 27 May 2014

Abusive Directory Syndrome

As ever there's been some activity recently on Full Disclosure where one side believes something's a security vulnerability and the other says it's not. I'm not going to be drawn into that debate, but one interesting point did come up. Specifically that you can't create files in the root of the system drive (i.e. C:\) as a non-admin user, you can only create directories. Well this is both 100% true and false at the same time, it just depends what you mean by a "file" and who is asking at the time.

The title might give the game away, this is all to do with NTFS Alternate Data Streams (ADS). The NTFS file system supports multiple alternative data streams which can be assigned to a file, this can be used for storing additional attributes and data out-of-band. For example it is used by Internet Explorer to store the zone information for a downloaded file so the shell can warn you when you try to execute a file from Internet. Streams have names and are accessed using a special syntax, filename:streamname. You can easily create a data stream using the command prompt, type the following (in a directory you can write to):

echo Hello > abc
echo World! > abc:stm

more < abc  - Prints Hello
more < abc:stm - Prints World!

Easy no? Okay lets try it in the root of the system drive (obviously as a normal user):

echo Hello > c:\abc:stm - Prints Foxtrot Oscar
Oh well worth a try, but wait there's more...  One of the lesser known abilities of ADS, except to the odd Malware author, is you can also create streams on directories. Does this create new directories? Of course not, it creates file streams which you can access using file APIs. Let's try this again:

mkdir c:\abc
echo Fucking Awesome! > c:\abc:stm
more < c:\abc - File can't be found
more < c:\abc:stm - Prints Fucking Awesome!

Well we've created something which looks like a file to the Windows APIs, but is in the root of the system drive, something you're not supposed to be able to do. It seems deeply odd that you can:

  • Add an ADS to a directory, and 
  • The ADS is considered a file from the API perspective

Of course this doesn't help us exploit unquoted service paths, you can't have everything. Still when you consider the filename from a security perspective it has an interesting property, namely that its nominal parent in the hierarchy (when we're dealing with paths that's going to be what's separated by slashes) is C:\. A naive security verification process might assume that the file exists in a secure directory, leading to a security issue.

Take for example User Account Control (UAC), better know as the "Stop with the bloody security dialogs and let me get my work done" feature which was introduced in Vista. The service which controls this (Application Info) has the ability to automatically elevate certain executables, for controlling the UI (UIAccess) or to reduce the number of prompts you see. It verifies that the executables are in a secure directory such as c:\windows\system32 but specifically excludes writeable directories such as c:\windows\system32\tasks. But if you could write to Tasks:stm then that wouldn't be under the Tasks directory and so would be allowed? Well let's try it!

echo Hello > c:\windows\system32\tasks:stm
more < c:\windows\system32\tasks:stm - Access Denied :(

Why does it do that? We only have to take a look at the DACL to find out why, we have write access to Tasks but not read:

c:\>icacls c:\Windows\system32\tasks
c:\Windows\system32\tasks BUILTIN\Administrators:(CI)(F)
                          NT AUTHORITY\SYSTEM:(CI)(F)
                          NT AUTHORITY\SYSTEM:(OI)(R,W,D,WDAC,WO)
                          NT AUTHORITY\Authenticated Users:(CI)(W,Rc)
                          NT AUTHORITY\NETWORK SERVICE:(CI)(W,Rc)
                          NT AUTHORITY\LOCAL SERVICE:(CI)(W,Rc)
                          CREATOR OWNER:(OI)(CI)(IO)(F)

Oh well... Such is life. We've managed to create the stream but can't re-read it, awesome Write Only Memory. Still this does demonstrate something interesting, the DACL for the directory is applied to all the sub-streams even though the DACL might make little sense for file content. The directory DACL for Tasks doesn't allow normal users to read or list the directory, which means that you can't read or execute the file stream.

In conclusion all you need to be able to create an ADS on a directory is write access to the directory. This is normally so you can modify the contents of the directory but it also applies to creating streams. But the immediate security principal for a stream then becomes the parent directory which might not be as expected. If I find the time I might blog about other interesting abuses of ADS at a later date.