Mozilla Firefox - Referer Spoofing Using JavaScript

Summary

Versions of Mozilla Firefox prior to 2.0.0.10 are vulnerable to a race-condition when setting 'window.location' values using JavaScript. In some circumstances, the race-condition can be exploited to spoof referer headers. Specially crafted iframe content can be used to perform cross-site request forgery (CSRF) against sites that accept GET requests and use referer checking for protection.

Attack Goal

The goal of the attack is to have an iframe pointed to one site and then cause the iframe to load a second location. The first site's location should become the referer header when requesting the second location's content. These locations could be on different sites, the same site or even the same page. If this can be accomplished, the attack can be used to defeat simplistic cross-site request forgery (CSRF) protections that depend entirely on the referer header.

Background

In general, Firefox attempts to prevent an iframe's parent from reading/writing content in the iframe's browsing context once the the location is changed. When an iframe location is updated, the iframe is submitted with a referer value of the parent's location. The parent's access to the iframe content is lost once the location is changed, but the parent can continue to exert control over the iframe by changing its location or creating new content. Additionally, if the iframe's new location is set from within its own browsing context, the previous location becomes the referer header value.

There have been several past vulnerabilities related to iframes (e.g., Michal Zalewski's IFRAME snatch, Bugzilla entries #381300 and #343168). These vulnerabilities show that there is a small window of time where the iframe context may be exposed. Using 'setTimeout' or 'setInterval' to load the second location would seem like obvious candidates, but the timers are cancelled once the existing iframe page is unloaded.

But what if the timing approach is inverted? Instead of using a timer to load the second location, a timer is used to the load the first location in the background. Then, once the first location is loaded, the current location is set to the desired site (thus causing the first location to become the referer). Normally this should be impossible, because the iframe should not have two browsing contexts at the same time. But, if the user is presented with 'alert', 'confirm' or 'prompt' dialog and the original iframe's context is persisted long enough for the first location to finish loading, the 'window.location' can be set to the second request; this second request will be submitted with a referer value of the first location.

Realizing the Attack

The following are two approaches to the attack:

Attack Matrix

Which attacks work with what user agents?

User AgentJoke MethodWinding Paths Technique
Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9 YesYes
Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9 YesYes
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9 YesYes
Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9a9pre) Gecko/2007110504 Minefield/3.0a9pre NoYes
Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O 10.4; en-US; rv:1.9a9pre) Gecko/2007110504 Minefield/3.0a9pre NoYes
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a9pre) Gecko/2007110505 Minefield/3.0a9pre NoYes

Notes

Demonstration