630 likes | 783 Views
Dynamic Information Flow Analysis for JavaScript in a Web Browser. Tom Austin Software and Languages Research Group University of California at Santa Cruz. How Can We Make JavaScript Secure?. Bank.com. XSS attack. Analytics.com. EvilAdServer.com. f(accountNum);. reportUsage();.
E N D
Dynamic Information Flow Analysisfor JavaScript in a Web Browser Tom Austin Software and Languages Research Group University of California at Santa Cruz
How Can We Make JavaScript Secure? Bank.com XSS attack Analytics.com EvilAdServer.com f(accountNum); reportUsage(); AnotherAdServer.com getAd(url).display(); function fillForm()={…} ? var accountNum = …; AdServer.com passwords validate(accountNum); financial information Widgets.com
Cross-Site Scripting (XSS):malicious injection of client-side code into web pages
Stealing Browser History • Example attack: steal browsing history. • Browser history is protected, BUT it can be derived from the color of links. return [ decode(ebayLink.currentStyle.color==visited), decode(msnLink.currentStyle.color==visited), decode(aolLink.currentStyle.color==visited), decode(cnnLink.currentStyle.color==visited), decode(boaLink.currentStyle.color==visited), ];
Current JavaScript Security • Same-origin policy: Limits a script’s access to different frames and windows • Browser-specific features • Signed scripts [Mozilla] • Secure zones [Internet Explorer] • JavaScript subsets • Facebook JavaScript (FBJS) • Google’s Caja
Information Flow Security in a Browser Bank.com XSS attack Analytics.com EvilAdServer.com H L L L AnotherAdServer.com L L L AdServer.com H L Widgets.com
Information Flow Analysis Overview • Track sensitive data as it flows through system. • Addresses dual problems of confidentiality (keeping data secret) and integrity (keeping tainted data from corrupting good data). • Focuses on the control flow of the program -- timing channels, back channels, etc. are out of scope.
Explicit Flows • Information flows directly by assignment. • Related to taint analysis in Perl, Ruby, and PHP. • Below example attempts to leak secret to the public variable x. function decode(secret) { var x = secret; //BAD return x; }
Implicit Flows function decode(x){ var y = false; if (x) y = true; return y; } • Data leaks through the control flow of the code. • The boolean value of x is returned in the field y, without direct assignment.
Correctness Property:Termination-insensitive noninterference • Noninterference: Public outputs (L) do not depend on private inputs (H) • Termination-insensitive: Program may leak one bit through termination • Intermediary output channels may leak more through termination behavior, but the attacker is limited to a brute force attack (Askarov et al. 2008)
Dynamic Analysis Static Analysis • Validation of code done on client • Validation usually done before run time • More information about current execution • Able to reason about complete program • Able to handle dynamic code evaluation • Easier to handle implicit flows?
Challenge: Implicit Flows Standard Solution: The No-Sensitive-Upgrade Check
Static Approaches to Implicit Flows function decode(x){ var y = true; var z = true; if (x) y = false; if (y) z = false; return z; } • Analysis ensures that private data does not affect public data. • In this example, y's final value depends on x. • [Denning 1976] NOT CERTIFIED
Implicit Flow Example function decode(x){ var y = true; var z = true; if (x) y = false; if (y) z = false; return z; } x=falseH x=trueH How can we safely handle this assignment? falseL
Simple-Upgrade (SU) Strategyfor Implicit Flows • Make a public variable private whenever it is modified in a private block of code. • Intuitive, but fails to defend against implicit flows.
Implicit Flow Example:Simple-Upgrade Strategy function decode(x){ var y = true; var z = true; if (x) y = false; if (y) z = false; return z; } x=falseH x=trueH Partially leaked falseL trueL
No-Sensitive-Upgrade (NSU) Strategy for Implicit Flows • Forbid assignment to public variables in private code. [Zdancewic 2002] • Defends against implicit flows. • Rejects some valid program executions.
Implicit Flow Example:NSU Strategy function decode(x){ var y = true; var z = true; if (x) y = false; if (y) z = false; return z; } x=falseH x=trueH STUCK falseL
The Importance of Termination return [ decode(ebayLink .currentStyle .color==visited), decode(msnLink .currentStyle .color==visited), decode(aolLink .currentStyle .color==visited), ]; • Simple-upgrade strategy: all variables are decoded and returned to the attacker. • No-sensitive-upgrade strategy: the attacker only knows whether all variables are false.
Challenge: Ease of Use Our Solution: Permissive-Upgrades
No-Sensitive-UpgradeFalse Alarms var name = emp.name; if(emp.isDoctor()){ name = "Dr. " + name; debug("Bonus for "+name;) emp.salary += phdBonus; } return emp;
Permissive-Upgrade Strategy Tolerates Partially Leaked Data • The no-sensitive-upgrade approach gets stuck when data is partially leaked. • Partially leaked data (labeled P) is: • Private on this execution • Possibly public on an alternate execution
Updated Security Lattice • The permissive-upgrade strategy permits partially leaked data (P) and adds it to the security lattice. • Partially leaked data must be treated more carefully than private data (H). • Critically, joining H-data with P-data results in P-data: P H "a"H + "b"P = "ab"P L
The Permissive-Upgrade Approach var name = emp.name; if(emp.isDoctor()){ name = "Dr. " + name; debug("Bonus for "+name;) emp.salary += phdBonus; } return emp;
Implicit Flow Example:Permissive-Upgrade Strategy function decode(x){ var y = true; var z = true; if (x) y = false; if (y) z = false; return z; } x=falseH x=trueH STUCK falseL
Privatize Partially Leaked Data • The permissive upgrade semantics still results in some stuck executions. • The programmer can add privatization operations (<H>) of values at critical points. • Since the value is made private on both branches, private data remains secure. <H>3P <H>3H 3H <H>3L
Implicit Flow Examplewith Privatization Operation function decode(x){ var y=true; var z=true; if (x) y=false; if ( y) z=false; return z; } x=falseH x=trueH falseP trueL
Privatization Inference • When an execution would get stuck, we infer the needed privatization operation for future reference. • The needed operations can be discovered with minimal developer effort.
Implicit Flow Example:Privatization Inference function decode(x){ var y=true; var z=true; if (x) y=false; if ( y) z=false; return z; } x=falseH x=trueH STUCK falseL
Implicit Flow Example:Privatization Inference function decode(x){ var y=true; var z=true; if (x) y=false; if (<H>y) z=false; return z; } x=falseH x=trueH falseP trueL
Permissive-Upgrade Summary • Accepts more valid program executions than the no-sensitive-upgrade approach. • Privatization operations help prevent stuck executions. • Privatization inference can determine privatization operations automatically.
Challenge: Ease of Use Alternate Proposed Solution: Faceted-Value Evaluation
Faceted-Value Evaluation • Instead of tagging security labels to values, store a high value and a low value. • When a variable is updated in a private context, only its high value is updated. • Authorized channels receive the correct values; untrusted channels receive stale/dummy values. v={"L. McCoy","Dr. L. McCoy"}: • output(v, L) "L. McCoy) • output(v, H) "Dr. L. McCoy) • Related to Secure Multi-execution [Devriese & Piessens 2010]
Implicit Flow Example:Faceted-Value Evaluation false function decode(x){ vary=true; varz=true; if (x) y=false; if (y) z=false; return z; } {false,false} {false,true} false {false,true}
Challenge: Performance Our Solution: Sparse Labeling
Does Performance Matter for JavaScript? • Applications have grown in size (Ajax, Gmail, etc.) • Browser designers spend a great of attention on the speed of their JavaScript implementations. JavaScript implementations have grown tremendously faster, but…
SunSpider (Apple’s benchmark) • Shorter is better • http://www2.webkit.org/perf/sunspider-0.9/sunspider.html
Mozilla’s benchmark • http://dromaeo.com • Green is best Safari Firefox Opera IE8
V8 benchmark • http://v8.googlecode.com • Longer is better • Results reported by CNET
Independent test • http://celtickane.com/labs/web-browser-javascript-benchmark/
a = b + c a b join + c
Label Locality: DOM Tree Example <body>: {Top} <div>: {Top} <p>: {Top} <div>: {Bank.com} <h1>: {Top} <a>: {Top} <div>: {Widget.com} <span>: {Bank.com} <table>: {Bank.com} <form>: {Widget.com} <button>: {Widget.com} <strong>: {Bank.com} <td>: {Bank.com} <td>: {Bank.com}
Implicit Labels • By exploiting label locality we can leave labels implicit. • We can omit the label on a value whenever it is subsumed by the program counter (pc). Universal labeling Sparse labeling Labeled data Unlabeled data
Removing Unnecessary Labels <body>: {Top} <div>: {Top} <p>: {Top} <div>: <h1>: {Top} <a>: {Top} <div>: {Bank.com} {Widget.com} <span>: <table>: <form>: <button>: {Bank.com} {Bank.com} {Widget.com} {Widget.com} <strong> <td>: <td>: {Bank.com} {Bank.com} {Bank.com}
Two Cases {Widget.com} First( ) => {Widget.com} 1 1 2 First( ) => 1 1 2
Slow-path vs. Fast-patha = b + c a b a b join + + c c
Semantics of Unary “-” if (JSVAL_IS_INT(rval)&&(i=JSVAL_TO_INT(rval))!=0) { //FAST PATH i = -i; regs.sp[-1] = INT_TO_JSVAL(i); } else { if (JSVAL_IS_DOUBLE(rval)) { //LESS-FAST PATH d = *JSVAL_TO_DOUBLE(rval); } else { //SLOW PATH ... //Implicit conversions //IDEAL SPOT FOR HANDLING LABELED DATA ... //Error handling } d = -d; ... }
Challenge: Information Flow Policy Here there be dragons…
Open Policy Questions • What should the security lattice be? • What data should be confidential? • What channels can an attacker use to leak data? • How can we test these policies?