Fixing the DLL loading vulnerability

Update 24/08/2010: Microsoft published an advisory, there’s an article from the MSRC about the preloading DLL vulnerability, and a tool that fixes the problem. And if you want to know more, there’s an MSDN article.

Update 25/08/2010: if you came here from golem.de, heise.de or h-online.com, good for you! The articles on these websites are blatantly wrong, and their proposed solution doesn’t work . You will find here the real solutions, and links to the relevant blog posts and advisories.

Look! A new shiny vulnerability, affecting a lot of Windows applications! OMG OMG OMG we’re DOOMED!

</crazy mode off>

OK, let’s get serious. This vulnerability is actually a very old one. It is there because the DLL search order includes the current directory (if someone can tell me why, I would be delighted to know that). Here is the search order (source: MSDN):

If SafeDllSearchMode is enabled, the search order is as follows:

  1. The directory from which the application loaded.
  2. The system directory. Use the GetSystemDirectory function to get the path of this directory.
  3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
  4. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  5. The current directory.
  6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.

If SafeDllSearchMode is disabled, the search order is as follows:

  1. The directory from which the application loaded.
  2. The current directory.
  3. The system directory. Use the GetSystemDirectory function to get the path of this directory.
  4. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
  5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.

For the record: disabling SafeDllSearchMode means that you’re stupid, or that you’re using a Windows before XP SP1 (note that this is not exclusive).

So, let’s assume that your application tries to load a DLL that isn’t present, either in your application directory, or in the system directories. Then, the application will try to load the DLL from the current directory. And that’s it. If there’s a DLL with the same name in that folder, it will be loaded in the application. That’s why you can get owned by opening a file in that same directory: it sets the current directory of the application to the file’s folder.

OMG OMG OMG we’re DOOMED, and it’s incredibly easy to exploit me!

So, now, let’s take a look at the fix. This is an OS flaw. You can’t fix all your applications yourself. H.D. Moore has some sysadmin fixes that you can apply to prevent the exploit from coming on your computer. But your applications will still be exploitable.

If you’re a developer, though, you can fix your application. There’s a function that can remove the current directory from the DLL search path: SetDllDirectory. From MSDN:

After calling SetDllDirectory, the DLL search path is:

  1. The directory from which the application loaded.
  2. The directory specified by the lpPathName parameter.
  3. The system directory. Use the GetSystemDirectory function to get the path of this directory. The name of this directory is System32.
  4. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
  5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  6. The directories that are listed in the PATH environment variable.

So, if you pass a safe directory(let’s say, C:\Windows\System32, or your application directory) as argument to SetDllDirectory, you effectively remove the current directory from the search path! It works, I tested it for you :)

But that’s not the end: you have to wipe out the PATH to be safe. From the metasploit blog:

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.

And if you test  your application with ProcMon, you will surely see that a lot of (potentially unsafe) directories are added to the PATH, and used to look for the DLL. So, remove all the useless directories from the PATH if you can!

(And now, for the disclaimer: this blog post is not endorsed by Microsoft, and if you want to be really safe and know the best solution to employ, wait for Microsoft’s patches and workarounds. But if you trust me enough (you fool… *evil laugh*), you can try that fix on your application, and maybe protect your users. )

Actually, that fix is encouraged by Microsoft, and David Leblanc wrote about it in February 2008.

12 thoughts on “Fixing the DLL loading vulnerability

  1. Scope of DLL security problem widens - Update

  2. Update to a safer VLC « Unhandled expression

  3. Der Suchpfad ins Unglück - Dipl.-Inform. Carsten Eilers

  4. What I want to know is: am I vulnerable?

    If I watch a YouTube video, am I accessing a network share? If I click on any webpage embedded content, am I accessing a network share?

    I have spent hours researching this topic and haven’t been able to determine if it even applies to me. Does it apply only to locally networked computers?
    Is an internet connection an affected network?

    Is it enough to use programs on the ever-growing list of affected apps, or does it require that I use them in particular ways (such as through file-sharing)?

    Please, someone, report clearly on this issue.

    • A youtube video is safe. If the embedded webpage content is a remote folder, it’s not safe. The vulnerability is exploited like this: when you find an application that loads automatically a DLL from the current directory, if you put a file with the name of that DLL in the same folder as a file handled by that application, and you open the file directly, the application will be exploited.
      It works with practically any type of folder: network shares, USB keys, and I even saw someone exploit it by making you download the file and the DLL (when you start the file from your Downloads folder, booom). I guess if you unzip some files and a malicious DLL is there among the files, it could still be exploited. And the DLL can be a hidden file, it will still work.
      My article was about developers, but for users, you can use the fix published by Microsoft ( http://support.microsoft.com/kb/2264107 ), or wait for Windows Update.

    • I know that. But if you’re still using Windows 2000 or XP SP1, I won’t believe that you care about security. And changing the current directory fixes the issue, but some applications really work on the current directory, so you can’t change it at will. For VLC, I used GetProcAddress to find the function when it is available, so it doesn’t break on XP (there’s a crash on startup on win2K that I can fix, but I don’t care about that OS).

      • If you looked at David’s code you would have seen that the current directory is saved, then changed just before calling LoadLibrary and restored after. This temporary change affects the current process only. This way he creates SafeLoadLibrary to replace the problematic LoadLibrary. Using SetDllDirectory fixes the same LoadLibrary problem and nothing more.

        The temporary directory change will change desired application operation only if you safe-load a DLL that needs the current directory exactly at the moment it is loaded (not after), which I think is would be weird. The only real drawback of that code is if calling SafeLoadLibrary from multiple threads you can create a race condition.

        As a developer I know that you can’t support every version of Windows, but if the VLC devs think “I don’t care about that OS” maybe you should change the text “This release only supports Windows 2000 (SP4+UR1), XP, Vista and 7″ from the download page.

        Anyway I think that calling SafeLoadLibrary instead of LoadLibrary when you can’t find SetDllDirectory is the more general solution, It’s true this is more complex than just calling a function at process start.
        Dropping support for Windows pre XP SP3 and using your energy on more useful code is yet another way you can go.

      • I guess you will not see a DLL using the current directory in its DllMain, but you can’t be sure. It could be another developer’s “genius idea”. The race condition problem could be fixed, but that would need a bit more code. For me, the reall drawback is that the vulnerability may not be triggered by a LoadLibrary on your code. If the LoadLibrary is in a third party library (like Qt), or if you use external codecs with DirectShow, a DLL can be loaded from CWD even with SafeLoadLibrary. And there may be problems with COM, too (I’ll need to check). The advantage of SetDllDirectory is that it effectively fixes the vulnerability for all the executables loaded by your application.

        Then, there is still the problem of supporting Win2k and XP. VideoLAN is an association of unpaid developers. You can’t expect us to support indefinitely old platforms that account to a very small part of our users. It’s a better idea to concentrate on features like GPU decoding or Windows 7 compatibility. Nevertheless, my fix for the DLL preloading bug doesn’t break VLC on old XPs, so I guess it is still supported :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s