Frontend Security: Applying Contextual Escaping Automatically, or How to Stop XSS in Seconds
-
Upload
adonatwork -
Category
Software
-
view
871 -
download
0
Transcript of Frontend Security: Applying Contextual Escaping Automatically, or How to Stop XSS in Seconds
Frontend Security: Applying Contextual Escaping Automatically, orHow to Stop XSS in Seconds
PRESENTED BY Nera Liu and Adonis Fung⎪ May 21, 2015
Problem Statement
What makes XSS prevention so hard?
Background > Related Work > Our Approach > Evaluations > Conclusion
XSS Quick Explanation
Given no proper output filtering:<h1>Hello <?php echo $_GET['name']; ?></h1>
An attack vector can come through the query string at victim.com/?name=XXX, where XXX is:
"'><script>alert(1)</script>
HTML of victim.com ends up being:<h1>Hello "'><script>alert(1)</script></h1>
Cross-Site Scripting (XSS)
Root Cause- Untrusted inputs executed as scripts under a victim’s origin/domain
Consequences- Cookie stealing, privacy leaking- Fully control the web content- Bug bounty costs
Cross-Site Scripting (XSS)
■ Ranked No. 3 / OWASP Top 10 WebApp Security Risks
Screen-captured from https://www.owasp.org/index.php/Top_10_2013-A3-Cross-Site_Scripting_(XSS)
XSS Defenses
Defense-in-depth:- Prevent, Detect, Contain, etc...
Generally, apply output filtering to prevent XSS- Blindly-escape sensitive chars (e.g., & < > " ' `)
- PHP: htmlentities(untrusted_data)
- JavaScript: untrustedData.replace(/[&<>"'`]/, ...)
- Templating: {{untrustedData}} is blindly-escaped by default
Blindly-escaping is still vulnerable!
Blindly-escaping (&<>"'`) would not stop XSS, when- {{url}} is an untrusted user input (assumed thereafter)- {{url}} is javascript:alert(1), or- {{url}} is # onclick=alert(1)
→ We need Contextual Escaping!- While blindlyEscape( data ) works, but not for url- blacklistProtocol( escapeUnquoted ( encodeURI( url ) ) )
A template is typically written like so:<a href={{url}}>{{data}}</a>
XSS Output Filtering
Contextual-escaping Filters (Secure)
Blindly-escaping Filters (Vulnerable)
Manual(error-prone and
doesn’t scale)
Automatic(defaulted by
template engines) ✔✘
✘
✔
Related Work
Limited solutions/attempts available- Use Closure/AngularJS w/Strict Contextual Escaping- Use XML Templates with Java/JSP- Without Contextual Escaping: React, Dust, etc...
Deployability/Adoption Issues- Framework specific- Browser compatibility issues- Not for existing projects, unless requiring many code changes
Highlights- Efficient HTML 5 compliant parser w/auto corrections- Auto apply contextual, just-sufficient, and faster escaping- Effortless adoption requiring as little as 2 LoC changes
https://yahoo.github.io/secure-handlebars
Our Approach: Secure Handlebars
Automatic contextual escaping made easy
Handlebars
Context Parser
Handlebars PreProcessor
High-level Architecture
Template Parser
Template AST
HTML5 Parser (w/auto corrections)
JS Parser
AST Walker
Template w/filter markups
abstracting branching logics and output expressions
CSS Parser
Pre-compiler
Contextual XSS Filters(registered as helpers/callbacks)
HTML
Data(possibly untrusted)
Runtime Compiler
Template Spec.
Our solution comprises of only the blue boxes
Handlebars
Context Parser
Handlebars PreProcessor
High-level Architecture
Template Parser
Template AST
HTML5 Parser (w/auto corrections)
JS Parser
AST Walker
Template w/filter markups
abstracting branching logics and output expressions
CSS Parser
Pre-compiler
Contextual XSS Filters(registered as helpers/callbacks)
HTML
Data(possibly untrusted)
Runtime Compiler
Template Spec.
Our solution comprises of only the blue boxes
Pre-Processor: Good Template Samples[Before]
<a href="{{url}}">{{url}}</a>
[After]
<a href="{{{yubl (yavd (yufull url))}}}">{{{yd url}}}</a>
Add contextual escaping filters {{{ }}} - disable the default blindly-escaping yufull - encodeURI() with IPv6 support yavd - html-escape double-quote character (" → ") yubl - disable dangerous protocols such as javascript: yd - html-escape less-than character (< → <)
Pre-Processor: Bad Template Samples[Before]
<input type="button" onclick="doSth({{data}})">
Warning!
Ensure placeholders are never put in scriptable contexts- Security anti-pattern to place (possibly) untrusted data in executable contexts- Workaround:
- <input type="button" data-sth="{{data}}" onclick="doSth(this.getAttribute('data-sth'))">
Pre-Processor: Branching Consistency Check[Before]{{#if highlight}}<strong>{{else}}<em {{/if}} {{unknownCxt}} ...
[After] A warning is raised!
{{#if highlight}}<strong>{{else}}<em {{/if}} {{data}} ...
Walk through branches & ensure they end up in identical state/context- Likely a careless mistake or typo- Obviously, context of {{unknownCxt}} is ambiguous
Warning!
Handlebars
Context Parser
Handlebars PreProcessor
High-level Architecture
Template Parser
Template AST
HTML5 Parser (w/auto corrections)
JS Parser
AST Walker
Template w/filter markups
abstracting branching logics and output expressions
CSS Parser
Pre-compiler
Contextual XSS Filters(registered as helpers/callbacks)
HTML
Data(possibly untrusted)
Runtime Compiler
Template Spec.
Our solution comprises of only the blue boxes
Standard Compliant- Can even auto-correct parse errors to enforce
consistent parsing across browsers
Robust, lightweight, and efficient- Simplified state transitions- No unnecessary handling (no DOM)
Design Principles of Context Parser
Figured from Overview of HTML 5 Parsing Model: https://html.spec.whatwg.org/multipage/syntax.html#overview-of-the-parsing-model
Handlebars
Context Parser
Handlebars PreProcessor
High-level Architecture
Template Parser
Template AST
HTML5 Parser (w/auto corrections)
JS Parser
AST Walker
Template w/filter markups
abstracting branching logics and output expressions
CSS Parser
Pre-compiler
Contextual XSS Filters(registered as helpers/callbacks)
HTML
Data(possibly untrusted)
Runtime Compiler
Template Spec.
Our solution comprises of all blue boxes
Design Principles of XSS Filters
Context-aware- More Secure - escape only
those that can break out from its context
Just sufficient encoding- Faster - no need to
escape all & > " ' `- More friendly - no more
double-encoding issues like &lt;
Deployability
Adoption- Switch from express-handlebars to express-secure-handlebars npm
- 2 LOCs changes: (1) dependency in package.json, (2) require(...)- Alternatively, a more decoupled approach:
- pre-process tmpl to get it rewrited during build process at server- only register helpers for data filtering and binding at client-side
Browser Compatibility- IE 7+, Safari 5+, Chrome, Firefox
Evaluations
Deployed in one the largest properties- Negligible offline overhead
- takes <3s to analyze/pre-process 880 templates- Insignifiant runtime overhead (i.e., filter callbacks, size: 1.3KB gz)
- unchained filters: up to 2 times faster than default- chained filters: slower but is already minimal to be secure
- True positives found! - e.g., unquoted, onclick, URI attributes, script tags, etc.
- More secure, efficient, and easier adoption- Open-sourced at github.com/yahoo and npmjs.com- Contact/Collaborate with us for more template support
Conclusion: Building A Safer Internet for All
Automatic contextual escaping made easy
Thank you!
Nera, Albert, Adon{neraliu, albertyu, adon}@yahoo-inc.
comTwitter: @neraliu, @yukinying, @adonatwork