mechanism that protects users at DOM level against common client-side attacks The current features • CSRF prevention • DOM-based XSS attacks prevention • Reverse Clickjacking/SOME prevention • Unwanted applications detection
server per user session Hidden fields with CSRF tokens are appended: • to all static forms of an HTML document • to all dynamically generated forms via MutationObserver No false positives for JSON/XML based REST APIs: • requests are checked only if its Content-Type corresponds to HTML forms that are sent from another domain
AJAX requests • XMLHttpRequest "send" method is overridden via window.XMLHttpRequest.Prototype • For old IE versions corresponding "send" methods are overridden for popular frameworks (jQuery, mootools, ExtJS, etc)
data is inserted in JavaScript function call context without sufficient validation (typically JSONP endpoints) Cannot be detected on server-side Example https://ex.com/InCallback/#q=urc_button.click Pavel Toporkov. Two tales about Google Vulnerabilities Ben Hayak. Same Origin Method Execution
function detectFiddler() { if (!allowInsecureDetectors) { return; } if (window.navigator.platform.substring(0,3) === 'Lin') { return; } var t = new Date().getTime(); var img = new Image(); img.src = 'http://127.0.0.1:8888/FiddlerRoot.cer'; img.onerror = function() { if (new Date().getTime() - t < timeout) { console.log('Fiddler environment detected.'); } }; }
(à la DOMinator) We do not know injection context Many sources, sinks and contexts for malicious JavaScript execution Cannot wait when page is fully loaded We need not only to prevent attacks but also to detect and report them
PhantomJS Precise Client-side Protection against DOM-based Cross-Site Scripting Towards Elimination of XSS Attacks with a Trusted and Capability Controlled DOM (Mario Heiderich)
to look for it – sources that are controlled by an attacker • location • window.name • storages, etc. We should know XSS features – possibility to change AST in one of the following contexts • HTML/DOM • JavaScript • Attribute • URL
Does it contain dangerous HTML? Does it contain something like dangerous JavaScript? Deny Allow location.pathname location.search location.hash window.name localStorage … document.cookie Yes Yes No No
sanitizer for HTML, MathML and SVG" Cure53’s project https://github.com/cure53/DOMPurify Features – Precise (not heuristic) – Library for developers – XSS sanitizer for HTML, MathML and SVG – Hooks mechanism
via jQuery) var dirty = '<a>123<b>456<script>alert(1)<\/script></b></a>789'; var policy = {FORBID_TAGS: ['a', 'b']}; var clean = DOMPurify.sanitize(dirty, policy); clean; //123456789 var dirty = '123<a href="javascript:alert(1)">I am a dolphin too!</a>'; var clean = DOMPurify.sanitize(dirty); clean; // "123<a>I am a dolphin too!</a>" var dirty = '<a x="1">123<b>456</b></a>'; var policy = {FORBID_ATTR: ['x']}; var clean = DOMPurify.sanitize(dirty, policy); clean; //"<a>123<b>456</b></a>"
is changed • " can be added if there are no quotes or it can replace' • closing tag can be added DOMPurify does nothing, if input does not contain "<" DOMPurify.sanitize("<svg width=1 height='2'>"); // "<svg height="2" width="1"></svg>" DOMPurify.sanitize("alert(1);"); // "alert(1);//"
clean = ''; var dirty = normalize(s); var purified = DOMPurify.sanitize(dirty); if (!isMatch(dirty, purified)) { return clean; } return s; } ε, dompurify(x) ≢ x x, dompurify(x) ≡ x sanitize(x) = DOMPurify is a sophisticated sanitizer. How can we use its power on WAF?
height="2" width="1"></svg>") // true sanitize("<svg width=1 height='2'>"); // "<svg width=1 height='2'>" isMatch("<svg onload=alert(1)", "<svg></svg>") // false sanitize("<svg onload=alert(1)"); // "" ε, dompurify(x) ≢ x x, dompurify(x) ≡ x sanitize(x) = DOMPurify is a sophisticated sanitizer. How can we use its power on WAF?
AST does not contain dangerous code Ready-made JavaScript parsers are used This approach is universal and can be used for detection of arbitrary injections It is heuristical
alert(1) contains CallExpression node • AST for ";alert(1);" does not contain CallExpression node Template-based var a = "<>"; A heuristic method based on tokens number ";alert(1);" – 1 token ' ";alert(1);" – 1 token "";alert(1);" – 8 tokens parse(var a = "";alert(1);"") parse("";alert(1);")
security policy and can be specified by ESTree node names We can use additional logic based on parent or child nodes to minimize false positives For simplicity we'll assume that the security policy is restricted by CallExpression node only
can not be built by parser? ""};alert(1);var f={t:" function sanitize(dirty) { var esprima = require('esprima'), estraverse = require('estraverse'), clean = '', tree; tree = esprima.parse(dirty); estraverse.traverse(tree, { enter: function(node) { if (node.type === 'CallExpression') { return clean; } } }); return dirty; } Esprima/estraverse
the right: ""};alert(1);var f={t:" ""};alert(1); The parsed string is changed using information about parse errors from the previous step When we find a dangerous node in AST we immediately stop parsing
modern browsers High performance Standard-compliant (ECMAScript, ESTree) Modular - allows to change parse logic Returns error information Error-tolerant
Output: is S an injection in CTX context? 1. Tokenize S in CTX context. Save all tokens in tokens array 2. Parse S and build AST 3. If this AST contains specified forbidden nodes, then S is an injection 4. Otherwise delete from S the next token 5. If S is not an empty string, go to the step 2
function escape(input) { // You know the rules and so do I input = input.replace(/"/g, ''); return '<body onload="think.out.of.the.box(' + input + ')">'; } return '<body onload="think.out.of.the.box()},{0:prompt(1)">'; "… the solution might work for some older versions of Chrome, while for others, a different vector would be needed…" This type of XSS can be found only if parser is error-tolerant
types • Contexts for sources and parameters • Forbidden ESTree nodes Additional rules in Acorn modules Predefined profiles for customer’s applications Heavy testing