ericmckean / google-security-research

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

Windows: Profile API CreateEnvBlock Local Information Disclosure #160

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Windows: Profile API CreateEnvBlock Local Information Disclosure
Platform: Windows 8.1 Update 32/64 bit (7 not tested)
Class: Information Disclosure

The exported function CreateEnvBlock from profapi.dll (which is used by the 
CreateEnvironmentBlock API function) has an information disclosure 
vulnerability when building the environment block for a user which can be 
locally exploited to disclose heap memory of a process calling the API. For 
example it's common when a privileged service spawns a process as another user 
to load the environment block, the information disclosure will be from the 
caller. 

The bug occurs in the SetEnvFromRegistryKey method which has roughly the 
following code:

DWORD dwMaxValueLen;

RegQueryInfoKey(hKey, ..., &dwMaxValueLen, ...);

// Increment for guaranteed NUL
dwMaxValueLen += 2;

WCHAR* lpBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwMaxValueLen);

RegEnumValue(hKey, ..., lpBuf, &dwMaxValueLen);

RtlSetEnvironmentVariable(..., lpBuf, wcslen(lpBuf)...);

The code adds an additional 2 bytes to the maximum length, and ensures the 
entire heap block is zeroed so those two bytes should stay zero. There's a race 
condition between the original query for the maximum size and the point where 
RegEnumValue is called. As the call uses the size with the NUL character 
allowance and not the original size it's possible to change the biggest value 
during the process to fill the entire buffer and as registry strings do not 
need to be NUL terminated the subsequent read will continue after the value 
buffer until it hits a NUL wide character. By choosing appropriate sizes this 
will read the heap header then try and read part of the following heap block.

Exploiting the race reliably would seem to be difficult, fortunately the 
function provides us with a way of winning the race. If the function encounters 
an environment variable with the names TEMP or TMP it will pass the value to 
the API GetShortPathName. By building a suitable path and using an OPLOCK on 
part of the directory hierarchy we can get signaled when the GetShortPathName 
API is being called on the path. 

One place this can be exploited locally is in scheduled tasks. When a scheduled 
task is executed the service calls CreateEnvBlock with the user's token to 
build the environment for the new process. By exploiting the race condition a 
new scheduled task process can be created with the permissions of the user, the 
leaked heap memory can then be extracted and inspected. This can be repeated 
indefinitely until useful memory is exposed. As the svchost process which 
contains the task scheduler has some interesting services it might be possible 
to disclose sensitive information. As it typically discloses heap header 
information it might be a useful technique for exploiting a heap overflow in 
the service if one could be found. 

Additionally while not a security issue there's a bug in the operation of the 
CreateEnvBlock function in that it doesn't take the Session ID from the token 
when querying for the Volatile Environment key. Instead it uses the session ID 
of the process which leads to the incorrect result, although for the purposes 
of exploitation it makes it easier. 

Provided is a PoC which exploits the issue on Windows 8.1 update. Due to the 
way in which the race condition is exploited this doesn't seem to work on 7 
(seems you can't add an oplock to a directory on Windows 7 or at least my code 
is wrong). Therefore I've not checked it on Windows 7, but I believe the bug 
still exists based on analysis of the DLL. There are other ways of winning the 
race such as using the WebDav redirector to forward requests for 
GetShortPathName to a locally listening host. To reproduce execute the 
following steps: 

1) Execute the file Poc_CreateEnvBlock_InfoDisclosure.exe
2) It should try and exploit the race and run a new copy of itself from the 
task scheduler printing any leaked memory.

It might require running a few times and for the system to have been used a 
little to ensure the heap of the task scheduler process has anything in it. The 
size of the value was chosen empirically, I've changed it to different sizes 
but most don't work.  

Expected result: 
The environment variable shouldn't contained additional data

Observed result:
The environment variable contains data leaked from the task scheduler's heap

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 10 Nov 2014 at 4:51

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by fors...@google.com on 11 Nov 2014 at 2:16

GoogleCodeExporter commented 9 years ago
Correspondance Date: 16 Jan 2015

< Microsoft have indicated that this issue does not meet the bar of a security 
bulletin. They feel that it does not provide the attacker with sufficient 
control over what heap memory is disclosed and so is not a serious enough 
security issue to require a bulletin. 

Marking as WontFix and removing view restriction.

Original comment by fors...@google.com on 16 Jan 2015 at 8:01