6

So as a rule of thumb I once learned that adding or removing HTML with JavaScript/JQuery (.html(),.append(), etc) leaves yourself wide open for DOM Based XSS Attacks. It is now my understanding that this is not 100% true. Supposedly there is a correct and safe way to add/remove HTML with JavaScript. I am hoping to learn some on what this "correct way" may be.

So as an example lets say I have an input filed that allows a user to append an item to a list. In this case the input would also be added to an array to be sent in future requests. Additionally this list would have a button to remove said item from that list. In an insecure environment we might do something like the following (negating array):

var list = $("#my_list");

$("#add_btn").on("click", function(){
    let input = $("#input_field").val();
    list.append(
        '<li>'+input+' <button>Remove</button></li>'
    );
});


$("#my_list").on("click", "button", function(){
    $(this).closest("li").remove();
});

How might one do the same but without the threat of XSS?

Link to JSFiddle demonstrating different suggested solutions

6
  • 1
    Hey, just to let you know, it's not recommended to cross post on multiple Stack Exchange sites. See this FAQ for more – Fire Quacker May 18 '20 at 17:10
  • @FireQuacker I will remember this going forward, thank you. – FamousAv8er May 18 '20 at 17:13
  • has nothing to do with javascript per say, but I would research something like anti-forgery tokens, which makes some cross site attacks more difficult to perform... docs.microsoft.com/en-us/aspnet/web-api/overview/security/… – pcalkins May 18 '20 at 22:08
  • @pcalkins I believe you may be confusing XSS for CSRF – FamousAv8er May 19 '20 at 16:39
  • yes, not all that familiar with terminology... but I believe there are XSS attacks that perform CSRF attacks.... (if a user visits a phishing site or has some malware plugin installed... that kind of thing... ) – pcalkins May 19 '20 at 17:23
5

Creating the DOM as string and using append or html indeed leads to DOM-based XSS. What you should do instead is to built the DOM elements using the proper functions and only inserting user-supplied input as text. Example:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<ul id=my_list class=my_list></ul>
<input type=text id=input_field value="<img src=x onerror=alert(1)>">
<button id=add_btn></button>

<script>
var list = $("#my_list");
$("#add_btn").on("click", function(){
    let input = $("#input_field").val();

    // this is insecure:
    //list.append('<li>'+input+' <button>Remove</button></li>');

    // this is secure:
    var listentry = document.createElement('li');
    listentry.innerText = input;
    list.append(listentry);
});
</script>
12
  • Would manipulating the DOM by removing elements open any attack vectors that could be mitigated in a similar manner? Something like $(this).closest("li").remove(); – FamousAv8er May 19 '20 at 14:45
  • 1
    @FamousAv8er Not as far as I know (and it really shouldn't happen, as you are not building DOM elements with user input, but just calling functions on some DOM element which we don't know anything about; if that would for some reason trigger an XSS payload, I'd consider it a vulnerability in jQuery). – tim May 19 '20 at 15:41
  • 1
    @dandavis It doesn't. text transforms the input to a string (which it already is). But when you then insert it along with the other string (<li><button>Remove</button></li>) into the DOM via append, it will be converted to DOM elements, thus triggering any JavaScript it may contain. – tim May 19 '20 at 18:31
  • 1
    @tim I have updated the JSFiddle to reflect this addition jsfiddle.net/zjr907h8 – FamousAv8er May 20 '20 at 16:39
  • 1
    @FamousAv8er The button doesn't seem to contain variables, so it should be fine as-is. But you should still be able to create it via document.createElement. To add attributes, you can use listentry.setAttribute('data-value', [value]);, which is secure (as in, the value input is treated as text). – tim Jun 16 '20 at 15:28

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.