Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Secure Node.js chat (avoid XSS)

I'm building a simple little chat with Node.js and socket.io

When a user types his message, it is broadcasted to all other users.

Server sends the message :

io.sockets.emit('fromServerToClient', { "message": message });

Client displays it :

socket.on('fromServerToClient', function (data) {
    $('#messages').append(data.message + '<br />');
});

But when you send something like <script>alert(1);</script>, it is executed on every client browser.

This is a serious security flaw and I want to avoid it as much as possible. I've seen people escape &, <, > and " characters, but I don't think it's enough!

How can I be 100% sure of not having a XSS vulnerability on my chat?

By the way, I always specify the charset to avoid UTF-7 attacks.

Thanks for your help.

like image 611
mimipc Avatar asked Jun 20 '13 23:06

mimipc


2 Answers

Don't use .html() because that's basically eval on steroids - capable of causing the interpretation of a good variety of languages.

Text is always interpreted as text though:

$('#messages').append($("<div>", {
    text: data.message
}));
like image 56
Esailija Avatar answered Oct 04 '22 12:10

Esailija


The best way here, is for the server to do nothing!

Yes, you read that right. The correct place to "escape" content is where it's being outputted, in the context where it's being outputted. This is known as Filter-In, Escape out.

So in your case, the client should handle the escaping for you. Funny enough, jQuery (which it looks like you're using) has a method that does this for you: $.fn.text(). So your client code becomes:

socket.on('fromServerToClient', function (data) {
    $('#messages').append($('<div></div>').text(data.message));
});

I added the div so that each message can be styled appropriately...

But your server side should have nothing to do with this escaping.

Now, you could decide to filter out anything that looks like HTML on the server, which would be known as Filtering (and either replace it away, or reject it). But definitely do not escape it!

like image 38
ircmaxell Avatar answered Oct 04 '22 12:10

ircmaxell