11

I'm testing xss attacks on my own code. The example beneath is a simple box where an user can type whatever he wants. After pressing "test!" button, JS will show the input string into two divs.This is an example I made to explain better my question:

<html>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
    function testIt(){
        var input = document.getElementById('input-test').value;
        var testHtml = document.getElementById('test-html');
        var testInnerHTML = document.getElementById('test-innerHTML');
        $(testHtml).html(input);
        testInnerHTML.innerHTML = input;
    }
</script>
<head>this is a test</head>
<body>  
    <input id="input-test" type="text" name="foo" />
    <input type="button" onClick="testIt();" value="test!"/>
    <div id="test-html">
    </div>
    <div id="test-innerHTML">
    </div>
</body>

if you try to copy it into a .html file and run it, it will work fine, but if you try to input <script>alert('xss')</script>, only one alert box will be thrown: the one inside `test-html' div (with html() function).

I really can't understand why this is happening, and also, inspecting the code with firebug gives me this result (after injecting the script)

<body>
this is a test
<input id="input-test" type="text" name="foo">
<input type="button" value="test!" onclick="testIt();">
<div id="test-html"> </div>
<div id="test-innerHTML">
  <script>
    alert('xss')
  </script>
</div>
</body>

as you can see test-html div is empty, and test-innerhtml div contans the script. Can someone tell me why? Is because html() is more secure against scripts injection or something similar?

Thanks in advance, best regards.

BeNdErR
  • 17,471
  • 21
  • 72
  • 103
  • 2
    You don't have to worry about security as the user types, because whatever script they try to insert will only affect them at that point. What you do need to worry about is what happens when the entered text gets submitted to your webserver - if you're storing it in a database you need to be sure you don't just blindly concatenate the entered text on the end of an SQL query. If you later return previously entered text you need to be sure that the entered value is escaped so that, e.g., " – nnnnnn Nov 29 '11 at 23:03
  • 3
    Hi nnnnnnn. XSS can occure even if the script never reaches the server. There are two types. Self-XSS where the user is tricked into typing something somehow, and then DOM-based XSS, which means the browser is using untrusted input directly in the browser, which never reaches the server. Typically this could be window.name, window.referer or data from after the # in the url. Lots of big sites around the web (wikipedia, aol, twitter) have had DOM based XSS. – Erlend Dec 01 '11 at 18:35

4 Answers4

28

Contrary to what is being said in the accepted answer, jQuery.html() and the many jQuery functions which accept HTML strings as arguments are more prone to DOM-based XSS injection than innerHTML, as noticed by the OP.

jQuery.html() extracts the <script> tags, updates the DOM and evaluates the code embedded in the script tags.

As a result, XSS can happen without user interaction even after the DOM is loaded when using jQuery.html().

This is very easy to demonstrate.

This will call alert():

$('.xss').html('<script>alert("XSS");</script\>');

http://jsfiddle.net/2TpHC/

While this will not:

var d = document.getElementById('xss');
d.innerHTML = '<script\>alert("XSS");</script\>';

http://jsfiddle.net/Tjspu/

Unfortunately, there are many other code paths (sinks) which lead to calling eval() in jQuery. The security conscious will probably avoid jQuery altogether, as far as possible.

Note that I do not claim that using innerHTML is an effective defense against XSS. It is not. Passing unescaped data to innerHTML is not safe, as pointed out by @daghan. One should always properly escape data when generating HTML.

Erwan Legrand
  • 4,148
  • 26
  • 26
  • 4
    '' alerts for innerHTML. You can use textarea instead of div but then '' alerts for firefox and ie9 – daghan Nov 03 '14 at 09:36
6

JQuery strips out the script tags, which is why you aren't seeing it append to the dom let alone executing.

To see an explanation of why jquery strips it out, you can see John Resig's reply here: https://forum.jquery.com/topic/jquery-dommanip-script-tag-will-be-removed

Hope this helps

MatthewJ
  • 3,127
  • 2
  • 27
  • 34
1

yes jquery html won't render script tags

but it isn't more secure because you can use many other xss payloads such as <a href> style , expression etc..

Ben
  • 1,914
  • 2
  • 13
  • 11
  • 2
    It *is* more secure, it just isn't *completely* secure and shouldn't be relied on. – Mario Nov 29 '11 at 22:41
  • 1
    yeah I guess that's true , but secure is not the word, let's just agree it's less vulnerable then innerHTML. – Ben Nov 29 '11 at 22:46
  • Actually, **what jQuery does is more prone to exploitation** because the first thing jQuery does when it finds ` – Erwan Legrand Apr 27 '17 at 10:42
1

This is similar to both this question and this one. .html() strips out the script tags before it inputs the HTML and executes them separately.

As for why the second one is not being executed, it is because dynamically added scripts like that will not be run after the page has been loaded.

But, as @Ben points out, there are a lot of XSS openings when accepting things like that. That said, if the information is being displayed on their own page, they can run any arbitrary code they want on their own machine. The big issue will be if you store this, or send this to other users. Unless you do that, there is no protecting users from themselves in these sorts of regards. Maybe knowing what you're trying to protect against will help.

Community
  • 1
  • 1
LoveAndCoding
  • 7,857
  • 2
  • 31
  • 55
  • So html() function does something like update/append the content and then run it again, while innerHTML just updates/appends the new html without running it? Anyway, I'm not trying to protect against something in particular, I'm reading a book about XSS attacks, and I'm trying to reproduce the examples I find. Now the doubt is solved! Thanks for your help! – BeNdErR Nov 29 '11 at 23:13