Wednesday, October 27, 2010

Breaking The SetDllDirectory Protection Against Binary Planting

The curious case of Windows environment variables or how to re-hack fixed iTunes and Safari

If you're a Windows developer trying to protect your applications from binary planting attacks, you have probably heard of the SetDllDirectory function. This function removes the current working directory from the search path when  loading DLLs and allows you to replace it with a (hopefully safe) location you specify.

For instance, the DLL search order after calling SetDllDirectory("C:\SafePath\") becomes:
  1. The directory from which the application loaded
  2. C:\SafePath\ 
  3. 32-bit System directory (Windows\System32)
  4. 16-bit System directory (Windows\System)
  5. Windows directory (Windows)
  6. Directories in the PATH environment variable

When providing an empty string to SetDllDirectory, the current working directory is simply removed from the DLL search order:
  1. The directory from which the application loaded
  2. 32-bit System directory (Windows\System32)
  3. 16-bit System directory (Windows\System)
  4. Windows directory (Windows)
  5. Directories in the PATH environment variable

In theory, calling SetDllDirectory at the beginning of your code should solve the binary planting problem at least as far as loading DLLs go (reminder: EXEs are also affected). The concept sounds good and it is in fact one of the recommendations in our developer guidelines for preventing binary planting vulnerabilities.

In practice though, DLL-based binary planting attacks may still be possible. How? Enter the world of unexpanded environment variables, a known Windows bug that goes a long way in helping binary planting attackers.

Our researchers have (re)discovered a curious fact that some Windows environment variables sometimes don't get expanded in the PATH. For example, the CommonProgramFiles environment variable, which typically expands to "C:\Program Files\Common Files", sometimes simply remains %CommonProgramFiles% in the PATH. This bug affects many other environment variables on all Windows platforms and has not only been publicly discussed before since 2003 (see here, here, here, here and here) but Microsoft has also issued a KB article on the subject 3 years ago. The bug, however, was never fixed.

Now what does this mean for binary planting? Suppose an application calls SetDllDirectory to protect itself against DLL planting attacks. Obviously, the current working directory is no longer in its library search path - but the PATH still is! And if any one of the environment variables in the PATH remains unexpanded, well..., it becomes a relative path. That is, relative to the current working directory. For instance, if the PATH looks like this:

PATH=C:\Program Files\Java\jdk1.6.0_21\bin;
%CommonProgramFiles%\Microsoft Shared\Windows Live;
C:\Program Files\QuickTime\QTSystem\

and the CommonProgramFiles variable doesn't get expanded, the actual PATH included in the search path will contain the loaction

%CommonProgramFiles%\Microsoft Shared\Windows Live

In case the DLL hasn't been found in preceding locations in the search path, the application will at this point try to load it from a subdirectory of the current working directory, specifically from

CWD\%CommonProgramFiles%\Microsoft Shared\Windows Live

For illustration purposes let's take Apple's latest iTunes and Safari as examples (remember that their DLL and EXE planting bugs have already been fixed). These applications both call SetDllDirectory at the beginning of their execution, which is a secure coding practice that we recommend. Now let's assume you also have ActivePython installed. ActivePython adds %APPDATA%\Python\Scripts to the system PATH. There is nothing wrong with this! What is wrong is that APPDATA, due to the Windows bug described above, often remains unexpanded in PATH, which effectively makes iTunes, Safari and countless other applications vulnerable to binary planting attacks.

Let's see this in action.

Again, this is not Apple's fault (although they could improve their code by specifying full paths to their libraries) and it's certainly not ActivePython's fault (PATH is meant to be used this way).

Besides, it's not just the APPDATA variable that helps attackers in this way. Our Online binary planting exposure test's logs show Windows machines trying to load DLLs from various unexpected paths, including:

  • %APPDATA%/Python/Scripts
  • %ProgramFiles(x86)%
  • %CommonProgramFiles%/Microsoft Shared/Windows Live
  • %PROGRAMFILES(x86)%/Common Files/Microsoft Shared/Ink
  • %USERPROFILE%/Local Settings/Temp
  • %systemroot%/system32/DATA/Config
  • %NpmLib%

What can we learn from this all? Mostly, don't just depend on SetDllDirectory to solve your DLL-planting problems. Use absolute, fully qualified paths to DLLs when loading them. Until Microsoft fixes this bug, any application that sets user or system PATH can unwittingly make your application vulnerable to binary planting if you're loading libraries from relative paths. And even then, some particularly adventurous application might add a relative location to PATH for whatever peculiar purpose, and break the SetDllDirectory  protection for the entire system. Again, use absolute paths to DLLs!

Finally, it needs to be said that this bug fortunately doesn't hinder the effectiveness of Microsoft's CWDIllegalInDllSearch hotfix. This hotfix successfully blocks DLL loads from the current working directory if configured properly even if relative locations are found in the PATH (it does nothing to prevent EXE planting attacks though).

Unexpanded variables bug analysis

For those interested in more information about the curious behavior of this Windows bug, here are some of our most important observations. We were testing on Windows XP Professional 32 bit, Windows Vista Business 32 and 64 bit and Windows 7 Professional 32 bit.

  1.  We noticed that the "expandability" of certain environment variables sometimes changes by logging off or restarting the computer. For instance, APPDATA in the user PATH is initially unexpanded on Windows 7, but gets expanded after logoff or restart. On Windows XP, however, logoff makes this variable "expandable," but restarting the machine again makes it "nonexpandable".
  2. Windows Vista 64 bit never expanded APPDATA in the user PATH, whatever we tried.
  3. While Windows XP expanded APPDATA in system PATH at least after logoff, Windows Vista and Windows 7 never expanded APPDATA in system PATH.
  4. COMMONPROGRAMFILES is never expanded in system PATH upon initial setting, and while other systems resolve this after logoff or restart, Windows Vista 64 bit never seems to expands this variable, period.
  5. The same goes for PROGRAMFILES, which is a very common variable to use.
Many other environment variables are affected, making it relatively likely that the SetDllDirectory protection against binary planting will not be efficient on computers with multiple software products installed (which might add locations to user or system PATHs).

Monday, October 18, 2010

How Visual Studio Makes Your Applications Vulnerable to Binary Planting

Creating a Binary Planting-Positive Application Without Writing a Single Line of Code

As attendees of the Hack In The Box conference learned last week, Microsoft Visual Studio makes it possible to develop a binary planting-positive (i.e., vulnerable) application without you having to write a single line of code in just 34 seconds. Let's look at the video first.

The video shows the process of creating an empty default MFC application (the Project Style setting could have been left at "Visual Studio", but "MFC Standard" creates an even simpler application) and associating this application with a ".bp" file extension ("bp" as in "binary planting", of course). Double-clicking test.bp then lunches the application and loads a malicious dwmapi.dll from the same directory.

At this moment (October 18, 2010), every single MFC application built with either old or updated Microsoft Visual Studio 2010 (probably others too) tries to blindly load dwmapi.dll upon initialization, resulting in a binary planting vulnerability when executed on Windows XP or older Windows systems (affecting more than two thirds of all Windows users). There is nothing a developer can do to prevent this; there are no settings in Visual Studio to change this behavior of MFC applications. The vulnerability lies in Microsoft's MFC library which comes with Visual Studio and is distributed to users' computers as part of Visual C++ Redistributable Package.

A number of applications have already been publicly reported vulnerable due to Microsoft's MFC library, including TortoiseSVN, L0phtCrack, BS Contact, Artlantis Studio, ALShow, DVDFab, ALZip; our own binary planting research project has identified a dozen more.

There is a mitigation factor though: if your MFC application is not associated with a file extension (i.e., it can't be launched by double-clicking on a file) and is not meant to be launched from the command line interpreter, it will be difficult to exploit.

There's good news and bad news for the developers. Good news is that only MFC applications seem to be affected. Another good news is that when Microsoft decides to patch the Visual C++ Redistributable Package, many of the affected applications should be automatically fixed on users' computers.

Bad news, however, is that this only applies to MFC applications that dynamically link MFC libraries; if these libraries are linked statically, they get integrated in the application's executables and do not use the redistributable libraries that Microsoft can patch on users' computers. Developers of such applications will have to wait for Microsoft to patch the bug in Visual Studio, rebuild their applications in order to integrate the fixed MFC code, redo the test runs, and deliver the new builds to every one of their users. In absence of automatic update facilities, these vulnerable applications are likely to remain so for a long time.

[Update April 13, 2011: Microsoft provided security updates for both Visual Studio and Visual C++ redistributable packages. See our blog post for more details.]

Friday, October 8, 2010

HITB Preview: More Binary Planting Material Revealed

Re-Hacking Fixed iTunes and Creating a Binary Planting-Positive Application Without Writing a Single Line of Code

As the Hack In The Box conference in Kuala Lumpur is just around the corner, we'd like to announce a couple of previously undisclosed candies the attendees of our Remote Binary Planting – An Overlooked Vulnerability Affair session will receive.

Re-Hacking Fixed iTunes

As you may know, this binary planting bug in Apple iTunes is famous for triggering the whole DLL hijacking / binary planting / DLL preloading explosion that's been echoing around the Net for over a month now. We released the above advisory when Apple fixed the binary planting bug that allowed a remote attacker to get her malicious QUSEREX.DLL executed on users' computers. The vulnerable executable was AppleMobileDeviceHelper.exe (along with a number of others that also tried to load this DLL). Interestingly, iTunes.exe was already protected with a SetDllDirectory call, possibly as a result of the famous Safari-IE blended threat issue in 2008, where Safari and IE unwittingly colluded against users to execute malicious code on their computers.

Our analysis of the iTunes binary planting fix revealed that AppleMobileDeviceHelper.exe now calls SetDllDirectory as well, which is a good thing. In addition, it doesn't try to load the non-existing DLL any more, adding to the basic security hygiene. All is well in the land of apples and binary planting then, right?

Well... Come to our presentation at HITB and see what "blended threat" really means in this multi-player drama that will likely trigger some 2008 flashbacks. You'll learn that SetDllDirectory isn't always that effective, and see how iTunes.exe feels about it.

Creating a Binary Planting-Positive Application Without Writing a Single Line of Code

For those of you optimizing the number of keystrokes for writing vulnerable applications (we know you're out there), this will be your treat. We'll show how innocent, well-meaning developers can create a binary planting-positive application without  writing a single line of code, and without doing anything out of the ordinary. There is a well-known development platform out there that really takes the effort out of insecure coding. And chances are you're using it.

[Update October 18,2010: How Visual Studio Makes Your Applications Vulnerable to Binary Planting]
[Update October 27,2010: Breaking The SetDllDirectory Protection Against Binary Planting]

See you next week in KL!

Thursday, October 7, 2010

Binary Planting Protection Guidelines for Developers

The Binary Planting web site is now providing guidelines for software developers who want to avoid introducing binary planting vulnerabilities in their products. These guidelines supplement Microsoft's guidelines.