Documente Academic
Documente Profesional
Documente Cultură
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>
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>
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());">
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() />
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 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. <div onClick=someJSFunction(\<%=ESAPI.encodeForHTMLAttribute( request.getParameter(input1))\%>> Some Text </div>
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):
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.
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).
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", "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))";
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]')";
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.
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.
MISCELLANEOUS
You can declare multiple variables on the same line even if they are of different types
var a = 1, b = window.opener, c=myString;
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%> />
null onmouseover=attackCode() x=
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(); } }
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.
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);
Data from localstorage or client DB is sent to vulnerable methods that we have been discussing
Q&A