New issue
Advanced search Search tips
Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Oct 2016
Cc:



Sign in to add a comment

Windows: Diagnostics Hub DLL Load EoP

Project Member Reported by forshaw@google.com, Aug 7 2016

Issue description

Windows: Diagnostics Hub DLL Load EoP
Platform: Windows 10 10586, not tested 8.1 Update 2 or Windows 7
Class: Elevation of Privilege

Summary:
The fix for CVE-2016-3231 is insufficient to prevent a normal user specifying an insecure agent path leading to arbitrary DLL loading at system privileges.

Description:

CVE-2016-3231 was an issue caused by passing a relative agent path name which allowed the DLL path loaded for the agent DLL to be redirected to another file. This seems to have been fixed and as far as I can tell this issue is no longer exploitable from a sandbox. However the problem is there’s an assumption that it’s not possible to write a file to the system32 directory, which technically is true but practically for this exploit false. 

As I’ve blogged about before, and also submitted bugs (for example MSRC-21233) a normal user can created named streams on directories as long as they have FILE_ADD_FILE access right to the directory. When you do this you create what looks from a path perspective to be in the parent. For example the system32\tasks folder is writable by a normal user, so you can copy a DLL to system32\tasks:abc.dll and when GetFullPathName is called the filename returned is tasks:abc.dll. When the GetValidAgentPath is called it checks if this file is in system32 by using GetFileAttributes, which succeeds and the service will proceed to load the file.

On the fixing side of things, I can’t see an obvious reason why just checking for invalid path characters in the agent path wouldn’t be sufficient (and in fact would arguably have fixed the original bug as well). Of course I think it’s slightly dodgy that you’ll load any DLL from system32, even ones which aren’t agent DLLs. You’d have to find something which was somehow exploitable in a very short time window during DllMain but it might work.

Also I wonder whether they’re any legitimate uses for named streams on NTFS directories? While it’s certainly out of scope perhaps they could only be created by admins? Or perhaps the access check shouldn’t be on the target directories but its parent directory where the effective file appears to be located. 

Proof of Concept:

I’ve provided a PoC as a C++ source code file. You’ll also need a DLL to test load, I’ve not provided one of these but any should do, as long as it matches the bitness of the OS.

1) Compile the C++ source code file.
2) Execute the poc passing the path to the DLL you want to load in the service as a normal user.
3) It should print that the DLL was loaded successfully.

Expected Result:
The loading of a DLL fails as the path is rejected.

Observed Result:
The DLL is loaded 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.

 
poc.cpp
6.8 KB View Download
Project Member

Comment 1 by forshaw@google.com, Aug 8 2016

Labels: MSRC-34385
Project Member

Comment 2 by forshaw@google.com, Oct 11 2016

Labels: CVE-2016-7188
Status: Fixed (was: New)
Fixed in https://technet.microsoft.com/library/security/MS16-125
Project Member

Comment 3 by forshaw@google.com, Oct 14 2016

Labels: -Restrict-View-Commit
Removing view restrictions. 

Comment 4 Deleted

I just tried that and this error was displayed:
"The specified module could not be found.
8007007E"

Sign in to add a comment