-1

I noticed that it's possible to XSS my chat application. Any suggestions on how to prevent this?

I've tried:

text = escape(text);

and

text = encodeURIComponent(text);

But everything just looks weird and clumsy. I would like it that if I wrote

<b>test</b>

it would print out that exact string, and not the bold version of it. Thanks.

<div class="chat-room"></div>

b.innerHTML = '<a target="_blank" href="http://steamcommunity.com/profiles/'+steamid+'"><img src="'+avatar+'" class="avatarka"></a><div class="msg_block"><span style="cursor:pointer" class="from">'+name+'</span>: <br><span style="font-size:14px;" class="msg">'+text+'</span></div>';
            $('.chat-room').append(b);
            $('.chat-room').scrollTop(100000);

This got really messy, if you need more info, please ask, and Ill provide what ever I can. Thanks.

m0nsterr
  • 131
  • 1
  • 6

1 Answers1

2

If you want text to be treated as text, not HTML, the most robust thing is to put it in a text node:

b.innerHTML = '<a target="_blank" href="http://steamcommunity.com/profiles/'+steamid+'"><img src="'+avatar+'" class="avatarka"></a><div class="msg_block"><span style="cursor:pointer" class="from">'+name+'</span>: <br><span style="font-size:14px;" class="msg"></span></div>';
b.querySelector(".msg").appendChild(document.createTextNode(text));
$('.chat-room').append(b);
$('.chat-room').scrollTop(100000);

Note that you may want to do the same with name, if that's also derived from user-input and you haven't already sanitized it.

I'm not sure why you have that mix of innerHTML and jQuery, but that's one way to do it. The more jQuery-esque version would be:

$(b).empty().append(
    $('<a target="_blank" href="http://steamcommunity.com/profiles/'+steamid+'"><img src="'+avatar+'" class="avatarka"></a><div class="msg_block"><span style="cursor:pointer" class="from">'+name+'</span>: <br><span style="font-size:14px;" class="msg"></span></div>')
        .find(".msg").text(text)
        .end()
);
$('.chat-room')
    .append(b)
    .scrollTop(100000);

The other way is simple text processing: Converting & to &amp; and < to &lt;:

text = text.replace(/&/g, "&amp;").replace(/</g, "&lt;");

But where possible I tend to use text nodes (directly as above, or via jQuery's text method), rather than replace.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Thanks, this actually solved my issue. Yeah, I don't know why the author of this chose the way it is. I found this on a forums, and desided to use it because I really liked that way it looked and the implementation of emoticons is really good aswell. Thanks again. – m0nsterr Apr 25 '16 at 14:45