ADsafety Type-based Verification of JavaScript Sandboxing Joe Gibbs Politz Spiridon Aristides Eliopoulos Arjun Guha Shriram Krishnamurthi 1
2
3
third-party ad third-party ad 4
Who is running code in your browser? 5
Who is running code in your browser? 5
Who is running code in your browser? 5
the host you visit 6
the host you visit 6
the host the ad server you visit 6
the host the ad server you visit same JavaScript context 6
the host the ad server you visit <iframe> 6
the host the ad server you visit <iframe> top.location.href 6
Microsoft Web Sandbox Google Facebook JavaScript Caja (FBJS) Yahoo! ADsafe All are defining safe sub-languages 7
8
eval 8
eval 8
eval e 8
eval e wrap(e) 8
eval e wrap wrap(e) 8
” s r e t l fi “ eval “wrappers” e ” s r e t i r w e r “ wrap wrap(e) — Maffeis, Mitchell, and Taly, ESORICS 2009 8
9
eval 9
eval untrusted ADSAFE.get(obj, x) widget 9
eval untrusted ADSAFE.get ADSAFE.get(obj, x) widget 9
• 1, 800 LOC adsafe.js library • 50 calls to three kinds of assertions • 40 type-tests • 5 regular-expression based checks • 60 privileged DOM method calls 10
? • 1, 800 LOC adsafe.js library • 50 calls to three kinds of assertions • 40 type-tests • 5 regular-expression based checks • 60 privileged DOM method calls 10
Type-based Verification of 11
Definition 1 (ADsafety): If all embedded widgets pass JSLint, then: 12
Definition 1 (ADsafety): If all embedded widgets pass JSLint, then: eval() document.write() document.createElement("script") 1.Widgets cannot load new code ... at runtime, or cause ADsafe to load new code on their behalf; 12
Definition 1 (ADsafety): If all embedded widgets pass JSLint, then: eval() document.write() document.createElement("script") 1.Widgets cannot load new code ... at runtime, or cause ADsafe to load new code on their behalf; 12
Definition 1 (ADsafety): If all embedded widgets pass JSLint, then: 1.Widgets cannot load new code at runtime, or cause ADsafe to load new code on their behalf; 2.Widgets cannot obtain direct <div> references to DOM nodes; Untrusted ADsafe <p> <div> Widget <b> 12
Definition 1 (ADsafety): If all embedded widgets pass JSLint, then: 1.Widgets cannot load new code at runtime, or cause ADsafe to load new code on their behalf; 2.Widgets cannot obtain direct <div> references to DOM nodes; Untrusted ADsafe <p> <div> Widget <b> 12
Definition 1 (ADsafety): If all embedded widgets pass JSLint, then: 1.Widgets cannot load new code at runtime, or cause ADsafe to load new code on their behalf; 2.Widgets cannot obtain direct <div> references to DOM nodes; 3.Widgets cannot affect the <div id="WIDGET"> DOM outside of their subtree; and Untrusted ADsafe <p> <div> Widget <b> 12
Definition 1 (ADsafety): If all embedded widgets pass JSLint, then: 1.Widgets cannot load new code at runtime, or cause ADsafe to load new code on their behalf; 2.Widgets cannot obtain direct <div> references to DOM nodes; 3.Widgets cannot affect the <div id="WIDGET"> DOM outside of their subtree; and Untrusted ADsafe <p> <div> Widget <b> 12
Definition 1 (ADsafety): If all embedded widgets pass JSLint, then: 1.Widgets cannot load new code at runtime, or cause ADsafe to load new code on their behalf; 2.Widgets cannot obtain direct references to DOM nodes; 3.Widgets cannot affect the DOM outside of their subtree; and 4.Multiple widgets on the same page cannot communicate. Widget A ADsafe Widget B 12
eval Goal: Verify ADsafe ADSAFE.get ADSAFE.get(obj, x) 13
eval Goal: Verify ADsafe ADSAFE.get ADSAFE.get(obj, x) untrusted, but passes JSLint 13
eval Goal: Verify ADsafe Goal: model JSLint ADSAFE.get ADSAFE.get(obj, x) untrusted, but passes JSLint 13
JSLint ensures: no DOM node references <div> Untrusted ADsafe <p> <div> Widget <b> “Widgets cannot obtain direct references to DOM nodes.” 14
JSLint ensures: no DOM node references bunch = { ADsafe ensures: __nodes__ : array of nodes , only “safe” append: function ..., methods on getText: function ..., bunches ... 20 functions } <div> Untrusted ADsafe <p> <div> Widget <b> “Widgets cannot obtain direct references to DOM nodes.” 14
JSLint ensures: no DOM node references bunch = { ADsafe ensures: __nodes__ : array of nodes , only “safe” append: function ..., methods on getText: function ..., bunches ... 20 functions } <div> No private fields in JavaScript! bunch.__nodes__ Untrusted ADsafe <p> <div> Widget <b> “Widgets cannot obtain direct references to DOM nodes.” 14
JSLint ensures: no DOM node references bunch = { ADsafe ensures: __nodes__ : array of nodes , only “safe” append: function ..., methods on getText: function ..., bunches ... 20 functions } <div> JSLint ensures: __nodes__ is bunch.__nodes__ Untrusted ADsafe <p> <div> Widget “private” <b> “Widgets cannot obtain direct references to DOM nodes.” 14
JSLint ensures: no DOM node references bunch = { ADsafe ensures: __nodes__ : array of nodes , only “safe” append: function ..., methods on getText: function ..., bunches ... 20 functions } <div> JSLint ensures: __nodes__ is bunch.__nodes__ Untrusted ADsafe <p> <div> Widget “private” <b> “Widgets cannot obtain direct bunch.append(...) references to DOM nodes.” Exploit append to return nodes? 14
JSLint ensures: no DOM node references bunch = { ADsafe ensures: __nodes__ : array of nodes , only “safe” append: function ..., methods on getText: function ..., bunches ... 20 functions } <div> JSLint ensures: __nodes__ is bunch.__nodes__ Untrusted ADsafe <p> <div> Widget “private” <b> ADsafe ensures: DOM nodes are “Widgets cannot obtain direct bunch.append(...) references to DOM nodes.” not returned 14
eval Goal 2: Verify ADsafe Goal 1: model JSLint ADSAFE.get ADSAFE.get(obj, x) untrusted, but passes JSLint 15
var n = 6 var s = "a string" var b = true 16
var n = 6 var s = "a string" var b = true Widget := Number + String + Boolean + Undefined + Null + 16
Widget := Number + String + Boolean + Undefined + Null + 17
{ x: 6, b: "car" } Widget := Number + String + Boolean + Undefined + Null + 17
{ x: 6, b: "car" } { nested: { y: 10, b: false } } Widget := Number + String + Boolean + Undefined + Null + ★ : Widget __nodes__: Array<Node> caller: � prototype: � ... code : Widget ⨉ ... → Widget __proto__: Object + Function + Array + ... 17
{ x: 6, b: "car" } { nested: { y: 10, b: false } } { __nodes__: 90 } myObj.prototype = { }; Widget := Number + String + Boolean + Undefined + Null + ★ : Widget __nodes__: Array<Node> caller: � prototype: � ... code : Widget ⨉ ... → Widget __proto__: Object + Function + Array + ... 17
{ x: 6, b: "car" } { nested: { y: 10, b: false } } { __nodes__: 90 } myObj.prototype = { }; function foo(x) { return x + 1; } foo(900) foo.w = "functions are objects" ["array", "of", "strings"] /regular[ \t]*expressions/ Widget := Number + String + Boolean + Undefined + Null + ★ : Widget __nodes__: Array<Node> caller: � prototype: � ... code : Widget ⨉ ... → Widget __proto__: Object + Function + Array + ... 17
JSLint Widget type-checker typable widgets widgets that pass JSLint 18
JSLint Widget type-checker typable widgets widgets that Claim: pass JSLint evidence: 1,100 LOC of tests or, passing JSLint ⇒ Widget-typable 18
JSLint Widget type-checker type-based typable arguments about widgets widgets widgets that Claim: pass JSLint evidence: 1,100 LOC of tests or, passing JSLint ⇒ Widget-typable 18
eval Goal 2: Verify ADsafe Goal 1: model JSLint ADSAFE.get ADSAFE.get(obj, x) untrusted, but passes JSLint 19
window.setTimeout(callback, delay); String eval window.setTimeout Widget → Widget 20
Object W i d g e t → W i d g e t g n i r t S Number /*: Widget ⨉ Widget → Widget */ ADSAFE.later = function(callback, delay) { if (typeof callback !== "function") { throw "expected function"; W i d g e t → W i } d g e t window.setTimeout(callback, delay); } String eval window.setTimeout Widget → Widget 20
Recommend
More recommend