【问题标题】:New in Socket.io, How to prevent Socket.io client script hackingSocket.io 中的新功能,如何防止 Socket.io 客户端脚本被黑客入侵
【发布时间】:2023-04-04 12:10:01
【问题描述】:

我是 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 将向服务器发送消息,通过此流程,任何访问网络的人都可以轻松修改 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>

此 hack 可能会对系统造成危害。

我的问题是,如何防止用户修改Javascript代码并手动调用socket.io服务器,包括有权登录Web应用程序的用户。

任何帮助将不胜感激!

【问题讨论】:

  • 归根结底,后端逻辑仍将是处理对套接字发出的请求的逻辑。一个“聊天消息”请求可能并不意味着对服务器或一个“get_users”请求,而是一个预设在服务器后端的“asdfga”。
  • 我理解您的意思是程序必须使用别名作为消息名称。例如,get_users 消息,我可以使用名为 'a00002' 的消息。我说的对吗?

标签: javascript node.js security socket.io


【解决方案1】:

我的问题是,如何防止用户修改 Javascript 代码和 手动调用 socket.io 服务器,包括拥有 有权登录网络应用程序。

您不能阻止用户修改您的 Javascript 代码。它可以从浏览器中复制、修改然后再次运行。你无法阻止这一点。您必须在不依赖任何代码保护的情况下保护事物。相反,您必须保护代码可以做的事情,这样流氓代码实际上不会对任何用户造成任何伤害,除了它自己。

客户永远不能被信任。服务器必须始终进行身份验证和验证,并且不暴露有害命令。

您应该验证或检查服务器上的每条消息,看看它是否合理,就像您应该验证所有表单内容或提交到服务器的 Ajax 调用一样。

Y您不应向浏览器公开任何对您的服务器有害的命令。例如,一个用户不应该能够从常规客户端页面中删除另一个用户 - 永远。基本上普通用户应该只能修改自己的东西。

您也可以为您的服务实施适用于您的 webSocket 连接的身份验证方案。这将允许您禁止任何造成伤害或似乎试图造成伤害的人使用您的服务。

您可以实施各种速率限制方案来限制任何给定用户可以对您的服务器执行多少操作,以保护服务器的完整性和负载。

您可以通过在流程中要求验证码或类似验证码的步骤(需要实际用户)来防止各种类型的自动化操作。


另外,请记住,根据定义,socket.io 客户端所能做的就是向服务器发送消息。您的工作是不暴露任何有害消息,并验证任何可能需要此类验证或可能被滥用的命令的真实性或来源。例如,绝对没有理由公开delete_user x 的命令。您可以公开一个命令让用户删除自己,但这几乎就是删除。普通用户永远不能删除其他用户。


仅供参考,所有这些相同的问题都适用于 Ajax 调用和表单 POST。它们是完全相同的问题,并且不是 webSocket 独有的,因为它们都涉及一个不受信任的客户端向您的服务器发送他们想要发送的任何内容。假设您无法控制客户端可能尝试执行的操作,您必须确保服务器安全。

【讨论】:

  • 感谢您的详细帮助。 1/ “您不应该向浏览器公开任何对您的服务器有害的命令”:我计划不公开关键功能,并且可能会更改消息的含义(例如:使用 MSG001 而不是 get_user)。 2/“你应该验证或检查每条消息”:如何完全实现它。如果我在每条消息中插入一个令牌,黑客也会克隆它,因为令牌存储在客户端。我正在考虑解决方案
  • @Ronaldinho - 隐藏邮件名称不会增加真正的安全性。它可能会稍微减慢攻击者的速度,但仅此而已。通常主要的保护措施是将逻辑从客户端转移到服务器(功能更安全,实现可以得到保障),以便服务器完成大部分工作,客户端只得到一个可以安全显示的最终结果。在这方面如何/做什么的细节不是通用的 - 它们非常特定于您的应用程序。
【解决方案2】:

您应该始终遵循的基本规则是——永远不要相信客户! 您必须在后端逻辑中验证数据。

例如,如果客户端发出:

socket.emit('delete_user', 1);

您已检查是否允许该用户执行此类操作。 如果不允许用户执行此类操作,只需关闭连接并且不要在后端执行所需的操作。

【讨论】:

    【解决方案3】:

    您的担忧是有道理的。客户端语言允许任何用户查看您的代码并执行代码,即使您对其进行了混淆。但是,考虑到这个项目不是 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
    

    长话短说,永远不要信任客户端的用户,始终检查后端的用户权限

    查看这些以获取更多信息

    http://passportjs.org/

    https://en.wikipedia.org/wiki/Access_control_list

    Express.js/Mongoose user roles and permissions

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 1970-01-01
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多