Professional Documents
Culture Documents
Barth Weinberger Song
Barth Weinberger Song
@SCOPECHAIN GLOBAL window window Math Math document local - document document decodeURI encodeURIComponent isNaN NaN NaN undefined undefined Infinity Infinity
__proto__ Window Shell - 1c700000 object - 1c700f60 object - 1c701340 decodeURIComponent escape kjsprint parseFloat 1c710090 a 1c7100a0
__proto__ __proto__ RangeError EvalError URIError TypeError ReferenceError SyntaxError object - 1c701140 dumpHeap object - 1c701200 eval object - 1c701040 parseInt
Date Number Boolean Array object - 1c700020 object - 1c701320 String Error RegExp encodeURI isFinite object - 1c701280 unescape
object - 1c701300 object - 1c700e20 object - 1c700de0 object - 1c700f20 object - 1c700ee0 object - 1c700e60 object - 1c700ea0
Object __proto__ __proto__ prototype constructor constructor prototype prototype constructor prototype constructor constructor prototype prototype constructor object - 1c701240 object - 1c700f80 object - 1c700fc0
object - 1c700c60 object - 1c700c20 object - 1c700be0 object - 1c700b20 __proto__ object - 1c7012e0 object - 1c700b60 object - 1c7008c0 object - 1c700da0 object - 1c700860 object - 1c700a40 object - 1c7009e0 object - 1c700920 object - 1c700980 object - 1c700d60
Function now parse UTC constructor constructor prototype prototype constructor prototype prototype constructor __proto__ prototype constructor fromCharCode __proto__ constructor prototype __proto__ __proto__ __proto__ __proto__ __proto__ prototype constructor __proto__ object - 1c7011c0 __proto__ object - 1c701080 __proto__ object - 1c701100
number prototype - 1c7004e0 date prototype - 1c700680 boolean prototype - 1c700440 array prototype - 1c700400 object - 1c7012c0 string prototype - 1c700420 error prototype - 1c7007c0 regExp prototype - 1c7006a0 __proto__ __proto__ __proto__ __proto__
object - 1c700d20 object - 1c700ca0 object - 1c700ce0 valueOf toExponential toFixed toLocaleString toPrecision toString __proto__ __proto__ toString valueOf __proto__ __proto__ __proto__ __proto__ __proto__ object - 1c700ba0 __proto__ toString __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ exec test toString compile __proto__ __proto__ __proto__
__proto__ object - 1c700580 object - 1c700500 __proto__ __proto__ __proto__ object prototype - 1c7000a0 __proto__ __proto__ object - 1c700700 object - 1c700740 object - 1c700780 object - 1c7006c0 __proto__ __proto__ __proto__ __proto__
__proto__ __proto__ __proto__ object - 1c700600 object - 1c7005c0 object - 1c700540 object - 1c700640 object - 1c700460 object - 1c7004a0 toLocaleString toString valueOf prototype constructor __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__ hasOwnProperty isPrototypeOf propertyIsEnumerable __proto__ object - 1c700820
__proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ object - 1c700100 object - 1c7000c0 object - 1c700140 object - 1c700aa0 object - 1c700240 object - 1c700280 object - 1c7002c0 object - 1c700300 object - 1c700180 object - 1c700200 object - 1c7001c0 __proto__ __proto__ __proto__ __proto__ __proto__
__proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__ __proto__
3.3 Implementation
Attacker Global Object@0x1a9e1420 Victim Global Object@0x1a9e2940
We implemented our leak detection algorithm in a 1,393 document document Object
gorithm can construct heap graphs of complex Web ap- __proto__ object@0x1a9e3380
nodes and 130,995 edges. These graphs are often vi- object@0x1a9e3be0
__proto__
the heap graph of an empty document. Although our in-
object@0x1a9e3ba0
strumentation slows down the browser, the instrumented __proto__
browser is still faster than Safari 3.1, demonstrating that Object Prototype@0x1a9e2980
4 Vulnerabilities and Exploitation Figure 2: Selected nodes from a heap graph showing a
In this section, we use our leak detector to detect cross- cross-origin JavaScript capability leak of the document
origin JavaScript capability leaks in WebKit. After object, object@0x1a9e3c20, after a navigation.
discovering two new vulnerabilities, we illuminate the
vulnerabilities by constructing proof-of-concept exploits
using three different techniques. In addition, we apply The layoutTestController contains a number of
our understanding of JavaScript pointers to breaking the objects that are shared between all security origins. Our
Subspace [11] mashup design. instrumentation flags JavaScript pointers to these objects
as suspicious, and, in fact, these pointers are exploitable
4.1 Test Suite in the test configuration of the browser. However, these
To find example cross-origin JavaScript capability leaks, pointers are not present in the release configuration of
we run our instrumented browser through a test suite. the browser because the layoutTestController
Ideally, to reduce the number of false negatives, we itself is present only during testing. We white listed
would use a test suite with high coverage. Because our these objects as visible to multiple security origins.
goal is to find example vulnerabilities, we use the We-
bKit project’s regression test suite. This test suite exer-
cises a variety of browser security features and tests for 4.2 Navigation and Document
the non-existence of past security vulnerabilities. Using
this test suite, our instrumentation found two new high- Vulnerability. When the browser navigates a window
severity cross-origin JavaScript capability leaks. Instead from one Web page to another, the browser replaces the
of attempting to discover and patch all these leaks, we document originally displayed in the window with a new
recommend a more comprehensive defense, detailed in document retrieved from the network. Our instrumen-
Section 5. tation found that WebKit leaks a JavaScript pointer to
WebKit’s regression test suite uses a JavaScript ob- the new document object every time a window navi-
ject named layoutTestController to facilitate its gates because the DOM updates the document prop-
tests. For example, each tests notifies the testing harness erty of the old global object to point to the new doc-
that the test is complete by calling the notifyDone ument occupying the frame. This leak is visible in
method of the layoutTestController. We mod- the heap graph (see Figure 2) as a dashed line from
ified this notifyDone method to store the JavaScript Attacker Global Object@0x1a9e1420 to the
heap graph in the file system after each test completes. honest document object, object@0x1a9e3c20.
Exploit. Crafting an exploit for this vulnerability is
Attacker Global Object@0x1c1d0040 Victim Global Object@0x1c1d13e0
subtle. An attacker cannot simply hold a JavaScript
location location Object
pointer to the old global object and access its object@0x1c1d2720 object@0x1c1d2740
document property because all JavaScript pointers to
__proto__ __proto__ object@0x1c1d1e20
global objects are updated to the new global object when
object@0x1c1d2700 prototype
a frame is navigated navigation [10]. However, the prop- __proto__
erties of the old global object are still visible to func- Object Prototype@0x1c1d1420
4.3 Lazy Location and History Because the beforeunload event handler runs af-
ter the child frame has attempted to frame bust, the at-
Vulnerability. For performance, WebKit instantiates tacker’s location object has been instantiated by the hon-
the window.location and window.history ob- est document and is mistakenly attached to the honest
jects lazily the first time they are accessed. When instan- Object.prototype (see Figure 3). The attacker ob-
tiating these objects, the browser constructs their proto- tains a pointer to the honest Object.prototype by
type chains. In some situations, WebKit constructs an traversing this prototype chain.
incorrect prototype chain that connects these objects to Once the attacker has obtained a JavaScript pointer
the Object.prototype of a foreign security origin, to the honest Object.prototype, there are a num-
creating a vulnerability if, for example, a document uses ber of techniques the attacker can use to compromise the
the following script to “frame bust” [12] in order to avoid honest security origin completely. We describe two rep-
clickjacking [7] attacks: resentative examples:
top.location.href = 1. Many Web sites use JavaScript libraries to smooth
"http://example.com/"; over incompatibilities between browsers and reuse
common code. One of the more popular JavaScript The JavaScript engine will call the attacker’s setter
libraries is the Prototype library [22], which is used function instead of storing honest_dom_node
by CNN, Apple, Yelp, Digg, Twitter, and many oth- into the foo property of obj, causing the
ers. If the honest page uses the Prototype library, variable x to contain a JavaScript pointer to
the attacker can inject arbitrary script into the hon- honest_dom_node. Once the attacker’s func-
est page by abusing the powerful invoke function tion is called with a pointer to the honest DOM
defined by the Prototype library. For example, the node, the attacker can inject malicious script into
attacker can use the follow script: the honest document using the innerHTML API.
var honest_function = 4.4 Capability Leaks in Subspace
honest_object_prototype.
__defineGetter__; The Subspace mashup design [11] lets a trusted integra-
var honest_array = tor communicate with an untrusted gadget by passing a
honest_function. JavaScript pointer from the integrator to the gadget:
argumentNames(); A Subspace JavaScript object is created in
honest_array.push(frames[0]); the top frame and passed to the mediator
honest_array.invoke("setTimeout", frame... The mediator frame still has access to
"... malicious script ..."); the Subspace object it obtained from the top
In the Prototype library, arrays contain a method frame, and passes this object to the untrusted
named invoke that calls the method named frame. [11]
by its first argument on each element of its ar-
ray, passing the remaining arguments to the in- Unfortunately, the Subspace design relies on leaking
voked method. To abuse this method, the at- a JavaScript pointer from a trusted security origin to
tacker first obtains a pointer to an honest ar- an untrusted security origin, creating a cross-origin
ray object by calling the argumentNames JavaScript capability leak. By leaking the communica-
method of an honest function reachable from tion object, Subspace also leaks a pointer to the trusted
the honest_object_prototype object. The Object.prototype via the prototype chain of the
attacker then pushes the global object of the communication object.
child frame onto the array and calls the honest To verify this attack, we examined CrossSafe [25], a
document’s setTimeout method via invoke. public implementation of Subspace. We ran a Cross-
The honest global object has a reference mon- Safe tutorial in our instrumented browser and examined
itor that prevents the attacker from accessing the resulting heap graph. Our detector found a cross-
setTimeout directly, but the reference monitor origin JavaScript capability leak: the channel object
allows invoke to access setTimeout because is leaked from the integrator to the gadget. By repeat-
invoke is defined by the honest document. edly dereferencing the __proto__ property, the un-
2. Even if the honest Web page does not use a complex trusted gadget can obtain a JavaScript pointer to the
JavaScript library, the attacker can often find a snip- trusted Object.prototype object. The untrusted
pet of honest script to trick. For example, suppose gadget can then inject a malicious script into the trusted
the attacker installs a “setter” function for the foo integrator using one of the techniques described in Sec-
property of the honest Object.prototype as tion 4.3.
follows:
5 Defense
function evil(x) {
In this section, we propose a principled defense for
x.innerHTML =
cross-origin JavaScript capability leaks. Our defense ad-
’<img src="about:blank"’ +
dresses the root cause of these vulnerabilities and incurs
’ onerror="... script ...">’;
a minor performance overhead.
});
honest_object_prototype. 5.1 Approach
__defineSetter__(’foo’, evil);
Currently, browser vendors defend against cross-origin
Now, if the honest script stores a DOM node in a JavaScript capability leaks by patching each individual
property of an object as follows: leak after the leak is discovered. We recommend an-
var obj = new Object(); other approach for defending against these vulnerabili-
obj.foo = honest_dom_node; ties: add access control checks throughout the JavaScript
engine. We recommend this principled approach over
ad-hoc leak plugging for two reasons:
• This approach addresses the core design issue un- Although we recommend that browsers adopt the access
derlying cross-origin JavaScript capability leak vul- control paradigm for Web content, other projects, such
nerabilities: the mismatch between the DOM’s ac- as Caja [16] and ADsafe [3], take the opposite approach
cess control security model and the JavaScript en- and elect to enforce an object-capability discipline on
gine’s object-capability security model. the DOM. These projects succeed with this approach be-
• This approach provides a second layer of defense: cause the preceding considerations do not apply: these
if the browser is leak-free, all the access con- projects target new code (freeing themselves from back-
trol checks will be redundant and pass, but if the wards compatibility constraints) that is written in a sub-
browser contains a leak, the access control checks set of JavaScript (freeing themselves from problematic
prevent the attacker from exploiting the leak. language features). For further discussion, see Section 6.
In a correctly implemented browser, Web content will be 5.2 Design
unable to determine whether the browser implements the
access control checks we recommend. The additional We propose adding access control checks to the
access control checks enhance the mechanism used to JavaScript engine by inserting a reference monitor into
enforce the same-origin policy but do not alter the policy each JavaScript object. The reference monitor interposes
itself, resulting in zero compatibility impact. on each get and set operation (described in Section 3)
and performs the following access control check:
Another plausible approach to mitigating these vul-
nerabilities is to adopt an object-capability discipline 1. Let the active origin be the origin of the document
throughout the DOM. This approach mitigates the sever- that defined the currently executing script.
ity of cross-origin JavaScript capability leaks by limiting 2. Let the target origin be the origin that “owns” the
the damage an attacker can wreak with the leaked capa- JavaScript object being accessed, as computed by
bility. For example, if the browser leaks an honest his- the algorithm in Section 3.1.
tory object to the attacker, the attacker would be able to 3. Allow the access if the browser considers the active
manipulate the history object, but would not be able to origin and the target origin to be the same origin
alter the document object. Conceptually, either adding (i.e., if their scheme, hosts, and ports match).
access control checks to the JavaScript engine or adopt- 4. Otherwise, deny access.
ing an object-capability discipline throughout the DOM If the access is denied, the JavaScript engine returns the
resolves the underlying architectural security issue, but value undefined for get operations and simply ig-
we recommend adopting the access control paradigm for nores set operations. In addition to adding these ac-
two main reasons: cess control checks, we record the security origin of each
• Adopting an object-capability discipline through- JavaScript object when the object is created. Our imple-
out the DOM requires “taming” [15] the DOM API. mentation does not currently insert access control checks
The current DOM API imbues every DOM node for delete operations, but these checks could be added
with the full authority of the node’s security origin at a minor performance cost. Some JavaScript objects,
because the API exposes a number of “universal” such as the global object, are visible across origins. For
methods, such as innerHTML that can be used these objects, our reference monitor defers to the refer-
to run arbitrary script. Other researchers have de- ence monitors that already protect these objects.
signed capability-based DOM APIs [4], but taming
5.3 Inline Cache
the DOM API requires a number of non-backwards
compatible changes. A browser that makes these The main disadvantage of performing an access control
changes will be unpopular because the browser will check for every JavaScript property access is the run-
be unable to display a large fraction of Web sites. time overhead of performing the checks. Sophisticated
• The JavaScript language itself has a number of fea- Web applications access JavaScript properties an enor-
tures that make enforcing an object-capability dis- mous number of times per second, and browser vendors
cipline challenging. For example, every JavaScript have heavily optimized these code paths. However, we
object has a prototype chain that eventually leads observe that the proposed access checks are largely re-
back to the Object.prototype, making it dif- dundant and amenable to optimization because scripts
ficult to create a weaker object-capability than virtually always access objects from the same origin.
the Object.prototype. Unfortunately, the Cutting-edge JavaScript engines, including Sa-
Object.prototype itself represents a power- fari 4’s Nitro JavaScript Engine, Google Chrome’s
ful object-capability with the ability to interfere V8 JavaScript engine, Firefox 3.5’s TraceMonkey
with the properties of every other object from the JavaScript engine, and Opera 11’s Carakan JavaScript
same document (e.g., the exploit in Section 4.3.) engine, optimize JavaScript property accesses using an
3.0%
inline cache [24]. (Of the major browser vendors, only
Microsoft has yet to announce plans to implement this 2.5%
optimization.) These JavaScript engines group together
JavaScript objects with the same “structure” (i.e., whose 2.0%
Slowdown
properties are laid out the same order in memory). When 1.5%
a script accesses a property of an object, the engine
caches the object’s group and the memory offset of the 1.0%
6%
(Other JavaScript engines, such as V8, do contain struc-
ture groups that span security origins, but this design 4%