home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

JavaScript: The Definitive Guide

Previous Chapter 20
JavaScript Security

20.2 Security Holes and Security Hobbles

The approach to JavaScript security in Navigator 2.0 and 3.0 has been to first identify security holes through which private information could be exported, and then to plug those holes. Typically, security holes are plugged by implementing a "security hobble"--i.e., by restricting or "hobbling" the capabilities of JavaScript so that the hole cannot be exploited. For example, the History object in client-side JavaScript is an array of the URLs that the user has previously visited during the current browsing session. Because this information is private, JavaScript has been hobbled so that it cannot access the elements of this array. Because of this hobble, we are left with a History object that supports only forward(), back(), and go() methods.

The problem with an identify-and-patch approach is that it can be difficult to identify security holes, and that there is no way of knowing when you've found all possible holes. A web browser is a complex thing, and JavaScript is a powerful scripting language. In Navigator 2.0 and 2.0.1, these two facts intersected to produce a number of security holes that had not been patched. For example, in Navigator 2.0, a JavaScript program could open a new window to display the special about:cache URL. Then it could read the links[] array of the document of that window to obtain information about cached files (and hence browsing history) of the client browser. This information could be placed in hidden fields of an HTML form and submitted to the web server without the user's knowledge. The about:cache URL could be displayed in a window so small that the user wouldn't notice it, or it could even be displayed in an invisible frame (i.e., one with zero height). A similar attack used the file:/// URL to discover the contents of the root directory of the client's system, and could recursively proceed to determine the client's entire directory structure.

Another attack, one that was undoubtedly exploited to some extent on the Internet, allowed a JavaScript program to automatically send email to any desired address whenever the user visited a web page. What this does, of course, is steal the email address of everyone who visits a page. This attack was accomplished by using the submit() method of the Form object to automatically submit an empty (and invisible) HTML form to a mailto: URL.

Not all security holes in Navigator 2.0 and 2.0.1 were the result of unforeseen interactions between the features of JavaScript and the rest of Navigator. Some were just bugs, plain and simple. For example, one bug allowed a web page to leave JavaScript code behind after it was unloaded. This code could do anything it wanted to. It could violate security by checking the URL of the document currently being viewed once every second and sending that information off to a web server or email address. Instead of publicizing a user's browsing history, this security hole publicized a user's browsing future!

Another serious bug-induced security hole was related to a bug in the security hobble for the FileUpload form element. JavaScript is hobbled so that it is not allowed to set the filename that appears in the FileUpload element. If it could set it, it would clearly be trivial to send the contents of any file on the client's computer (a password file, perhaps) across the network to a web server, an obviously grave breach of security. Unfortunately, there the hobble that prevented this was not sufficient, and there was a straightforward trick that would allow a JavaScript program to specify what file was to be uploaded. Fortunately, this trick was not publicized, and a new version of Navigator, with this bug fixed, was quickly released.[1]

[1] For more information on this and other Netscape 2.0 and 2.0.1 security holes, see the "JavaScript Problems I've Discovered" web pages by John Robert LoVerso of the OSF Research Institute at http://www.osf.org/~loverso/javascript.

Many of the security holes discovered in Navigator 2.0 were patched with hobbles in Navigator 2.0.1, and Netscape even added the option to disable JavaScript entirely (the ultimate hobble) in this version of the browser. Unfortunately, a new crop of holes were discovered almost as soon as 2.0.1 was released. Because of the continuing problem with security holes, and because of the resulting bad press, Netscape soon released Navigator 2.0.2, which fixed all known security-related bugs and implemented a very general hobble that would, hopefully, spell an end to security holes. With this hobble implemented, a JavaScript program is not allowed to read the properties of any window (or frame) or the properties of any objects within a window if the contents of that window were loaded from a different web server than the JavaScript program itself. This hobble rules out a whole class of security holes. It means that a program cannot open a new window to display about:cache, file:///, or some other URL and extract information from that URL. This hobble is particularly important when a corporate firewall is in use--it prevents a script loaded from the Internet from opening a new window and going browsing in a private intranet.

The bug fixes and the mega-hobble in Navigator 2.0.2 were included in Navigator 3.0 and appear to have been quite effective at patching security holes--there has been a long spell without any new ones being discovered. Unfortunately a new hole has recently been discovered. The hobble that was inserted to prevent automatic submission of a form to a mailto: URL only worked for certain form encodings and methods. Embarrassingly for Netscape, it turns out that other combinations of form submission methods and encodings still allow a form to be automatically submitted without user confirmation, effectively stealing the user's email address. By the time this book is published, the hobble will have been strengthened, and this security hole will have been patched (for good this time, we hope) in Navigator 3.0.1.

Security Hobbles in Navigator 3.0

The following is a complete list of security hobbles in Navigator 3.0.1. While not all earlier versions of Navigator implement all of these hobbles, you should assume that they are all in place, if you want your code to be portable to the latest versions of Navigator. If you are yourself worried about private information being exported through security holes, then you should of course upgrade to the most recent version of Navigator that has all of these hobbles implemented.

  • The History object does not allow access to its array elements or to its next, previous, or current properties that contain URLs that the browser has previously visited. These URLs are private information and scripts are not allowed to access them because they could otherwise export them through an HTML form.

  • The value property of the Password object does not contain the user's input to that Password field. The user's input is submitted with the form, but is hidden from the script. A script can read and write the value property, but cannot affect the value displayed in the field nor obtain the user's actual input to that field. In theory, if a user trusts a CGI script with their password, they should also trust a script from the same site with it, but because passwords are such sensitive information, access is limited on a "need to know" basis. Since JavaScript does not "need to know" the value of a password intended for a CGI script, it is not allowed to know.

  • The value property of the FileUpload object is read-only. If this property could be set by JavaScript, a script could set it to any desired filename and cause the form to upload the contents of any specified file (such as a password file) to the server. There was a flaw in this hobble in Navigator 2.0.1 which allowed malicious scripts to upload arbitrary files. The hobble has been strengthened and correctly implemented in 2.0.2 and later versions.

  • A form that is to be submitted to a mailto: URL cannot be submitted without the user's explicit approval. If this were not the case, then a script could steal the user's email address by submitting an empty form automatically through the Form.submit() method or by tricking the user into clicking on a Submit button. Prior to Navigator 3.0.1, this hobble was only partially implemented--user confirmation for mailto: forms was only required when the form was submitted with the POST method and the default encoding type. In 3.0.1, confirmation is required for all mailto: form submissions.

  • JavaScript cannot read properties of a window if the contents of that window were loaded from a different server than the JavaScript code being run. A "different server" is any server on a different host, or a server on the same host using a different protocol. This prevents scripts from one site from stealing any kind of information from other sites (which might be behind firewalls, for example).

  • A JavaScript program cannot run for a very long time without periodic user confirmation that it should continue. After every one million "branches" (i.e., if statements and loop iterations) that the JavaScript interpreter executes, it pops up a dialog notifying the user that the script is still running and asks if it should continue to execute it. This helps prevent JavaScript programs from using a client machine as a computation server, or from attempting a "denial of service" attack by locking up the browser or slowing it down so much as to be unusable. Note, however, that this doesn't help all that much. One trivial denial-of-service attack simply involves repeatedly popping up dialog boxes with alert().

  • A JavaScript program cannot close a browser window without user confirmation unless it opened the window itself. This prevents malicious scripts from calling self.close() to close the user's browsing window, thereby causing Navigator to exit. There is one exception to this hobble. The first page loaded when Navigator starts up is allowed to close the initial browsing window. This exception enables power users to create home pages that close the default browsing window and open one or more custom windows.

Security in Internet Explorer

Since Internet Explorer 3.0 has not been around as long and is not used as commonly as Navigator, it has not been subjected to such intense scrutiny, as Netscape's browser was. Thus, while IE does not have a history of security holes its implementation of JavaScript, there may yet be holes discovered.

The one known JavaScript security hole in Internet Explorer is a major one. IE does not contain the security hobble described above which prevents a script from one URL from reading the properties of a script from another URL. This means, for example, that if you use IE on Windows 95, a script could load the contents of a URL like file:///C|\Windows\StartMenu\ into a hidden frame, and then examine the links[] array of that frame to determine what programs you have installed in your Windows start menu. This private information might then be submitted in a hidden field of some innocuous looking form.

Previous Home Next
JavaScript and Security Book Index The domain Property

HTML: The Definitive Guide CGI Programming JavaScript: The Definitive Guide Programming Perl WebMaster in a Nutshell