Last week, HD Moore, creator of the Metasploit penetration testing suite, tweeted about a newly patched iTunes flaw. The tweet said that many other (unspecified) Windows applications were susceptible to the same issue—40 at the time, but probably hundreds.

The problem has been named, or rather, renamed, "Binary Planting," and it stems from an interaction between the way Windows loads DLLs and the way it handles the "current directory." Every program on Windows has a notion of a "current directory"; any attempt to load a file using a relative path (that is, a path that does not start with a drive letter or a UNC-style "\server" name) looks in the current directory for the named file. This concept is pretty universal—Unix-like systems have the same, called a "working directory"—and it's a decades-old feature of operating systems.

Windows, again in common with other operating systems, has the ability to load DLLs at runtime, during the execution of a program.

A systematic flaw in Windows applications certainly looks bad for Windows, but the operating system vendor is not in a position to provide a fix.

Where Windows is different from other operating systems is that it combines these two features; when a program instructs Windows to load a DLL, Windows looks in several different places for the library, including the current directory. Critically, it searches the current directory before looking in more likely locations such as the System32 directory, where most system libraries reside.

It's this that opens up the problem. When a file is loaded in Windows by double clicking it, and using file associations to start up the right program, Windows sets the current directory of the newly-started program to be the directory that contains the file. In the course of opening the file, they also try to load one or more DLLs. In normal circumstances, these DLLs will be loaded from the System32 directory. However, if an attacker knows the names of any of the DLLs the program tries to load, and puts a DLL with one of those names adjacent to a data file, he can ensure that his DLL will be loaded whenever the program tries to open the data file. Programs can also change their current directory manually, so the current directory will often appear to "follow" the last data file loaded.

Hence, "binary planting." An attacker creates a data file—which can be perfectly harmless in and of itself—and "plants" a DLL in the same directory. He then entices someone into opening the data file, for example through a link on a webpage or an e-mail. The vulnerable program will then attempt to open the data file, and in so doing will load the malicious DLL, allowing the attacker to do whatever he likes.

So, for example, an MP3 and a malicious DLL are placed alongside each other. The user double clicks the MP3 to load it, causing iTunes to start, and causing iTunes to use the folder with the MP3 as its current directory. During its startup, iTunes loads a number of DLLs, and one of them will be the malicious DLL.

The newly reported issue is a slightly new take on this old problem; instead of placing the DLL and data file on a local or LAN disk, they're placed on Internet-accessible file servers, using either the HTTP-based WebDAV or Windows' usual SMB/CIFS file-sharing protocols. In this way, a link to data file (with its side-by-side DLL) can be put into webpages or sent in mass e-mails.

Everything old is new again

The peculiar thing about all this is that this vulnerability has been known for a long time. The order in which directories are searched is documented, and has been documented for many years (that documentation dates back to 1998, and there are likely references that are older still, if one has any decade-old developer documents handy), and the dangers of using the current directory for loading libraries were explicitly highlighted a decade ago. As well as warning in the documentation about the dangers, Microsoft bloggers have also written about the issue in the past, telling developers how to avoid the problem.

To reduce the impact of this problem, Windows XP (and Windows 2000 Service Pack 4) changed the DLL loading behavior, by introducing a new mode named "SafeDllSearchMode." With this mode enabled, the current directory is only searched after the Windows directories, rather than before. This new mode was made the default in Windows XP Service Pack 2, and all subsequent operating systems from Microsoft. It is not, however, a complete solution; if a program tries to load a DLL that does not exist in the Windows directories, it will still fall back to attempting to load from the current directory, and so will still load a malicious DLL.

To address this, Windows has, since Windows XP SP1, provided a mechanism for programs to opt out of loading DLLs from the current directory completely. This has to be something that the program explicitly chooses to do, however, as there is the possibility that some software will depend on loading libraries from the current directory; making an OS-wide change to prevent the current directory being used in this way would break those programs.

All of which adds up to a tricky situation. Programs that are vulnerable to these problems are buggy. The operating system's standard behavior may not be ideal, but it provides the ability to write safe applications—though the design is plainly poor, it's not a fatal flaw, and certainly can't be described as a bug. It's just an artifact of Windows' long history. The behavior made sense in the security unconcerned world of single-user, un-networked 16-bit Windows, which is where it was first implemented, but is plainly undesirable in the modern world.

The fact that programs may legitimately depend on the behavior is another complexity: Microsoft can't easily make a unilateral decision to remove the current directory from the DLL search path, because the impact of such a change on legitimate programs could be substantial, and crippling. Microsoft has been telling developers to be careful, and to make sure they do the right thing, for many years now.

This places the company in an awkward position. A systematic flaw in Windows applications certainly looks bad for Windows, but the operating system vendor is not in a position to provide a fix. Though most programs will be able to get away with disabling DLL loading from the current directory completely, that's a determination that must be left to the program's authors, not Redmond. Unfortunately, not all vendors will do this in a timely manner, or possibly even at all.

Fixing the problem

If something isn't safe by default, and requires extra development effort to be made safe, programmers are going to write unsafe programs.

Microsoft has produced a hotfix that allows system administrators to forcibly disable DLL loading from the current directory for applications of their choosing, or systemwide. This still runs the risk of breaking those applications, but this approach allows users to test that their applications will remain working and apply the fix if it's harmless.

To try to maximize its usefulness, the fix is a little more complicated than simply disabling DLL loading from the current directory completely. It has three levels of protection: it can disable DLL loading from the current directory when the current directory is a WebDAV directory, it can disable it when the current directory is any kind of remote directory (whether it be WebDAV, SMB/CIFS, or anything else), and it can disable the use of the current directory for DLL loading completely. In this way, programs which legitimately need to load libraries from the current directory can still be made safe from network-based attacks.

This is not a perfect solution—disabling network-based libraries still permits exploitation via USB key, for example—but it does allow people to protect themselves. In conjunction with disabling WebDAV and blocking SMB at the network perimeter, it should offer reasonably robust protection against untargeted mass attacks. But it places a substantial burden on administrators to create the necessary registry entries to enable the protective behavior, and for many the only practical answer may be to enable the safe behavior system-wide and just hope it doesn't break anything.

If developers are paying attention, we should expect to see a spate of fixes that tackle this problem. In its own security bulletin, Microsoft says that it's currently investigating whether any of its programs are susceptible to the issue, and as mentioned, Apple has already updated iTunes to avoid the problem; there are sure to be many other companies with work to do for the same problem.

In that sense, the extra publicity that this old problem has been given is good news: it should raise awareness of the problem ensuring that more developers take care to address it—and for many, it should be a simple fix, as simply disabling the use of the current directory for library loading will suffice.

But it does highlight a bigger issue. If something isn't safe by default, and requires extra development effort to be made safe, programmers are going to write unsafe programs. It's an issue seen time and time again with more conventional security flaws such as buffer overflows: trusting programmers to do the right thing doesn't work. They may do the right thing some of the time, perhaps even most of the time, but they won't do the right thing all of the time, and software will contain exploitable flaws as a result.

Microsoft has made great strides with its own software to strive to eliminate common exploitable bugs from its own code, and to reduce the exploitability should those bugs be discovered, but even these efforts have not been 100 percent successful, and bugs are still found. And as the (re)discovery of this problem shows, getting that message out to third-party developers is an uphill struggle.

The company says that it is looking into ways to make it easier for developers to avoid this mistake in future, but short of making it impossible—by removing DLL loading from the current directory entirely, or at least requiring it to be explicitly enabled—it's hard to see what the company could do to improve the situation, as for most applications the problem is already easily avoided with just a single line of code.

In a world where developers can't be trusted to follow best practices, perhaps the correct response should have been for the company to make the new hotfix opt-out, rather than opt-in; make it establish a system-wide default, and allow administrators to revert to the old behavior for those programs that require it. This means disabling documented, standard functionality, but there's little practical alternative.

Microsoft has said that it is willing to break backwards compatibility if it's necessary to solve security issues, but typically only when the backward compatible behavior is irredeemably unsafe, and not required for any legitimate purpose. This is, after all, why the company changed the search order in the past, to search the current directory after the Windows directories instead of before.

The situation here is certainly trickier—programs might quite legitimately depend on the current, dangerous behavior—but if exploitation using this attack vector becomes widespread, the company may be faced with little alternative but to break compatibility and provide bulletproof protection after all. History has shown that the ability to write safe programs is not enough: software needs to be safe by default, as painful as that may be.