|
|
Adobe Reader: NtSetInformationFile Rename Check Bypass Elevation of Privilege | |||
| Project Member Reported by forshaw@google.com, May 22 2015 | Back to list | |||
Adobe Reader: NtSetInformationFile Rename Check Bypass Elevation of Privilege
Platform: Windows
Version: Acrobat Reader DC 15.007.20033.2203 (11.X not tested)
Class: Elevation of Privilege
Summary:
The NtSetInformationFile hook in the Reader sandbox checks the source file handle against policy. It’s possible to bypass this check allowing a file hard link to be renamed into a permitted directory which can be used to elevate privileges.
Description:
The NtSetInformationFile hook in the Reader sandbox performs two main checks on the arguments it’s passed from the sandboxed process. It verifies that write access it allowed to the destination path and that write access is also granted to the renaming file handle location. However the policy check for the file handle fails open, specifically if we can’t get the full path from the handle it will do the real NtSetInformationFile call anyway. The code is roughly:
if (get_handle_path(hFile, &path) && path.size() && !check_policy(path, GENERIC_WRITE)) {
return ACCESS_DENIED;
} else {
NtSetInformationFileReal(...);
}
The code which gets the full path uses the GetFinalPathNameByHandle API, if that API fails then the error will be propagated up the stack, causing the check to fail open. The trick therefore is find a way to cause the API call to fail. As we’re sharing the handle between the sandboxed and broker process one thing we can do is to rename the file, this in turn will change the path returned by the API. If we do the rename repeatedly we can cause the logic in the API to fail leading to an error being returned which will allow the check to be bypassed. There’s a second similar issue in the sandbox code itself. Even if the internals of the API don’t fail you can produce a similar effect by making a file longer than MAX_PATH, this bypasses an initial API call. The code will then allocate a larger buffer for the file path, if the size of the path changes between the two calls then this second call will also fail and the error will be returned. Ultimately these calls can’t be trusted to work correctly and the sandbox should err on the side of caution and fail if it’s unable to get the path.
You’d need to be able to get DELETE access to a file to rename and you’d also need to be able to add new directory entries to the rename location in order to perform the attack. Fortunately there’s a few places on a default install of Windows 8.1 which you can write to when running in the reader sandbox, such as C:\ProgramData\Microsoft\PlayReady. Of course this doesn’t seem immediately useful, what use is renaming a file you need to have write access to another location you also have write access via the broker? Well one thing you can do is create a hardlink to a file you have read access to but not write access. Contrary to the CreateHardlink API which requires the linked to file to be writable, you can create a link to a file with any access rights such as SYNCHRONIZE or READ_CONTROL. You can then rename the hard link to the destination folder and get the broker to open it for write access. This could be used for example write to an existing file in the reader Privileged directory which is normally Read Only which might facilitate an escape. As a hardlink isn’t a reparse point all checks will pass, the broker will believe the file exists in the target directory even though it’s cross-linked against another file.
So to exploit this you perform the following operations:
1. Create a hard link in a directory that can be written to directly.
2. Start a thread, renaming the file to two different length file names repeatedly.
3. In another thread repeatedly call the NtSetInformationFile hook until successful.
4. The renamed file can now be written to using the broker.
Proof of Concept:
1) Extract the PoC to a location on a local hard disk which is readable (but not writeable) by the sandboxed reader process (such as directory in the root of the drive)
2) Start Acrobat Reader and find the PID of the AcroRd32.exe sandboxed process
3) Run injectdll <PID> example.dll from the command prompt
4) You should find a file, test.txt in %TEMP%\acrord32_sbx which links to the example.txt in the poc folder with specific contents.
Expected Result:
The NtSetInformationFile call in the broker should fail with STATUS_ACCESS_DENIED.
Observed Result:
The rename succeeds.
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.
Project Member
Comment 1
by
forshaw@google.com,
May 23 2015
,
Jul 5 2015
,
Jul 14 2015
,
Jul 22 2015
Opening issue |
||||
| ► Sign in to add a comment | ||||