return of the xss jedi

25
RETURN OF XSS JEDI BY ABE KANG A Review and XSS and Introduction to DOM based XSS

Upload: lily-kang

Post on 01-Dec-2014

80 views

Category:

Documents


7 download

TRANSCRIPT

Page 1: Return of the XSS Jedi

RETURN OF XSS JEDI

BY ABE KANG

A Review and XSS and Introduction to DOM based XSS

Page 2: Return of the XSS Jedi

5 XSS CONTEXTS (HTML PARSER)

HTML

URL

CSS

HTML Attribute

JavaScript (Event Handler Attributes and in

between <script> tags)

Page 3: Return of the XSS Jedi

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.

Page 4: Return of the XSS Jedi

HTML CONTEXT

A HTML context is output which is usually rendered in between HTML markup tags (<TD> tags in this example). Another way of understanding the HTML context is the displayed text (content) in the page.

<TABLE>

<TR><TD>Name:</TD><TD>${actionForm.name}</TD></TR>

<TR><TD>Adress:</TD><TD><%=dbVariable.address%></TD></TR>

<TR><TD>City:</TD><TD><bean:write name=”actionForm” value=”city”/></TD></TR>

<TR><TD>State:</TD><TD><c:out value=”${param.state}</TD></TR>

<TABLE>

HTML Encode to Mitigate

Page 5: Return of the XSS Jedi

URL CONTEXT

The URL Context consists of user output placed in “src”, “href”,

“background”, and other URL based attributes. Most URL

context exploits are related to passing

“javascript:malicious_code()”, “vbscript:malicious_code()” and

“data:text/html;charset=utf-8;base64,PHNjcmlwdD…” in URL

based attributes.

Notes to keep in mind

The colon needs to be URL encoded or all of the above attacks work

The following will still execute:

<a href=“<%=AllCharsHTMLEncodedVar%>”>Test</a>

<a href=“javascript:<%=AllCharsURLEncoded%>”>Test</a>

<a href=“<%=AllCharHTMLEncoded%>:<%=AllCharsURLEncoded%>”>Test</a>

URL Encode to Mitigate

Page 6: Return of the XSS Jedi

CASCADING STYLE SHEET (CSS) CONTEXT

The URL Context consists of user output placed in CSS attributes. Most CSS

XSS exploits are related to the “style” attribute.

//the user can select the color

<div style="background-color:<%=request.getParameter(“color”)%>;">

<div style="background-color: green; background-image: url (javascript:bad_code());">

Use a level of indirection to mitigate.

Page 7: Return of the XSS Jedi

HTML ATTRIBUTE CONTEXT

The 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.

The following are considered HTML contexts: <input type=“<%=var%>” name=“<%=var2%>” value=“<%=var3%>”/>

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.

<input type=text name=name value=<%=var3%>/>

The attacker can pass in “Input onclick=attackCode()” to produce:

<input type=text name=name value=Input onclick=attackCode() />

Use HTML Attribute Encoding to mitigate

Page 8: Return of the XSS Jedi

JAVASCRIPT CONTEXT (EVENT HANDLER)

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

<script> 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 HTML-

unescaped (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.

<div onClick=”someJSFunction(\“<%=ESAPI.encodeForHTMLAttribute(

request.getParameter(“input1”))\”%>”> Some Text </div>

Page 9: Return of the XSS Jedi

JS CONTEXT (EVENT HANDLER MITIGATION)

These steps are for older browsers: 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

quotes Mitigated example (assuming user input will end up in an HTML

component): <div onClick=”someFunction(„<%=ESAPI.encodeForJavaScript( ESAPI.encodeForHTML(request.getParameter(“input1”)))‟%>)”>

Page 10: Return of the XSS Jedi

JS CONTEXT (IN BETWEEN <SCRIPT> TAGS)

AKA DOM BASED XSS

Because 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

Page 11: Return of the XSS Jedi

DOM XSS IN HTML SUB-CONTEXT

This context in JavaScript code highlights functions which output text to the browser as HTML. element.innerHTML = “<HTML> Tags and markup”;

element.outerHTML = “<HTML> Tags and markup”;

document.write(“<HTML> Tags and markup”);

document.writeln(“<HTML> Tags and markup”);

element.innerHTML = “<%=Encoder.encodeForJS(Encoder.encodeForHTML(untrustedData))%>”;

element.outerHTML = “<%=Encoder.encodeForJS(Encoder.encodeForHTML(untrustedData))%>”;

document.write(“<%=Encoder.encodeForJS(Encoder.encodeForHTML(untrustedData))%>”);

document.writeln(“<%=Encoder.encodeForJS(Encoder.encodeForHTML(untrustedData))%>”);

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.

Page 12: Return of the XSS Jedi

DOM XSS IN URL SUB-CONTEXT

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”, „<%=Encoder.encodeForJS(Encoder.encodeForURL(userRelativePath))%>‟); var y = document.createTextElement(“Click Me To Test”); x.appendChild(y); document.body.appendChild(x);

var x = document.createElement(“a”); x.href = „<%=Encoder.encodeForJS(Encoder.encodeForURL(userRelativePath))%>‟; 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).

Page 13: Return of the XSS Jedi

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 = "&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x32;&#x33;&#x29;"

//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:&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x32;&#x33;&#x29;&#x0A;"

//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\u0028\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);

Page 14: Return of the XSS Jedi

DOM XSS IN CSS SUB-CONTEXT

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))„

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", "background-image:\0075\0072\006C\0028'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\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))";

Page 15: Return of the XSS Jedi

DOM XSS IN HTML ATTTRIBUTE SUB-CONTEXT

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 (<script>, <object>, etc.).

/*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);

document.scripts[1].text = "alert('scripts[1]')";

Page 16: Return of the XSS Jedi

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 =

"&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x

31;&#x32;&#x33;&#x29;"

//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:&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x32;&#x33;&#x29;&#x0A;"

//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 <script> does not work

//var s = "<\/script><script>alert(123)<\/script>//";

/*

var inp = document.createElement("input");

inp.setAttribute("value", s);

var form1 = document.forms[0];

form1.appendChild(inp);

Page 17: Return of the XSS Jedi

DOM XSS IN EVENT HANDLER SUB-CONTEXT

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);

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.

Page 18: Return of the XSS Jedi

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 =

"&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x

31;&#x32;&#x33;&#x29;"

//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:&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x32;&#x33;&#x29;&#x0A;"

//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);

Page 19: Return of the XSS Jedi

DOM BASED XSS CODE EXECUTION METHODS

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})

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.

Page 20: Return of the XSS Jedi

MISCELLANEOUS JavaScript statements can be terminated by semicolon or new line.

var a =1

var b =2;

You can declare multiple variables on the same line even if they are of different types

var a = 1, b = window.opener, c=“myString”;

You can assign system functions and objects to variables

var o = eval;

o(“alert(213)”);

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.

<input type=“text” onclick=“<%=JSEncodedVar%>” />

The attacker can pass in null” onmouseover=attackCode() x=“

<input type=“text” onclick=“null\” onmouseover=attackCode() x=\“” />

The above attack works because the HTML parser runs before the JavaScript parser.

Page 21: Return of the XSS Jedi

HTML 5 XSS NOTIFICATIONAPI PHISHING

Shows a Outlook Email Notification in bottom right corner of screen. Only works in

Chrome

function RequestPermission (callback) {

window.webkitNotifications.requestPermission(callback);

}

function showNotification(){

if (window.webkitNotifications.checkPermission() > 0) {

RequestPermission(showNotification);

}

else {

window.webkitNotifications.createNotification("http://www.wf.com/home.png",

"Title", "Body").show();

}

}

Page 22: Return of the XSS Jedi

HTML 5 XSS WebStorageAPI Poisoning

An attacker can over write Web Storage

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….

Page 23: Return of the XSS Jedi

HTML 5 XSS ClientSide SQL Injection

Request Parameters going to client side SQL

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);

Page 24: Return of the XSS Jedi

HTML 5 XSS CLIENT-SIDE STORED XSS

Data from localstorage or client DB is sent to vulnerable

methods that we have been discussing

Page 25: Return of the XSS Jedi

Q&A

?