1

Question: Is stringifying all user input with something like JSON.stringify enough to prevent xss attacks? If not, is there an example of a xss exploit that overcomes this?

Edit for clarification: You can assume that the website does allow for html/script tags in user input and the user input gets inserted into elements the DOM.

  • You mean that you're literally applying JSON.stringify to the input and then writing it out to wherever it goes on the page? Can you give some context? Is it going between tags (<b>[STRINGIFIED_TEXT]</b>), in a property (`<font class="[STRINGIFIED_TEXT]">) or in javascript? – Conor Mancone Aug 9 at 14:44
3

To avoid many attacks, you should pay attention to what type of content you're manipulating. What looks like text is not necessarily text. This applies both for SQL (SQL Injection) and HTML (XSS).

The string abc is written abc as text. It is also written abc as HTML. So you may think that if you have text to display, you can just concatenate it with the rest of your HTML. But no, you can't.

The issue is that some characters have a special meaning in HTML. The biggest issue is <, but & is also a problem, and you want to avoid a few others for various reasons, including > and quotes, if what you are writing is an HTML attribute.

So, what you need to do is convert your text to HTML before you insert it into HTML: text is not HTML, and HTML is not text.

In some languages you have standard functions to do this, such as PHP's htmlspecialchars which you should use on every single piece of text you insert into HTML.

In Javascript, there's no standard function for this, so you have two alternatives:

  • You don't write HTML. You shouldn't anyway. You should create DOM elements, then set attributes on them, or set the text contents of them. If you use jQuery, that means you shouldn't write:

    // XXX DON'T DO THIS! EVER!
    $(thing).append($('<b>'+string+'</b>'));
    

    You should instead write:

    $(thing).append($('<b></b>').text(string));
    

    You shouldn't use .html() either.

    Likewise, don't do this:

    // XXX DON'T DO THIS
    $(thing).append($('<img src="'+url+'">"));
    

    Do this instead:

    $(thing).append($('<img>').attr('src', url));
    
  • Or, if you really want to write HTML, then you need to convert all your text to HTML to do that. This means at the very least replacing: < with &lt; and & with &amp;, but you also want to replace > with &gt and " with &quot; and ' with &#39; if that will end up in an attribute (easier to always do it). A regex replacement will do.

JSON.stringify will not help you here. JSON.stringify will not convert text to HTML, it will convert text to JSON. You want to use (actually, you need to use it) if you want to insert text into Javascript (though this would more likely happen server-side). But it doesn't protect you against XSS.

  • Thanks for the info! From an attack perspective, can you give a simple example of an xss exploit that would defeat stringification? I've tried A LOT of html injections but every time they just get converted to benign strings and the javascript inside them never executes. – ElsaInSpirit Aug 9 at 15:08
  • How are you trying? The easiest way to see it is with a server-side script. For instance in PHP: /* XXX DON'T DO THIS */ <b><?php echo $_GET['whatever'] ?></b> and call it with ?whatever=<script>alert(1);</script> should do (haven't tested it). – jcaron Aug 9 at 15:13
  • 4
    +1 @gurl.js I might clarify one detail. If the you use $(thing).append(JSON.stringify(input)) then even the most basic payload (<script>alert(1)</script>) will result in an exploit. If you use $(thing).text(JSON.stringify(input)) then you are safe even without the stringify. As a result, it's quite possible you haven't found an exploit because you happen to be using a safe method, not because of your use of JSON.stringify. – Conor Mancone Aug 9 at 15:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.