11.22.24
Browser Security Handbook, part 2.3

Navigation and content inclusion across domains

There are numerous mechanisms that permit HTML web pages to include and display remote sub-resources through HTTP GET requests without having these operations subjected to a well-defined set of security checks:

  • Remote scripts: <SCRIPT SRC="..."> tags may be used to issue GET requests to arbitrary sites, likewise. A relatively relaxed JavaScript (or E4X XML) parser is then applied to the received content; if the response passes off as something resembling structurally sound JavaScript, this cross-domain payload may then be revealed to other scripts on the current page; one way to achieve this goal is through redefining callback functions or modifying object prototypes; some browsers further help by providing verbose error messages to onerror handlers. The possibility of cross-domain data inclusion poses a risk for all sensitive, cookie-authenticated JSON interfaces, and some other document formats not originally meant to be JavaScript, but resembling it in some aspects (e.g., XML, CSV).Note: quite a few JSON interfaces not intended for cross-domain consumption rely on a somewhat fragile defense: the assumption that certain very specific object serializations ({ param: "value"}) or meaningless prefixes (&&&START&&&) will not parse via <SCRIPT SRC="...">; or that endless loop prefixes such as while (1) will prevent interception of the remainder of the data. In most cases, these assumptions are not likely to be future-safe; a better option is to require custom XMLHttpRequest headers, or employ a parser-breaking prefix that is unlikely to ever work as long as the basic structure of JavaScript is maintained. One such example is the string of )]}', followed by a newline.
  • Remote stylesheets: <LINK REL="stylesheet" HREF="..."> tags may be used in a manner similar to <SCRIPT>. The returned data would be subjected to a considerably more rigorous CSS syntax parser. On one hand, the odds of a snippet of non-CSS data passing this validation are low; on the other, the parser does not abort on the first syntax error, and continues parsing the document unconditionally until EOF - so scenarios where some portions of a remote document contain user-controlled strings, followed by sensitive information, are of concern. Once properly parsed, CSS data may be disclosed to non-same-origin scripts through getComputedStyle or currentStyle properties (the former is W3C-mandated). One potential attack of this type was proposed by Chris Evans; in Internet Explorer, the impact may be greater due to the more relaxed newline parsing rules.
  • Embedded objects and applets: <EMBED SRC="...">, <OBJECT CODEBASE="...">, and <APPLET CODEBASE="..."> tags permit arbitrary resources to be retrieved via GET and then supplied as input to browser plugins. The exact effect of this action depends on the plugin to which the resource is routed, a factor entirely controlled by the author of the page. The impact is that content never meant to be interpreted as a plugin-based program may end up being interpreted and executed in a security context associated with the serving host.
  • Document-embedded frames: <FRAME> and <IFRAME> elements may be used to create new document rendering containers within the current browser window, and to fetch any target documents via GET. These documents would be subject to same-origin checks once loaded.

Note that on all of the aforementioned inclusion schemes other than <FRAME> and <IFRAME>, any Content-Type and Content-Disposition HTTP headers returned by the server for the sub-resource are mostly ignored; there is no opportunity to authoritatively instruct the browser about the intended purpose of a served document to prevent having the data parsed as JavaScript, CSS, etc.

In addition to these content inclusion methods, multiple ways exist for pages to initiate full-page transitions to remote content (which causes the target document for such an operation to be replaced with a brand new document in a new security context):

  • Link targets: the current document, any other named window or frame, or one of special window classes (_blank, _parent, _self, _top) may be targeted by <A HREF="..."> to initiate a regular, GET-based page transition. In some browsers, such a link may be also automatically "clicked" by JavaScript with no need for user interaction (for example, using the click() method).
  • Refresh and Location directives: HTTP Location and Refresh headers, as well as <META HTTP-EQUIV="Refresh" VALUE="..."> directives, may be used to trigger a GET-based page transition, either immediately or after a predefined time interval.
  • JavaScript DOM access: JavaScript code may directly access location.*, window.open(), or document.URL to automatically trigger GET page transitions, likewise.
  • Form submission: HTML <FORM ACTION="..."> tags may be used to submit POST and GET requests to remote targets. Such transitions may be triggered automatically by JavaScript by calling the submit() method. POST forms may contain payloads constructed out of form field name-value pairs (both controllable through <INPUT NAME="..." VALUE="..."> tags), and encoded according to application/x-www-form-urlencoded (name1=value1&name2=value2..., with %nn encoding of non-URL-safe characters), or to multipart/form-data (a multipart MIME-like format), depending on ENCTYPE= parameter.In addition, some browsers permit text/plain to be specified as ENCTYPE; in this mode, URL encoding is not applied to name=value pairs, allowing almost unconstrained cross-domain POST payloads.Trivia: POST payloads are opaque to JavaScript. Without server-side cooperation, or the ability to inspect the originating page, there is no possibility for scripts to inspect the data posted in the request that produced the current page. The property might be relied upon as a crude security mechanism in some specific scenarios, although it does not appear particularly future-safe.

Related tests:

Test description MSIE6 MSIE7 MSIE8 FF2 FF3 Safari Opera Chrome Android
Are verbose onerror messages produced for <SCRIPT>? YES YES YES YES NO NO NO NO NO
Are verbose onerror messages produced for <STYLE>? NO NO NO NO NO NO NO NO NO
Can links be auto-clicked via click()? YES YES YES NO NO NO YES NO NO
Is getComputedStyle supported for CSS? (W3C) NO NO NO YES YES YES YES YES YES
Is currentStyle supported for CSS? (Microsoft) YES YES YES NO NO NO YES NO NO
Is ENCTYPE=text/plain supported on forms YES YES YES YES YES NO YES NO NO

Note that neither of the aforementioned methods permits any control over HTTP headers. As noted earlier, more permissive mechanisms may be available to plugin-interpreted programs and other non-HTML data, however.

Arbitrary page mashups (UI redressing)

Yet another operation permitted across domains with no specific security checks is the ability to seamlessly merge <IFRAME> containers displaying chunks of third-party sites (in their respective security contexts) inside the current document. Although this feature has no security consequences for static content - and in fact, might be desirable - it poses a significant concern with complex web applications where the user is authenticated with cookies: the attacker may cleverly decorate portions of such a third-party UI to make it appear as if they belong to his site instead, and then trick his visitors into interacting with this mashup. If successful, clicks would be directed to the attacked domain, rather than attacker's page - and may result in undesirable and unintentional actions being taken in the context of victim's account.

There are several basic ways to fool users into generating such misrouted clicks:

  • Race condition attacks: lastly, the attacker may simply opt for hiding the target UI (as a frame, or as a separate window) underneath his own, and reveal it only miliseconds before the anticipated user click, not giving the victim enough time to notice the switch, or react in any way. Scripts have the ability to track mouse speed and position over the entire document, and close or rearrange windows, but it is still relatively difficult to reliably anticipate the timing of single, casual clicks. Timing solicited clicks (e.g. in action games) is easier, but there is a prerequisite of having an interesting and broadly appealing game to begin with.

In all cases, the attack is challenging to carry out given the deficiencies and incompatibilities of CSS implementations, and the associated difficulty of determining the exact positioning for the targeted UI elements. That said, real-world exploitation is not infeasible. In two of the aforementioned attack scenarios, the fact that that the invisible container may follow mouse pointer on the page makes it somewhat easier to achieve this goal, too.

Also note that the same UI redress possibility applies to <OBJECT>, <EMBED>, and <APPLET> containers, although typically with fewer security implications, given the typical uses of these technologies.

UI redress attacks gained some prominence in 2008, after Jeremiah Grossman and Robert 'RSnake' Hansen coined the term clickjacking and presented the attack to the public. Discussions with browser vendors on possible mitigations are taking place (example), but no definitive solutions are to be expected in the short run. So far, the only freely available product that offers a reasonable degree of protection against the possibility is NoScript (with the recently introduced ClearClick extension). To a much lesser extent, on opt-in defense is available Microsoft Internet Explorer 8, Safari 4, and Chrome 2, through a X-Frame-Options header (reference), enabling pages to refuse being rendered in any frames at all (DENY), or in non-same-origin ones only (SAMEORIGIN).

On the flip side, only a single case of real-world exploitation is publicly known as of this writing.

In absence of browser-side fixes, there are no particularly reliable and non-intrusive ways for applications to prevent attacks; one possibility is to include JavaScript to detect having the page rendered within a cross-domain <IFRAME>, and try to break out of it, e.g.:

try {
 
if (top.location.hostname != self.location.hostname) throw 1;
} catch (e) {
  top
.location.href = self.location.href;
}

It should be noted that there is no strict guarantee that the update of top.location would always work, particularly if dummy setters are defined, or if there are collaborating, attacker-controlled <IFRAME> containers performing conflicting location updates through various mechanisms. A more drastic solution would be to also overwrite or hide the current document pending page transition, or to perform onclick checks on all UI actions, and deny them from within frames. All of these mechanisms also fail if the user has JavaScript disabled globally, or for the attacked site.

Likewise, because of the features of JavaScript, the following is enough to prevent frame busting in Microsoft Internet Explorer 7:

<script>
var location = "clobber";
</script>
<iframe src="http://www.example.com/frame_busting_code.html"></iframe>

Joseph Schorr cleverly pointed out that this behavior may be worked around by creating an <A HREF="..." TARGET="_top"> HTML tag, and then calling the click() on this element; on the other hand, flaws in SECURITY=RESTRICTED frames render even this variant of limited use.

Relevant tests:

Test description MSIE6 MSIE7 MSIE8 FF2 FF3 Safari Opera Chrome Android
Is CSS opacity supported ("decoy underneath")? YES YES YES YES YES YES YES YES YES
Are partly obstructed IFRAME containers clickable ("decoy on top")? YES YES
YES YES YES YES YES YES
Is cross-domain scrollBy scrolling permitted? NO NO NO NO NO NO NO NO n/a
Is cross-domain anchor-based frame positioning permitted? YES YES YES YES YES YES YES YES n/a
Is X-Frame-Options defense available? NO NO YES NO NO YES NO YES n/a
Views: 8490 | Added by: b1zz4rd | Rating: 0.0/0
Total comments: 0
Name *:
Email *:
Code *:
close