On September 13th, 2016 Microsoft released security bulletin MS16-104 , which addresses several vulnerabilities affecting Internet Explorer. One of those vulnerabilities is CVE-2016-3353, a security feature bypass bug in the way .URL files are handled. This security issue does not allow for remote code execution by itself; instead, it allows attackers to bypass a security warning in attacks involving user interaction. In this blogpost we discuss the whole process, from reverse engineering the patch to building a Proof-of-Concept for this vulnerability.
### Analysis Notes
This 1-day analysis was performed using the following versions of IE 11 for Windows 8.1 x64:
* Vulnerable version: ieframe.dll 11.0.9600.18427
* Patched version: ieframe.dll 11.0.9600.18450
#### Determining the relevant module
Microsoft Security Bulletin MS16-104 (September 2016) provides KB3185319  as the patched version of IE 11 on Windows 8.1 x64. This patch replaces KB3175443  (released on August 2016 as part of Security Bulletin MS16-095). Therefore, the diffing process will be performed between the mentioned new and old versions.
The September patch (KB3185319) ships 45 DLL files and 7 EXE files, so the first step is to determine which one of the patched binaries contains the fix for the specific vulnerability we are analyzing.
The Microsoft advisory mentions that:
> the attacker could send the targeted user a specially crafted .URL file that is designed to exploit the bypass
This hint is all we need to determine the affected module among a total of 52 shipped binaries.
We start by looking for the .URL file extension within the Windows Registry, under the `HKEY_CLASSES_ROOT\.url` key. The default value for this key is InternetShortcut, so we need to check out the `HKEY_CLASSES_ROOT\InternetShortcut\shell\Open\Command` key to find out which binary opens this file extension. The default value for this key is `"C:\WINDOWS\system32\rundll32.exe" "C:\WINDOWS\system32\ieframe.dll"`,OpenURL %l. That means that ieframe.dll is the module we are looking for, and more precisely, ieframe!OpenURL is the function in charge of processing .URL files when they are launched from the Windows Explorer.
By inspecting the ieframe!OpenURL function in IDA Pro we can see that the actual work is mostly delegated to the CInternetShortcut class:
[ieframe.dll version 11.0.9600.18427]
.text:102FBAC0 ; __stdcall OpenURL(x, x, x, x)
.text:102FBAC0 public _OpenURL@16
.text:102FBADE push 334h ; dwBytes
.text:102FBAE3 push 8 ; dwFlags
.text:102FBAE5 mov [ebp+var_214], esi
.text:102FBAEB call ds:__imp__GetProcessHeap@0 ; GetProcessHeap()
.text:102FBAF1 push eax ; hHeap
.text:102FBAF2 call ds:__imp__HeapAlloc@12 ; HeapAlloc(x,x,x)
.text:102FBAF8 test eax, eax
.text:102FBAFA jz short loc_102FBB07
.text:102FBAFC mov ecx, eax ; this
.text:102FBAFE call ??0CInternetShortcut@@QAE@XZ ; CInternetShortcut::CInternetShortcut(void)
.text:102FBB3B push 2 ; this
.text:102FBB3D lea edx, [ebp+pwszDst]
.text:102FBB43 mov ecx, ebx
.text:102FBB45 call ?LoadFromFileW@CInternetShortcut@@QAGJPBGK@Z ; CInternetShortcut::LoadFromFileW(ushort const *,ulong)
.text:102FBBC0 push ebx ; this
.text:102FBBC1 call ?Release@CInternetShortcut@@UAGKXZ ; CInternetShortcut::Release(void)
Knowing that the CInternetShortcut class is involved in the processing of .URL files, now we can perform binary diffing between the old and the new versions of ieframe.dll, paying special attention to modifications in methods belonging to the CInternetShortcut class.
### Binary diffing
After loading and analyzing both the vulnerable and the patched versions of ieframe.dll in IDA Pro, we diffed the two IDA databases using BinDiff. Ordering the matched functions in BinDiff by ascending similarity we can see that the first method of the CInternetShortcut class with significant changes is CInternetShortcut::InvokeCommand(_CMINVOKECOMMANDINFO *), with a similarity ratio of 0.84.
When comparing the flow-graphs of said method, we can determine that this is the function with a security fix indeed.
The new (fixed) version includes additional checks before calling CInternetShortcut::_InvokeCommand. If we dig into the right part of the screen (the patched version) we can see the checks that have been added:
If the CL register is 0, then the CInternetShortcut::_InvokeCommand method is invoked as usual. However, when CL != 0, the function will call CDownloadUtilities::OpenSafeDialog. If said security dialog is accepted by the user, then CInternetShortcut::_InvokeCommand is called.
So we move on to determine where the value of the CL register is set:
From that code snippet we can conclude that CL is set to 1 when the processed file has .URL extension and also contains the Mark Of The Web (MOTW)  Alternate Data Stream. In that case, the user will be presented with a security warning before proceeding to process the .URL file.
### Determining impact of the bug
Microsoft's bulletin doesn't give much precision on what the attacker can achieve by exploiting this bug; it only mentions that "the attacker could send the targeted user a specially crafted .URL file that is designed to exploit the bypass". On the other hand, ZDI advisory ZDI-16-506  mentions that "If the victim opens the .URL file, the attacker can execute arbitrary code on the victim's machine under the context of the user". Also, ZDI mentions that the bug has been discovered by Eduardo Braun Prado. By looking at other security advisories published by Eduardo , we can see that he specializes in exploiting "link-like" file formats (.MCL, .LNK) to execute arbitrary programs without a security warning being shown to the user. So we decided to follow this clue and work with the hypothesis that this vulnerability would allow us to execute an arbitrary program if we can convince a user to open a specially crafted .URL file, with no security warning being shown to the user.
This is the content of a typical .URL file:
In order to understand how to exploit the bug, let's see how CInternetShortcut::_InvokeCommand (the function that, on the patched version, is only called after the additional security checks) works.
The function calls CInternetShortcut::CExecHelper::Init, which initializes a SHELLEXECUTEINFO  structure. Then it calls CInternetShortcut::CExecHelper::ResolveProtocol to verify if the protocol specified in the URL key of the .URL file is properly registered in the current machine.
Then it calls CInternetShortcut::CExecHelper::IEDirectExec, which tries to open the destination URL in Internet Explorer, if possible at all. If that's not possible, then CInternetShortcut::CExecHelper::Execute is invoked. CInternetShortcut::CExecHelper::Execute just calls the ShellExecuteEx  API, with the SHELLEXECUTEINFO structure initialized before as its parameter.
Therefore we can make the URL key of a .URL file point to an executable file, and it will be executed via ShellExecuteEx. However, when initializing the SHELLEXECUTEINFO structure, the lpParameters field is set to NULL, therefore we cannot provide arbitrary arguments to the file to be executed. That means that we aren't able to abuse local interpreters like cscript, wscript or powershell, and we need to provide the file to be executed instead.
Looking for exploitation possibilities under similar scenarios, we stumbled upon Google Project Zero bug #693  (which describes a vulnerability in a TrendMicro product), in which Tavis Ormandy mentions the idea of auto-downloading a .ZIP file containing an .HTA file with arbitrary code, and taking advantage of the Windows Explorer feature that treats .ZIP files as folders to execute the .HTA file inside the .ZIP via ShellExecute by specifying a path like this: C:/Users/someone/Downloads/test.zip/test.hta. His scenario is pretty similar to ours, since he also mentions that he's able to avoid MOTW security warnings using this trick.
Further tests revealed that this trick will also work if the .ZIP file containing the .HTA file is hosted in an SMB share.
### Proof of Concept
In order to exploit the vulnerability, the contents of the .URL file that is sent to the target user must be like this:
This is the code for the ms16-104.hta file, taken from the Project Zero's PoC mentioned above. It will run "cmd.exe /k echo hello world!". It must be zipped into test.zip, and the .ZIP file must be hosted on the SMB shared folder specified in the .URL file.
Set o = CreateObject("Shell.Application")
o.ShellExecute "cmd.exe", "/k echo hello world!", "", "", 1
When a user downloads the malicious .URL file using a web browser, the file is properly marked with MOTW, indicating that this file may be potentially harmful.
Under normal conditions, if a user tries to open a file marked with MOTW, a security warning is shown to the user, stating that the file may be malicious and asking if he/she really wants to open it. However, due to the security bug being analyzed here, when opening the malicious .URL file, the remote .HTA file referenced by the .URL file is executed without any warnings, ignoring the fact that the Mark Of The Web is present on the .URL file.
On patched systems, the user is presented with the following security warning when trying to open a .URL file containing the MOTW:
Mark Of The Web (MOTW) is an Alternate Data Stream added by web browsers (and other highly-exposed software like email clients) to files downloaded from the Internet. When a user double clicks on a file that is marked with MOTW, a security warning is typically shown, telling the user that the file comes from the Internet and that it can be harmful.
In the case of .URL files before the MS16-104 patch, the MOTW is not honored, so the file referenced by the .URL file is simply executed via ShellExecuteEx with no security warning at all. This can be abused to execute arbitrary code by convincing a user to open a malicious .URL file which points to a .HTA file inside a .ZIP file, with the .ZIP file being hosted in a SMB share.