Chrome-plated holes

It's gone, the myth of invulnerability of Mozilla users: one wrong click may be enough to infect your system with spyware -- even if you are using Mozilla or Firefox. The reasons are quite similar to well known security holes in Internet Explorer.

vorlesen Druckansicht
Lesezeit: 11 Min.
Inhaltsverzeichnis

In the last few years, Microsoft's Internet Explorer has mainly drawn attention for its security problems. Again and again security holes were published that allowed spyware and trojans to be installed on user systems without the user doing anything more than opening an infested Web site; other times, some minimal action was required such as clicking or performing drag&drop on the page. Those holes were and are still actively exploited to download Spyware and Trojans onto the systems of unwary users.

The unholy trinity of ActiveX, Active Scripting and the local zone was responsible for a lot of these problems. Special Active X components provide methods for writing and activating files from within IE. With Active Scripting, those actions can be remotely activated. And for all this to work, the code has to be executed in the security zone of the local system. What is less commonly known: Mozilla & Co. offer quite similar concepts. And they are responsible for some of the serious security holes published during the last few months that damaged the reputation of Mozilla as a safe alternative to IE.

Usually, only pages originating from the system they are opened on -- such as with a file:-URI -- have these privileges in IE. Writing an IE exploit, for example to install spyware from an external web site, therefore means that hackers have to find a way to get those rights of the local zone. But before XP Service Pack 2, many roads led to Rome.

It is especially well known that the function to present local help files opened the doors to the local zone again and again. For example, one exploit opened a help window, planted shortcuts with the JavaScript function document.write(), and activated them with scripted mouse click events. Once in the "local system” zone, objects like ADODB.Stream, Shell.Application or WScript.Shell delivered access to the required system functions to write files and execute programms. But SP2 (almost) put an end to this. Even the security researcher http-equiv, who discovered and documented dozens of serious IE flaws, stated that SP2 did a good job with securing IE loopholes. For one, Microsoft tightened access to the local zone; second, they deactivated functions for writing and starting files from within IE like ADODB.stream and Shell.Application.

Now Mozilla and Firefox are getting into the headlines. In July 2003, I warned in a comment on heise Security that Mozilla isn't really immune to this kind of trouble. Mozilla's object model XPCOM offers quite similar methods for accessing system functions that can be scripted as well. The only question was: can external web sites abuse that functionality? They can, as Michael Krax demonstrated with his firescrolling demo: "chrome", the browser's user interface, operates with highest privileges that allow files to be read, written, and activated. Comparable to the local system zone of IE, writing a working exploit only meant he had to find a way to plant code into this chrome.

A typical exploit for the Internet Explorer yielded the following code that creates a new file and executes it:

Set WshShell = CreateObject("WScript.Shell") 
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.CreateTextFile(path, True)
...
f.Write(" code"
...
f.Close
WshShell.run(path)

This code was taken from a demo of the c't-Browsercheck. The major elements of the recently published Mozilla exploits are quite similar. The analogue component to a FileSystemObject is the component @mozilla.org/file/local;1, which implements the interface nsILocalFile to access local files. (This nomenclature reminds me of something -- did anybody ask for coffee? ;-) So the equivalent to the above code for Mozilla looks like this:

file=Components.classes['@mozilla.org/file/local;1'].\
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(path);
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE,420);
outputStream=Components.classes\
['@mozilla.org/network/file-output-stream;1'].\
createInstance(Components.interfaces.nsIFileOutputStream);
outputStream.init(file,0x04|0x08|0x20,420,0);
output='...';
outputStream.write(output,output.length);
outputStream.close();
file.launch();

This code originates from Michael Krax' firelinking demo. It creates a new file and executes it via file.launch(). Different from ActiveX XPCOM is not restricted to the windows platform. With simple modifications, the code also works on Linux and Mac OS X systems. Those changes can be deployed by a browser switch. This is exactly what the Firelinking-Demo in the c't-Browsercheck does.

Of course, a web site normally is not allowed to write on the hard disk of its visitors. For this kind of activity the JavaScript code has to ask the PrivilegeManager for permission. This is typically done with something like:

netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); 

UniversalXPConnect gives unrestricted access to the whole API. The PrivilegeManager will accept such requests only in special cases; initiated from an external web site, this call usually fails. Therefore, a working exploit has to somehow ensure that this code is executed in a context that the PrivilegeManager accepts as trustworthy.

This context is delivered by the chrome. You can imagine Mozilla as an empty canvas drawn upon by several different components. The whole User Interface -- i.e., all the menus and dialogs -- are essentially (XPCOM) components that can be scripted. Essentially everything surrounding the displayed web page is called the chrome.

The modular concept of Mozilla allows to reconfigure the browser virtually at will and provides the basis for the popular extensions. The chrome requires functions and the rights to access the local system. Every now and then, a user wants to save a web page locally. To do so, the code activated by the save dialog in the file menu needs permission to save a file to disk.

The trick of the recent Mozilla exploits is to inject code into particular elements of the user interface. As Mozilla -- like all browsers -- accepts extended URLs like javascript:alert('Hello World'); one can obviously try to inject such JavaScript-URLs in places where the chrome works with URLs. There are a lot of them, and some have already proven to be vulnerable: the dialog for installing XPI plug-ins displays a little icon that originates from a URL and in the location bar, Mozilla displays the "favicon” of a web site. You can still place bets, where the next such problem occurs.

As of 13. Juli the counter is closed. With Firefox 1.0.5 the next of those holes was disclosed. The jackpot goes to those who put it on the dialog "Set As Wallpaper".

The exploits of the last months shattered Mozilla's image as a secure browser. Embarrassing crashes, known from Microsoft's worst days, only made things worse. There was a fix of a serious security problem. Thousands of users downloaded MBytes from the net to install the new version only to learn a short time alter that developers had disabled the demo exploit but left the hole wide open. A minor change in the exploit code made it work again.

Instead of patching holes here and there, it is about time to reconsider the security concept. Developers are aware of the situation: "we have done a crappy job lately, patching just symptoms and producing compatibility problems without fixing underlying security holes." Brendan Eich, inventor of JavaScript and Mozilla's chief architect rages in bugzilla.

The underlying security hole Eich is addressing is obvious. Two zones in Mozilla operate with different rights: the chrome, allowed to do everything, and the restricted part that handles code from untrustworthy sources. And the borders are becoming blurred because the two parts have to interact, exchange events, data and even code.

That is why the Mozilla team is working on separating those zones more sharply. They intend to track the origin of potentially dangerous elements like the afore-mentioned JavaScript URLs more consistently. This origin then decides what privileges they can achieve [2]. The more general solution of completely denying chrome privileges to javasccript: URLs was abandoned for compatibility reasons [3]. Furthermore, content and chrome are not to share DOM object wrappers any more [4]. And finally, developers are revising the event handling to protect the chrome from script generated events.

Because conceptual changes never go without breaking compatibility -- extensions don't work any more, pages may not be displayed correctly and so on -- they are being tested only in the development branch (1.1 for Firefox). Only patches without significant incompatibilities are to be ported back into the stable branch (Firefox 1.0). In the case of acute security problems, users of the stable versions have to settle with workarounds that stop exploits from working but do not address the real problem. This is often reserved for the trunk version, i.e. Firefox 1.1.

The very dedicated development community of the open source browsers has always succeeded in producing patches for published security problems very quickly. Users of Mozilla & Co. have not remained unprotected from known security hazards, which did happen with the Internet Explorer. So there are no known cases where security holes have been exploited to spread spyware and the like on a large scale.

But this can change any time. Criminal organisations already have their own experts who are able to discover and exploit security holes. This was proven quite impressively by the zero-day exploit for Internet Explorer analyzed by jelmer. It combined a couple of minor problems in a very complex way to achieve higher permissions.

This exploit was found in the wild, before the security problems were known to the public. As Mozilla and Firefox become more widespread, the danger increases that criminals will look for security loopholes and start to exploit them before developers even know about them. And the current versions of Mozilla and Firefox offer too much undefended area for such attacks. But the developers have heard the wakeup calls, and there is hope that the security provisions for Firefox 1.1 will pass the test.

[1] The c't-Browsercheck

[2] Bugzilla: Fix all non-origin URL load processing to track origin principals

[3] Bugzilla: javascript: should never execute with chrome privs

[4] Bugzilla: Stop sharing DOM object wrappers between content and chrome (ju)