我是Socket.IO的新手,我刚刚在http://socket.io/get-started/chat/实施了有关Socket.IO的教程说明。这很有意思。
但现在我担心安全问题。 发送消息的客户端代码是:
<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>
函数调用socket.emit将向服务器发送消息,通过此流程,访问Web的任何人都可以轻松修改Javascript代码(使用Chrome devtools或Firebug)向服务器发送任何消息。
例如,用户可以按如下方式添加代码行:
<script>
$(document).load(function() {
socket.emit('chat message', '1122');
socket.emit('get_users', null);
socket.emit('delete_user', 1); // What ever he wants
});
</script>
此黑客可能会对系统造成危害。
我的问题是,如何阻止用户修改Javascript代码并手动调用socket.io服务器,包括有权登录Web应用程序的用户。
任何帮助都将非常感谢!
答案 0 :(得分:10)
我的问题是,如何防止用户修改Javascript代码和 手动调用socket.io服务器,包括拥有的用户 登录Web应用程序的权利。
您无法阻止用户修改您的Javascript代码。可以从浏览器中复制,修改然后重新运行。你不能阻止这一点。您必须在不依赖任何代码保护的情况下保护事物。相反,你必须保护代码可以做的事情,这样流氓代码才能真正对除了自己以外的任何用户造成伤害。
永远不会信任客户。服务器必须始终进行身份验证和验证,并且不会暴露有害命令。
您应该验证或检查服务器上的每条消息,看看它是否合理,就像您应该验证提交给服务器的所有表单内容或Ajax调用一样。
Y 您不应向浏览器公开任何对您的服务器有害的命令。例如,一个用户不应该从常规客户端页面中删除其他用户。基本上,普通用户应该只能修改自己的东西。
您也可以为您的服务实施适用于您的webSocket连接的身份验证方案。这将允许您禁止任何人从您的服务中造成伤害或似乎试图造成伤害。< / p>
您可以实施各种速率限制方案,这些方案限制任何给定用户可以对您的服务器执行的操作,以保护服务器的完整性和负载。
您可以通过在流程中需要像验证码或类似验证码的步骤来阻止各种类型的自动操作(需要实际用户)。
另外,请记住,根据定义,socket.io客户端可以执行的任务是向服务器发送消息。您的工作不是暴露任何有害消息,并验证可能需要该类型验证或可能被滥用的任何命令的真实性或来源。例如,绝对没有理由公开delete_user x
的命令。您可以为用户公开一个命令以自行删除,但这几乎可以用于删除。普通用户永远不能删除其他用户。
仅供参考,所有这些相同的问题都适用于Ajax调用和表单POST。它们是完全相同的问题,并不是webSocket独有的,因为它们都涉及不受信任的客户端发送服务器,无论他们想发送什么。假设您无法控制客户端可能尝试的操作,您必须使服务器安全无虞。
答案 1 :(得分:2)
您应该遵循的基本规则是 - 永远不要相信客户! 您必须验证后端逻辑中的数据。
例如,如果客户端发出:
socket.emit('delete_user', 1);
您已检查是否允许该用户执行此类操作。 如果不允许用户执行此类操作,只需关闭连接,不要在后端执行所需的操作。
答案 2 :(得分:2)
您的担忧是有效的。客户端语言允许任何用户查看您的代码并执行代码,即使您对其进行了模糊处理。但是,认为这个项目不是100%构建在前端,并且它背后有一个API,意味着任何类型的后端逻辑,你必须检查用户是否可以删除/更新应用程序中的特定事物。
举一个例子,假设我有一个联系人列表,我可以编辑列表,因为我是一个典型的用户。我想从我的联系人列表中删除我的前女友。在她的名字旁边,有一个删除按钮。单击此按钮时,将执行一段JavaScript代码,例如
button.on("click", delete_user);
我可以转到JavaScript控制台并获取该特定按钮,只需从控制台执行此操作即可。我能够做到这一点,因为我有身份验证。我登录了系统。如果没有使用我的凭据登录的人看到该列表,他/她将无法执行此代码,因为在后端会有一段代码就像这样,
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
长话短说,从不信任客户端的用户,总是检查后端的用户权限
检查这些以获取更多信息