For
compatibility or usability reasons, and sometimes out of simple
oversight, certain DOM properties and methods may be invoked across
domains without the usual same-origin check carried out elsewhere.
These exceptions to DOM security rules include: - The ability to look up named third-party windows by their name: by design, all documents have the ability to obtain handles of all standalone windows and <IFRAME> objects they spawn from within JavaScript.
Special builtin objects also permit them to look up the handle of the
document that embeds them as a sub-resource, if any (top and parent); and the document that spawned their window (opener).On top of this, however, many browsers permit arbitrary other named window to be looked up using window.open('',<name>),
regardless of any relation - or lack thereof - between the caller and
the target of this operation. This poses a potential security problem
(or at least may be an annoyance) when multiple sites are open
simultaneously, one of them rogue: although most of user-created
windows and tabs are not named, many script-opened windows, IFRAMEs, or
"open in new window" link targets, have specific names.Trivia: window.name property, set for top-level windows or <IFRAME>
containers, is a convenient way to write and read back session-related
tokens in absence of cookies. The information stored there is preserved
across page transitions, until the window is closed or renamed.
- window.postMessage API:
this new mechanism introduced in several browsers permits two willing
windows who have each other's handles to exchange text-based messages
across domains as an explicit feature. The receiving party must opt in
by registering an appropriate event handler (via window.addEventListener()), and has the opportunity to examine MessageEvent.origin property to make rudimentary security decisions.
A survey of these exceptions is summarized below: Test description | MSIE6 | MSIE7 | MSIE8 | FF2 | FF3 | Safari | Opera | Chrome | Android | Can window.open() look up unrelated windows? | YES | YES | NO | YES | YES | YES | NO | YES* | YES | Can frames[] look up unrelated windows? | NO | NO | NO | NO | NO | NO | NO | NO | NO | Can <win>.frames[] access third-party IFRAMEs? | YES | YES | NO | YES | YES | YES | NO | YES* | YES | Is <win>.frames[] iterator permitted? | YES | YES | YES | NO | NO | NO | (NO) | NO | NO | Can window.open() reposition unrelated windows? | YES | YES | NO | YES | YES | YES | NO | YES* | YES | Can <win>.history.* methods be called on unrelated targets? | NO | NO | (NO) | YES | YES | YES | NO | YES* | YES | Can <win>.location.* properties be set on unrelated targets? | YES | YES | (NO) | YES | YES | YES | NO | YES* | YES | Can <win>.location.* methods be called on unrelated targets? | YES | YES | (NO) | YES | YES | YES | NO | YES* | YES | Can <win>.document.write() be called on unrelated targets? | NO | NO | NO | YES | NO | NO | NO | NO | NO | Can TARGET= links reposition unrelated targets? | YES | YES | NO | YES | YES | YES | YES | YES* | YES | Is setting window.on* properties possible across domains? | YES (?) | YES (?) | YES (?) | NO | NO | NO | NO | NO | NO | Is setting window.opener possible across domains? | YES | YES | NO | NO | NO | NO | NO | NO | NO | Is setting window.name possible across domains? | YES | YES | NO | NO | NO | NO | NO | NO | NO | Is calling frameElements methods possible across domains? | NO | NO | NO | YES | NO | NO | NO | NO | NO | Can top-level documents navigate subframes of third-party frames? | YES | YES | NO | YES | YES | YES | NO | YES | YES | Is postMessage API supported? | NO | NO | YES | NO | YES | NO | YES | YES | NO |
* In Chrome, this succeeds only if both tabs share a common renderer process, which limits the scope of possible attacks. As
a consequence of cross-domain security controls being largely an
afterthought, there is no strong compartmentalization and separation of
browser-managed resource loading, cache, and metadata management for
unrelated, previously visited sites - nor any specific protections that
would prevent one site from exploiting these mechanisms to unilaterally
and covertly collect fairly detailed information about user's general
browsing habits. Naturally, when the ability for www.example-bank.com to find out that their current visitor also frequents www.example-casino.com
is not mitigated effectively, such a design runs afoul of user's
expectations and may be a nuisance. Unfortunately, there is no good
method to limit these risks without severely breaking backward
compatibility, however. Aside from coding vulnerabilities such as cross-site script inclusion, some of the most important browsing habit disclosure scenarios include: - Reading back CSS :visited class on links: cascading stylesheets support a number of pseudo-classes
that may be used by authors to define conditional visual appearance of
certain elements. For hyperlinks, these pseudo-classes include :link (appearance of an unvisited link), :hover (used while mouse hovers over a link), :active (used while link is selected), and :visited (used on previously visited links).Unfortunately, in conjunction with the previously described getComputedStyle and currentStyle
APIs, which are designed to return current, composite CSS data for any
given HTML element, this last pseudo-class allows any web site to
examine which sites (or site sub-resources) of an arbitrarily large set
were visited by the victim, and which were not: if the computed style
of a link to www.example.com has :visited properties applied to it, there is a match.
Trivia: even in absence of these APIs, or with JavaScript
disabled, somewhat less efficient purely CSS-based enumeration is
possible by referencing a unique server-side image via target-specific :visited descriptors (more).
- Full-body CSS theft: as indicated in earlier sections,
CSS parsers are generally very strict - but they fail softly: in case
of any syntax errors, they do not give up, but rather attempt to locate
the next valid declaration and resume parsing from there (this behavior
is notably different from JavaScript, which uses a more relaxed
parser, but gives up on the first syntax error). This particular
well-intentioned property permits a rogue third-party site to include
any HTML page, such as mbox.example-webmail.com, as a faux stylesheet - and have the parser extract CSS definitions embedded on this page between <STYLE> and </STYLE> tags only, silently ignoring all the HTML in between.Since
many sites use very different inline stylesheets for logged in users
and for guests, and quite a few services permit further page
customizations to suit users' individual tastes - accessing the getComputedStyle or currentStyle after such an operation enables the attacker to make helpful observations about victim's habits on targeted sites.
- Resource inclusion probes with onload and onerror checks: many of the sub-resource loading tags, such as <IMG>, <SCRIPT>, <IFRAME>, <OBJECT>, <EMBED>, or <APPLET>, will invoke onload or onerror handlers (if defined) to communicate the outcome of an attempt to load the requested URL.Since
it is a common practice for various sub-resources on complex web sites
to become accessible only if the user is authenticated (returning HTTP
3xx or 4xx codes otherwise), the attacker may carry out rogue attempts
to load assorted third-party URLs from within his page, and determine
whether the victim is authenticated with cookies on any of the targeted
sites.
- Image size fingerprinting: a close relative of onload and onerror probing is the practice of querying Image.height, Image.width, getComputedStyle or currentStyle APIs on <IMG>
containers with no dimensions specified by the page they appear on. A
successful load of an authentication-requiring image would result in
computed dimensions different from these used for a "broken image"
stub.
- Document structure traversal: most browsers permit pages to look up third-party named windows or <IFRAME>
containers across domains. This has two important consequences in the
context of user fingerprinting: one is that may be is possible to
identify whether certain applications are open at the same time in
other windows; the other is that by loading third-party applications in
an <IFRAME> and trying to look up their sub-frames, if
used, often allows the attacker to determine if the user is logged in
with a particular site.On top of that, some browsers also leak
information across domains by throwing different errors if a property
referenced across domains is not found, and different if found, but
permission is denied. One such example is the delete <win>.program_variable operator.
- Cache timing:
many resources cached locally by the browser may, when requested, load
in a couple milliseconds - whereas fetching them from the server may
take a longer while. By timing onload events on elements such as <IMG> or <IFRAME>
with carefully chosen target URLs, a rogue page may tell if the
requested resource, belonging to a probed site, is already cached -
which would indicate prior visits - or not.The probe works only
once, as the resources probed this way would be cached for a while as a
direct result of testing; but premature retesting could be avoided in a
number of ways.
- Pseudo-random number generator probing: a research paper
by Amit Klein explores the idea of reconstructing the state of
non-crypto-safe pseudo-random number generators used globally in
browsers for purposes such as implementing Javascript Math.random(), or generating multipart/form-data MIME boundaries, to uniquely identify users and possibly check for certain events across domains.
Assorted tests related to the aforementioned side channels: Test description | MSIE6 | MSIE7 | MSIE8 | FF2 | FF3 | Safari | Opera | Chrome | Android | Is detection of :visited styles possible? | YES | YES | YES | YES | YES | YES | YES | YES | YES | Can image sizes be read back via CSS? | NO | NO | NO | YES | YES | YES | NO | YES | YES | Can image sizes be read back via Image object? | YES | YES | YES | YES | YES | YES | YES | YES | YES | Does CSS parser accept HTML documents as stylesheets? | YES | YES | YES | YES | YES | YES | YES | YES | YES | Does onerror fire on all common HTTP errors? | YES | YES | YES | YES | YES | YES | YES | YES | YES | Is delete <win>.var probe possible? | NO | NO | NO | YES | YES | NO | NO | NO | NO |
Note: Chris Evans and Billy Rios explore many of these vectors in greater detail in their 2008 presentation, "Cross-Domain Leakiness".
|