[Update 2/12/2019: Just one day after we had issued this micropatch, Adobe released an update of Adobe Reader DC that fixed the vulnerability. We strongly recommend all users of Adobe Reader to apply Adobe's update, at which point our micropatch will automatically no longer get applied.]
Today we'll look at a fairly simple vulnerability in Adobe Reader DC that allows a PDF document automatically send an SMB request to attacker's server as soon as the document is opened. The vulnerability was published by Alex Inführ along with a proof-of-concept in a detailed report on Alex's blog and hasn't been patched at the time of this writing. [Update 2/12/2019: the vulnerability was subsequently assigned CVE ID CVE-2019-7089.]
This vulnerability, similar to CVE-2018-4993, the so-called Bad-PDF reported by CheckPoint in April last year, allows a remote attacker to steal user's NTLM hash included in the SMB request. It also allows a document to "phone home", i.e., to let the sender know that the user has viewed the document. Obviously, neither of these is desirable.
At the time of this writing, the latest version of Adobe Reader DC, 2019.010.20069, is affected but older versions are likely in the same boat too.
Analysis
To understand the problem, let's start with the above-mentioned Bad-PDF (CVE-2018-4993). The malicious PDF included a certain element that triggered automatic loading of another PDF from a remote share. Until Adobe Reader got patched, this happened without the user noticing anything, or being able to prevent it.
Adobe patched this issue by adding a security warning that was shown to the user before making the request to a remote share:
Security warning added to fix the Bad-PDF issue. |
This warning allowed the user to decide whether to allow the potentially malicious document to "phone home" or not.
Now on to the issue at hand: it is functionally identical (for attacker), just in a different place. While Bad-PDF used an /F entry to load a remote file, this issue exploits loading a remote XML style sheet via SMB. Interestingly, if the document tries to do so via HTTP, there is a security warning there:
Attempting to load a remote style sheet via HTTP triggers a warning. |
However, when using a UNC path (the type of path that denotes a resource in a shared folder), the loading occurs without a warning
The Micropatch
The Reader already implies the correct behavior by showing a security warning on loading a remote style sheet via HTTP, so we decided to add our own security warning for loading style sheets via UNC as well.
We started by locating the point where the HTTP-loading and UNC-loading execution paths diverge, and patch-in a warning for UNC paths. Finding said divergence point was relatively easy using Process Monitor: we caught CreateFile events on both HTTP and UNC loads, then compared their call stacks to see where the two execution paths said good-bye to each other. This turned out to be in function sub_208B3C53, the relevant code block of which is shown here:
Both HTTP- and UNC-based style sheet loads reach the above code block, whereby an HTTP-based load never returns from the first call marked in red (it triggers an exception that Reader handles somewhere else), and a UNC load is implemented inside the second call marked in red.
As you can see from the comments in the code, we found where the file path resides before the second call (this required a little digging on the stack at that point). We verified it by changing said path on-the-fly in debugger to make sure the path-loading code actually uses that, and then we were ready to inject our patch.
There exists a handy Windows function called PathIsUNCA, which is already being used by Reader elsewhere to check whether a path is a UNC path (the "A" at the end denotes an ASCII path in contrast to a wide-char path). So we decided to first call this function to see if we have a UNC path, and then if we do, issue a prompt to the user. To do the latter, we used another well-known Windows function MessageBoxA. Based on user's response, we would then allow the UNC path to be loaded or not. The only thing to decide at this point was how to implement the "not", i.e., how to prevent the UNC path from loading if the user decided not to trust the document.
In such cases, we always want to keep things simple and minimize possible surprises. We therefore decided to simply empty the path string by putting a zero at its beginning, resulting in Reader trying to load an empty path. It does complain that it can't load it though but the exploit is blocked and, frankly, we're fairly confident that loading style sheets form UNC paths doesn't work at all because as much as we tried, Reader always encountered an error. So maybe UNC style sheets are not a supported use case at all but they did turn out to be a vulnerability.
Here is the source code of our micropatch:
MODULE_PATH "..\AffectedModules\AcroForm.api_19.10.20064.48846_32bit\AcroForm.api"
PATCH_ID 349
PATCH_FORMAT_VER 2
VULN_ID 4694
PLATFORM win32
patchlet_start
PATCHLET_ID 1
PATCHLET_TYPE 2
PATCHLET_OFFSET 0x000b3f6b ; Injecting before the call towards loading
; a non-HTTP URL
PIT Shlwapi.dll!PathIsUNCA,User32.dll!MessageBoxA
code_start
push ecx ; save ecx so we don't corrupt it
mov eax, dword [eax+10h] ; at this point, the address of path
; is at [eax+10h]+4
add eax, 4
push eax
push eax ; we push the address of path twice as we may need it
; in remediation too
call PIT_PathIsUNCA ; is it a UNC path?
test eax, eax
jz skip ; not a UNC path - skip the warning dialog
push 0x00000134 ; uType = MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2
call get_lpCaption
db "Security Warning",0
get_lpCaption:
call get_lpText
db "This document is trying to access a file on the network. If you trust this document, choose Yes. If you do not trust this document, choose No.",0
get_lpText:
push 0 ; hWnd = NULL
call PIT_MessageBoxA
cmp eax, 6 ; Did user click "Yes"?
je skip ; if so, skip remediation
; Remediation: we'll simply delete the entire URL string by putting
; a 0 at the beginning
pop eax ; pop the previously pushed path address
mov byte [eax], 0 ; put a 0 at the start of path
push eax ; we need to re-push something because we have a pop in the epilogue
skip:
pop eax ; pop the additional address of path
pop ecx ; restore original ecx and continue to execute the call
; towards loading the provided URL
code_end
patchlet_end
PATCH_ID 349
PATCH_FORMAT_VER 2
VULN_ID 4694
PLATFORM win32
patchlet_start
PATCHLET_ID 1
PATCHLET_TYPE 2
PATCHLET_OFFSET 0x000b3f6b ; Injecting before the call towards loading
; a non-HTTP URL
PIT Shlwapi.dll!PathIsUNCA,User32.dll!MessageBoxA
code_start
push ecx ; save ecx so we don't corrupt it
mov eax, dword [eax+10h] ; at this point, the address of path
; is at [eax+10h]+4
add eax, 4
push eax
push eax ; we push the address of path twice as we may need it
; in remediation too
call PIT_PathIsUNCA ; is it a UNC path?
test eax, eax
jz skip ; not a UNC path - skip the warning dialog
push 0x00000134 ; uType = MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2
call get_lpCaption
db "Security Warning",0
get_lpCaption:
call get_lpText
db "This document is trying to access a file on the network. If you trust this document, choose Yes. If you do not trust this document, choose No.",0
get_lpText:
push 0 ; hWnd = NULL
call PIT_MessageBoxA
cmp eax, 6 ; Did user click "Yes"?
je skip ; if so, skip remediation
; Remediation: we'll simply delete the entire URL string by putting
; a 0 at the beginning
pop eax ; pop the previously pushed path address
mov byte [eax], 0 ; put a 0 at the start of path
push eax ; we need to re-push something because we have a pop in the epilogue
skip:
pop eax ; pop the additional address of path
pop ecx ; restore original ecx and continue to execute the call
; towards loading the provided URL
code_end
patchlet_end
With this micropatch in place, opening the malicious document results in the following warning before a request is made to the remote server:
The security dialog that was micropatched into Adobe Reader. |
If the user selects "Yes", the remote style sheet is loaded (whereby the SMB request delivers your NTLM hash to the remote server), and if they select "No", Reader complains about not being able to load the style sheet from and empty path. Done.
We asked Alex, the security researcher who found this issue, to test our micropatch and he was kind enough to confirm its efficiency against this attack. (Thanks, Alex, for your help! We encourage all security researchers to collaborate on creating and testing micropatches.)
For the visual types among you, here is a video of our micropatch in action:
Conclusion
As always, if you have our Agent installed and registered, this micropatch is already on your computer - and applied to Adobe Reader whenever it loads AcroForm.api (that only happens when certain documents are opened). Otherwise, you can register a free 0patch account and install 0patch Agent to get this micropatch applied to your Reader.
Note that Adobe might issue an official fix for this issue tomorrow as they release their monthly Reader update, but if not, we'll quickly port the micropatch to the new Reader version to keep the vulnerability patched on your computers. [Update 2/12/2019: Adobe did issue an official fix the next day.]
Cheers!
@mkolsek
@0patch
What's with the idp.alexa.exe avast picked up on when installing?
ReplyDeleteThere is no such file included in our product. Did you download our agent from our web sites https://0patch.com or https://dist.0patch.com?
Delete