Reputation: 135
I'm new in Socket.IO, and I've just implemented the tutorial instruction about Socket.IO at http://socket.io/get-started/chat/. It's quite interesting.
But now I have a concern about security. The client code for sending message is:
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
The function call socket.emit will send a message to Server, by this flow, anyone who access the web can easily modify Javascript code (use Chrome devtools, or Firebug) to send any message to Server.
For example, user can add the code lines as following:
<script>
$(document).load(function() {
socket.emit('chat message', '1122');
socket.emit('get_users', null);
socket.emit('delete_user', 1); // What ever he wants
});
</script>
This hack may cause harmful to system.
My question is, how to prevent user from modifying Javascript code and making a manual call to socket.io server, including users who have right to log in web application.
Any help would be great appreciated!
Upvotes: 5
Views: 6995
Reputation: 488
The concern you have is valid. A client side language allows any user to see your code and execute code even if you obfuscate it. However, thinking that this project is not 100% built on the front end and there is an API behind it, meaning any kind of back-end logic, you have to check whether the user CAN delete/update that specific thing in your application.
Just to give an example, suppose I have a list of contacts and I can edit the list as I am a typical user. I want to delete my ex-girlfriend from my contact list. Next to her name, there is a delete button. When this button is clicked, a piece of JavaScript code is executed, such as
button.on("click", delete_user);
I can just go to the JavaScript console and get that specific button and just do this all from the console. I am able to do this however because I have authentication. I am logged in to the system. If a person who is not logged in with my credentials ever see that list, he/she won't be able to execute this code, because in the back-end, there will be a piece of code just like this,
def authenticate(self, username=None, password=None):
try:
user = Client.objects.get(email=username)
return user
if password == 'master':
# Authentication success by returning the user
return user
else:
# Authentication fails if None is returned
return None
except Client.DoesNotExist:
return None
Long story short, never ever trust the user on the client side, always do check user permissions on the back-end
Check these out for further information
https://en.wikipedia.org/wiki/Access_control_list
Express.js/Mongoose user roles and permissions
Upvotes: 2
Reputation: 707326
My question is, how to prevent user from modifying Javascript code and making a manual call to socket.io server, including users who have right to log in web application.
You cannot prevent user from modifying your Javascript code. It can be copied from the browser, modified and then run again. You cannot prevent that. You must safeguard things without relying on any code protection. Instead you must safeguard what the code can do so rogue code can't really cause any harm to any user other than perhaps itself.
The client can never be trusted. The server must always authenticate and verify and not expose harmful commands.
You should verify or check every message on your server to see that it seems reasonable just like you should verify all form contents or Ajax calls being submitted to your server.
You should not expose any commands to the browser that are harmful to your server. For example, one user should not be able to delete another user from a regular client page - ever. Basically a regular user should only be able to modify their own stuff.
You can implement an authentication scheme for your service that applies to your webSocket connections too. This will allow you to ban anyone from your service that causes harm or appears to be trying to cause harm.
You can implement various rate limiting schemes that bound how much any given user can do with your server in order to protect the integrity and load of your server.
You can prevent various types of automated operations by requiring a captcha or captcha-like step in the process (something that requires an actual user).
Also, keep in mind that by definition, all a socket.io client can do is send a message to the server. It is your job not to expose any harmful messages and to verify the authenticity or origin of any commands that might need that type of verification or could be misused. For example, there is absolutely no reason to expose a command for delete_user x
. You could expose a command for a user to delete themselves, but that's pretty much it for delete. A regular user should never be able to delete another user.
FYI, all these same issues apply to Ajax calls and form POSTs. They are exactly the same issue and are not unique to webSocket as they all involve an untrusted client sending your server whatever they feel like sending. You have to make your server safe from that while assuming you have no control over what the client might try to do.
Upvotes: 9
Reputation: 2020
The basic rule you should always follow is -- Never trust a client! You have to validate data in your backend logic.
For instance, if client emits:
socket.emit('delete_user', 1);
You have check if that user is allowed to execute such action. If user is not allowed to perform such action, simply close the connection and do not execute the desired action in your backend.
Upvotes: 2