ADsafety Type-based Verification of JavaScript Sandboxing Joe - - PowerPoint PPT Presentation

adsafety
SMART_READER_LITE
LIVE PREVIEW

ADsafety Type-based Verification of JavaScript Sandboxing Joe - - PowerPoint PPT Presentation

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


slide-1
SLIDE 1

ADsafety

Type-based Verification of JavaScript Sandboxing

Joe Gibbs Politz Spiridon Aristides Eliopoulos Arjun Guha Shriram Krishnamurthi

1

slide-2
SLIDE 2

2

slide-3
SLIDE 3

3

slide-4
SLIDE 4

4

third-party ad third-party ad

slide-5
SLIDE 5

5

Who is running code in your browser?

slide-6
SLIDE 6

5

Who is running code in your browser?

slide-7
SLIDE 7

5

Who is running code in your browser?

slide-8
SLIDE 8

the host you visit

6

slide-9
SLIDE 9

the host you visit

6

slide-10
SLIDE 10

the host you visit the ad server

6

slide-11
SLIDE 11

the host you visit the ad server

6

same JavaScript context

slide-12
SLIDE 12

the host you visit the ad server

6

<iframe>

slide-13
SLIDE 13

the host you visit the ad server

6

<iframe>

top.location.href

slide-14
SLIDE 14

Facebook JavaScript (FBJS) Google Caja Yahoo! ADsafe

All are defining safe sub-languages

7

Microsoft Web Sandbox

slide-15
SLIDE 15

8

slide-16
SLIDE 16

eval

8

slide-17
SLIDE 17

eval

8

slide-18
SLIDE 18

eval e

8

slide-19
SLIDE 19

eval e wrap(e)

8

slide-20
SLIDE 20

wrap eval e wrap(e)

8

slide-21
SLIDE 21

wrap eval e wrap(e)

“ fi l t e r s ” “wrappers” — Maffeis, Mitchell, and Taly, ESORICS 2009 “ r e w r i t e r s ”

8

slide-22
SLIDE 22

9

slide-23
SLIDE 23

eval

9

slide-24
SLIDE 24

eval

ADSAFE.get(obj, x)

9

untrusted widget

slide-25
SLIDE 25

ADSAFE.get

eval

ADSAFE.get(obj, x)

9

untrusted widget

slide-26
SLIDE 26
  • 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

slide-27
SLIDE 27
  • 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

?

slide-28
SLIDE 28

Type-based Verification of

11

slide-29
SLIDE 29

Definition 1 (ADsafety): If all embedded widgets pass JSLint, then:

12

slide-30
SLIDE 30

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

slide-31
SLIDE 31

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

slide-32
SLIDE 32

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;

<div> <p> <div> <b>

ADsafe Untrusted Widget

12

slide-33
SLIDE 33

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;

<div> <p> <div> <b>

ADsafe Untrusted Widget

12

slide-34
SLIDE 34

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

<div id="WIDGET"> <p> <div> <b>

ADsafe Untrusted Widget

<div>

12

slide-35
SLIDE 35

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

<div id="WIDGET"> <p> <div> <b>

ADsafe Untrusted Widget

<div>

12

slide-36
SLIDE 36

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.

ADsafe Widget A Widget B

12

slide-37
SLIDE 37

13

ADSAFE.get

eval

ADSAFE.get(obj, x)

Goal: Verify ADsafe

slide-38
SLIDE 38

13

ADSAFE.get

eval

ADSAFE.get(obj, x)

Goal: Verify ADsafe untrusted, but passes JSLint

slide-39
SLIDE 39

13

ADSAFE.get

eval

ADSAFE.get(obj, x)

Goal: Verify ADsafe untrusted, but passes JSLint Goal: model JSLint

slide-40
SLIDE 40

14

JSLint ensures: no DOM references

node “Widgets cannot obtain direct references to DOM nodes.”

<div> <p> <div> <b>

ADsafe Untrusted Widget

slide-41
SLIDE 41

14

bunch = { __nodes__ : array of nodes, append: function ..., getText: function ..., ... 20 functions }

ADsafe ensures:

  • nly “safe”

methods on bunches JSLint ensures: no DOM references

node “Widgets cannot obtain direct references to DOM nodes.”

<div> <p> <div> <b>

ADsafe Untrusted Widget

slide-42
SLIDE 42

14

bunch = { __nodes__ : array of nodes, append: function ..., getText: function ..., ... 20 functions }

ADsafe ensures:

  • nly “safe”

methods on bunches

bunch.__nodes__ No private fields in JavaScript!

JSLint ensures: no DOM references

node “Widgets cannot obtain direct references to DOM nodes.”

<div> <p> <div> <b>

ADsafe Untrusted Widget

slide-43
SLIDE 43

14

bunch = { __nodes__ : array of nodes, append: function ..., getText: function ..., ... 20 functions }

ADsafe ensures:

  • nly “safe”

methods on bunches JSLint ensures:

__nodes__ is

“private”

bunch.__nodes__

JSLint ensures: no DOM references

node “Widgets cannot obtain direct references to DOM nodes.”

<div> <p> <div> <b>

ADsafe Untrusted Widget

slide-44
SLIDE 44

14

bunch = { __nodes__ : array of nodes, append: function ..., getText: function ..., ... 20 functions }

ADsafe ensures:

  • nly “safe”

methods on bunches JSLint ensures:

__nodes__ is

“private”

bunch.append(...) bunch.__nodes__

JSLint ensures: no DOM references

node “Widgets cannot obtain direct references to DOM nodes.”

<div> <p> <div> <b>

ADsafe Untrusted Widget

Exploit append to return nodes?

slide-45
SLIDE 45

14

bunch = { __nodes__ : array of nodes, append: function ..., getText: function ..., ... 20 functions }

ADsafe ensures:

  • nly “safe”

methods on bunches JSLint ensures:

__nodes__ is

“private”

bunch.append(...)

ADsafe ensures: DOM nodes are not returned

bunch.__nodes__

JSLint ensures: no DOM references

node “Widgets cannot obtain direct references to DOM nodes.”

<div> <p> <div> <b>

ADsafe Untrusted Widget

slide-46
SLIDE 46

15

ADSAFE.get

eval

ADSAFE.get(obj, x)

Goal 2: Verify ADsafe untrusted, but passes JSLint Goal 1: model JSLint

slide-47
SLIDE 47

var n = 6 var s = "a string" var b = true

16

slide-48
SLIDE 48

var n = 6 var s = "a string" var b = true

16

Widget := Number + String + Boolean + Undefined + Null +

slide-49
SLIDE 49

17

Widget := Number + String + Boolean + Undefined + Null +

slide-50
SLIDE 50

{ x: 6, b: "car" }

17

Widget := Number + String + Boolean + Undefined + Null +

slide-51
SLIDE 51

★: Widget __nodes__: Array<Node> caller: prototype: ... code : Widget ⨉ ... → Widget __proto__: Object + Function + Array + ...

{ x: 6, b: "car" } { nested: { y: 10, b: false } }

17

Widget := Number + String + Boolean + Undefined + Null +

slide-52
SLIDE 52

★: Widget __nodes__: Array<Node> caller: prototype: ... code : Widget ⨉ ... → Widget __proto__: Object + Function + Array + ...

{ x: 6, b: "car" } { nested: { y: 10, b: false } } { __nodes__: 90 } myObj.prototype = { };

17

Widget := Number + String + Boolean + Undefined + Null +

slide-53
SLIDE 53

★: Widget __nodes__: Array<Node> caller: prototype: ... code : Widget ⨉ ... → Widget __proto__: Object + Function + Array + ...

{ 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/

17

Widget := Number + String + Boolean + Undefined + Null +

slide-54
SLIDE 54

JSLint Widget type-checker

typable widgets widgets that pass JSLint

18

slide-55
SLIDE 55

JSLint Widget type-checker

typable widgets widgets that pass JSLint

  • r, passing JSLint ⇒Widget-typable

Claim:

evidence: 1,100 LOC of tests

18

slide-56
SLIDE 56

JSLint Widget type-checker

typable widgets widgets that pass JSLint

  • r, passing JSLint ⇒Widget-typable

type-based arguments about widgets

Claim:

evidence: 1,100 LOC of tests

18

slide-57
SLIDE 57

19

ADSAFE.get

eval

ADSAFE.get(obj, x)

untrusted, but passes JSLint Goal 1: model JSLint Goal 2: Verify ADsafe

slide-58
SLIDE 58

20

window.setTimeout(callback, delay);

eval

window.setTimeout Widget→Widget String

slide-59
SLIDE 59

20

window.setTimeout(callback, delay);

eval

window.setTimeout Widget→Widget String

S t r i n g W i d g e t → W i d g e t W i d g e t → W i d g e t Object Number

/*: Widget ⨉ Widget → Widget */ ADSAFE.later = function(callback, delay) { if (typeof callback !== "function") { throw "expected function"; } }

slide-60
SLIDE 60

20

window.setTimeout(callback, delay);

window : { eval: ☠, setTimeout : (Widget ⨉ ... → Widget) ⨉ Widget → Undefined, ... }

eval

window.setTimeout Widget→Widget String

S t r i n g W i d g e t → W i d g e t W i d g e t → W i d g e t Object Number

/*: Widget ⨉ Widget → Widget */ ADSAFE.later = function(callback, delay) { if (typeof callback !== "function") { throw "expected function"; } }

slide-61
SLIDE 61

20

window.setTimeout(callback, delay);

window : { eval: ☠, setTimeout : (Widget ⨉ ... → Widget) ⨉ Widget → Undefined, ... }

eval

window.setTimeout Widget→Widget String

S t r i n g W i d g e t → W i d g e t W i d g e t → W i d g e t Object Number

/*: Widget ⨉ Widget → Widget */ ADSAFE.later = function(callback, delay) { if (typeof callback !== "function") { throw "expected function"; } }

Widget

slide-62
SLIDE 62

20

window.setTimeout(callback, delay);

window : { eval: ☠, setTimeout : (Widget ⨉ ... → Widget) ⨉ Widget → Undefined, ... }

Widget ⨉ ... → Widget

eval

window.setTimeout Widget→Widget String

S t r i n g W i d g e t → W i d g e t W i d g e t → W i d g e t Object Number

/*: Widget ⨉ Widget → Widget */ ADSAFE.later = function(callback, delay) { if (typeof callback !== "function") { throw "expected function"; } }

Widget

slide-63
SLIDE 63

20

window.setTimeout(callback, delay);

window : { eval: ☠, setTimeout : (Widget ⨉ ... → Widget) ⨉ Widget → Undefined, ... }

Widget ⨉ ... → Widget

—Politz et al. USENIX Security 2011 and Guha, Saftoiu, Krishnamurthi. ESOP 2011.

eval

window.setTimeout Widget→Widget String

S t r i n g W i d g e t → W i d g e t W i d g e t → W i d g e t Object Number

/*: Widget ⨉ Widget → Widget */ ADSAFE.later = function(callback, delay) { if (typeof callback !== "function") { throw "expected function"; } }

Widget

This is just one kind of if-split we handle.

slide-64
SLIDE 64

JSLinted widget adsafe.js

21

slide-65
SLIDE 65

JSLinted widget adsafe.js

21

slide-66
SLIDE 66

JSLinted widget adsafe.js

21

slide-67
SLIDE 67

JSLinted widget

Widget W i d g e t Widget W i d g e t

adsafe.js

21

slide-68
SLIDE 68

JSLinted widget

Widget W i d g e t Widget W i d g e t

adsafe.js

21

slide-69
SLIDE 69

JSLinted widget

Widget W i d g e t Widget W i d g e t

adsafe.js

Widget Widget Widget Widget

21

slide-70
SLIDE 70

JSLinted widget

Widget W i d g e t Widget W i d g e t

adsafe.js

Widget Widget Widget Widget Array<Node> Node

21

slide-71
SLIDE 71

JSLinted widget

Widget W i d g e t Widget W i d g e t

adsafe.js

Widget Widget Widget Widget Array<Node> Node N

  • d

e Node

21

slide-72
SLIDE 72

22

typable widgets widgets that pass JSLint

JSLinted widget

Widget Widget W i d g e t Widget

adsafe.js

Widget Widget Widget W i d g e t Array<Node> N

  • d

e

JSLint model Type-checked ADsafe

+ = ⋯

slide-73
SLIDE 73

23

typable widgets widgets that pass JSLint

var fakeNode = { tagName: "div", appendChild: function(elt) { var win = elt.ownerDocument.defaultView; win.eval("alert('hacked')"); } };

slide-74
SLIDE 74

23

typable widgets widgets that pass JSLint

var fakeNode = { tagName: "div", appendChild: function(elt) { var win = elt.ownerDocument.defaultView; win.eval("alert('hacked')"); } }; var fakeBunch = { __nodes__: [fakeNode] }; Rejected by JSLint

slide-75
SLIDE 75

23

typable widgets widgets that pass JSLint

var fakeNode = { tagName: "div", appendChild: function(elt) { var win = elt.ownerDocument.defaultView; win.eval("alert('hacked')"); } }; var fakeBunch = { __nodes__: [fakeNode] }; Rejected by JSLint var fakeBunch = { '__nodes__': [fakeNode] }; Accepted by JSLint

type error: expected Array<HTML>, received Array<Widget>

slide-76
SLIDE 76

/*: Widget ⨉ Widget → Widget */ WrappedElt.prototype.style = function(name, val) { var regexp = new Regexp("url"); if (regexp.test(val)) { return error(); } ... this.__node__.style[name] = val ... }

24

slide-77
SLIDE 77

/*: Widget ⨉ Widget → Widget */ WrappedElt.prototype.style = function(name, val) { var regexp = new Regexp("url"); if (regexp.test(val)) { return error(); } ... this.__node__.style[name] = val ... } expected String, received Widget

24

slide-78
SLIDE 78

/*: Widget ⨉ Widget → Widget */ WrappedElt.prototype.style = function(name, val) { var regexp = new Regexp("url"); if (regexp.test(val)) { return error(); } ... this.__node__.style[name] = val ... } expected String, received Widget var firstCall = true; var badName = { toString: function() { if (firstCall) { firstCall = false; return "font"; } else { return "url('/evil.xml')"; } } };

passes safety check returns bad value

24

slide-79
SLIDE 79

/*: Widget ⨉ Widget → Widget */ WrappedElt.prototype.style = function(name, val) { var regexp = new Regexp("url"); if (regexp.test(val)) { return error(); } ... this.__node__.style[name] = val ... } expected String, received Widget var firstCall = true; var badName = { toString: function() { if (firstCall) { firstCall = false; return "font"; } else { return "url('/evil.xml')"; } } };

passes safety check returns bad value

Fix: check_string assertion inserted here, and in 16

  • ther places

24

slide-80
SLIDE 80

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; 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.

<div> <p> <div> <b>

ADsafe Untrusted Widget

<div id="WIDGET"> <p> <div> <b>

ADsafe Untrusted Widget

<div>

ADsafe Widget A Widget B

25

slide-81
SLIDE 81

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; 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.

<div> <p> <div> <b>

ADsafe Untrusted Widget

<div id="WIDGET"> <p> <div> <b>

ADsafe Untrusted Widget

<div>

ADsafe Widget A Widget B

25

slide-82
SLIDE 82

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; 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.

<div> <p> <div> <b>

ADsafe Untrusted Widget

<div id="WIDGET"> <p> <div> <b>

ADsafe Untrusted Widget

<div>

ADsafe Widget A Widget B

25

slide-83
SLIDE 83

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; 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.

<div> <p> <div> <b>

ADsafe Untrusted Widget

<div id="WIDGET"> <p> <div> <b>

ADsafe Untrusted Widget

<div>

ADsafe Widget A Widget B

25

slide-84
SLIDE 84

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; 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.

<div> <p> <div> <b>

ADsafe Untrusted Widget

<div id="WIDGET"> <p> <div> <b>

ADsafe Untrusted Widget

<div>

ADsafe Widget A Widget B

Retracted

25

slide-85
SLIDE 85

Caveats:

  • 11 LOC unverified
  • subtree property unverified

26

!

slide-86
SLIDE 86

JavaScript program

Proofs for JavaScript?

27

slide-87
SLIDE 87

JavaScript program λJS program

desugar

Proofs for JavaScript? Proofs for λJS.

27

slide-88
SLIDE 88

JavaScript program λJS program “their answer” “our answer”

desugar

SpiderMonkey, V8, Rhino 100 LOC interpreter

identical for Mozilla JS test suite*

Proofs for JavaScript? Proofs for λJS.

— Guha, Saftoiu, Krishnamurthi. ECOOP 2010.

27

slide-89
SLIDE 89

banned = { 'arguments' : true, callee : true, caller : true, constructor : true, 'eval' : true, prototype : true, stack : true, unwatch : true, valueOf : true, watch : true }

function reject_global(that) { if (that.window) { error(); } }

+

if (/url/i.test(string_check(value[i]))) { error('ADsafe error.'); }

+

and other patterns...

28

slide-90
SLIDE 90

banned = { 'arguments' : true, callee : true, caller : true, constructor : true, 'eval' : true, prototype : true, stack : true, unwatch : true, valueOf : true, watch : true }

function reject_global(that) { if (that.window) { error(); } }

+

if (/url/i.test(string_check(value[i]))) { error('ADsafe error.'); }

+

and other patterns...

28

... can be succinctly expressed with types

Widget := Number + String + Boolean + Undefined + Null + ★: Widget __nodes__: Array<Node> caller: prototype: ... code : Widget ⨉ ... → Widget __proto__: Object + Function + Array + ...

slide-91
SLIDE 91

★: Widget __proto__: Object + Function + Array + ... code : Widget ⨉ ... → Widget arguments: caller: ... Widget := Number + String + Boolean + Undefined + Null +

JavaScript program λJS program “their answer” “our answer”

SpiderMonkey, V8, Rhino 100 LOC interpreter

desugar identical for Mozilla JS test suite*

wrap wrap(e) e eval

u n t y p a b l e typable typable

1.Model sandbox as a type system 2.Object types for JavaScript (★ and ☠) 3.Proofs over tractable JavaScript semantics

Conclusion

29

slide-92
SLIDE 92

Extra Slides

30 Spiridon Aristides Eliopoulos

slide-93
SLIDE 93

Unverified Code

31 function F() {}; ADSAFE.create = typeof Object.create === 'function' ? Object.create : function (o) { F.prototype = typeof o === 'object' && o ? o : Object.prototype; return new F(); }; /*: (banned → True) & (not_banned → False) */ function reject_name(name) { return banned[name] || ((typeof name !== 'number' || name < 0) && (typeof name !== 'string' || name.charAt(0) === '_' || name.slice(-1) === '_' || name.charAt(0) === '-')); }

slide-94
SLIDE 94

Theorems

32

slide-95
SLIDE 95

Full Widget Type

33