Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

25
Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies* Phu H. Phung Chalmers, Sweden Stanford Security Seminar July 12, 2010 * This talk is based 2 joint papers with David Sands, Andrey Chudnov, Jonas Magazinius appeared on ASIACCS’09 & OWASP AppSec’10

description

Stanford Security Seminar, July 12, 2010, Stanford, CA, USA.

Transcript of Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Page 1: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies*

Phu H. PhungChalmers, Sweden

Stanford Security SeminarJuly 12, 2010

* This talk is based 2 joint papers with David Sands, Andrey Chudnov, Jonas Magazinius appeared on ASIACCS’09 & OWASP AppSec’10

Page 2: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

The concern problems

• Injected (untrusted) JavaScript code (e.g.XSS) – A malicious user (the attacker) injects potentially

dangerous JavaScript code into a webpage via data entry in the webpage, e.g.:• blog• forum• web-mail

• Third party scripts (e.g. advertisement, mashup web applications)

• Buggy code

Page 3: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Difficult issues

• Parser mismatch problem: – filter does not always parse in the same way as

browser• Dynamic scripts problematic, e.g.

document.write, eval, ...<script> document.write(‘<scr’);document.write(‘ipt> malic’);var i= 1;document.write(‘ious code; </sc’);document.write(‘ript>’);</script>

<script> malicious code; </script>

Page 4: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

The landscape of JavaScript security mechanisms

• Server filtering, but parser mismatch problem• Language subset, sandboxing• Behavioral sandboxing– Code transformation– No code transformation• Browser modification• No browser modification

Page 5: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Our approach: Use an Inlined Reference Monitor

• “inline” the policy into the JavaScript code so that the code becomes self-protecting

• The policy enforcement is implemented in a lightweight manner – does not require browser modification– non invasive: the original code (and any dynamically

generated code) is not syntactically modified– its implementation is a small and simple adaptation of an

aspect-oriented programming library

Page 6: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

The policies

• The enforcement mechanism is security reference monitor-based• Ensure safety property of program execution

• Examples:• Only allow URI in a white-list when sending by

XMLHttpRequest• Do not allow send after cookie read• Limit the number of alerts to 2

Page 7: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Enforcement method

• Intercept JavaScript built-in method calls by inlining policy into the call– control or modify the bad behaviour

• Monitor access to sensitive properties

Page 8: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Enforcement method

alert implementation

JavaScript execution environment(e.g. browsers)Native implementations

code pointers User functions

alert(..) window.alert

alert wrapper(+policy code)

Attacker codealert = function(){...};

alert wrapper

unique

Phu H. Phung, David Sands, Andrey Chudnov – cse.chalmers.se

Dagstuhl 09141, 2 April 2009

Page 9: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Implementation

• Use aspect-oriented programming (AOP) style to intercept JavaScript API method calls var wrapper = function(object, method, Policy) {

//...

var original = object[method];

var aspect = function() {

//...

return Policy.apply(...,

proceed : function(){

return original.apply(...)

});

};

object[method] = aspect;

return aspect;

};

Page 10: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Monitoring Property access

• Use the setter and getter object.prototype.__defineGetter__(...),object.prototype.__defineSetter__(...)

• Property: even can redefine setter/getter, original wrapped properties are still protected

Page 11: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Deployment• Structure of a webpage containing policy

enforcement code

• Policies are located in the first script tag– Policy enforcement is applied for the rest of code

Dagstuhl 09141, 2 April 2009

The enforcement code can be deployed in any sides: server side,

proxy or plug-in

Page 12: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Secure the wrapper

• There are several issues that an attacker can exploit the wrapper– Function and Object Subversion• Modifying the Function/ Object –prototype

– Global setter subversion– Recover the wrapped built-in using aliases • Static aliases• Dynamic aliases

Page 13: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Function and Object Subversion

Object• prototype • valueOf( )

Function• constructor• prototype • apply( )

• call( )

{function instance}• constructor

Modifying subverts expected behavior

Wrapper:original.apply(this,args)

Attack code:var org;Function.prototype.apply =

function(){ org = this}

Fixing :original.apply= $virgin_apply

Page 14: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Global Setter subversion

Wrapper code

policy({args: arguments,

proceed: original})

Subversion

var org;Object.prototype.

__defineSetter__(‘proceed’, function(o) { org = o });

Fixing the wrapper:• No temporary objects?• Use “safe” objects…• Change JavaScript: Don’t execute setters upon instantiation (IE, Firefox)

Page 15: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Static aliases

alert

window.alert

Window.prototype.alert

constructor.prototype.alertwindow.__proto__.alert

window.window.alert

Page 16: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

wrapper

Dynamic aliases

alert

alert alert

We provide pre-defined policies which enforce methods that possible return a window object with the same policies as the current window

Page 17: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Sane Policies

• Object and Function Subversion in Policies• Non Declarative Arguments

Page 18: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Function and Object Subversion in Policies

Policy code

var whitelist = {"good.com":true, "good2.org":true}

if(whitelist[address.substr(...))])

Fixing subversion• hasLocalProperty()• Use “safe” objects…

Subversion

Object.prototype[‘evil.com’]=true;*

String.prototype.substr = function(){ return ‘good.com’}

The policy writer should not have to remember this…

Credit: Meyerovich at el, WWW’10

Page 19: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

“Safe” objects• safe() function– Creates a blank object which does not inherit from

the prototype-chain• {__proto__: null}

– Recursively copies all fields from the input object to the newly created copy

Page 20: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Non-declarative vs. declarative policies

Policy code

if (whitelist[address])img.src = address;

Fixing problem

Policy declare which types itexpects in a type language andmonitor enforces it

Attack

x = {toString: function() { this.toString=

function()’bad.com’;return ‘good.com’; }

}

Page 21: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Types for Declarative Argumentsargument array cloning by type:policy.toString(b) === ’xyz’

a b c

? ‘string’

? ‘xyz’

original argument array

inspection typeinspection argument array

Computation by policy code leading to call to invocation.proceed()

? ‘xy’ 42

policy’s modifiedargument array

Recombine with original argument

a ‘xy’ 42

and pass to original built-in

Example policy computation for some built-in called with (a,b,c). In this example the policy inspects b at type string and removes the last character, and sets the third parameter to 42 before calling proceed() in order to access the original built-in function. In the diagram ? is an abbreviation for undefined, and array objects are depicted as boxes.

policy function proceed function

Page 22: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Summary

• Our approach is to control and modify the behaviour of JavaScript by transforming the code to make it self-protecting– no browser modifications– non-invasive

• solve the problem of dynamic scripts• avoiding the need for extensive runtime code transformation

• Possible vulnerabilities of the library are addressed and fixed

• Typing for arguments to prevent

Dagstuhl 09141, 2 April 2009

Page 24: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Further work

• Case studies for particular web applications• Fully develop the framework, including

treating mashups, policies that span multiple pages

• Authoring policies:– Not easy for the programmer to ensure that all

objects are safe • Strong motivation for defining a policy language for

authoring policies which are well behaved.

Page 25: Self-Protecting JavaScript: A Lightweight Approach to Enforcing Security Policies

Thank you!