【问题标题】:Why is there no same-origin policy for WebSockets? Why can I connect to ws://localhost?为什么 WebSockets 没有同源策略?为什么我可以连接到 ws://localhost?
【发布时间】:2014-07-03 15:53:43
【问题描述】:

我想为我的应用程序(DaemonWebGUI 和 DaemonFatClient 等)使用 WebSockets 进行进程间通信。在测试期间,我尝试通过 websocket.org (http://www.websocket.org/echo.html) 上的 JavaScript WebSocket 客户端连接到本地运行的 Web 套接字服务器 (ws://localhost:1234)。

我现在的问题是:
为什么会这样? 浏览器中是否没有实施跨域策略(此处:Linux 上的 FF29)?

我问是因为如果 websocket.org 是邪恶的,它可能会尝试与我的本地 WS 服务器通信并将它从 localhost 接收到的每条消息重定向到任何其他服务器:

本地 WebSocket 服务器 浏览器 邪恶的 Web 服务器 在 ws://localhost:1234 在 http://evil.tld | | | | |-----[GET /]--------->| | || | | |----[邪恶前锋]---->| | | |

我还没有测试整个用例,但是从 websocket.org 提供的 JS 连接到 ws://localhost 确实有效。

【问题讨论】:

  • websocket.org 不应该是邪恶的,Web 套接字可以;)

标签: javascript security websocket


【解决方案1】:

WebSockets可以跨域通信,不受SOP(Same Origin Policy)限制。

没有 WebSockets 也可能发生您描述的相同安全问题。

邪恶的JS可以:

  • 创建一个带有指向 evil.tld 的 URL 的脚本/图像标记,并将数据放入查询字符串中。
  • 创建一个表单标签,将数据放入字段中,然后调用表单的“提交”操作,执行一个可以跨域的 HTTP POST。 AJAX 受 SOP 限制,但普通 HTTP POST 不受限制。检查 XSRF 网络安全问题。

如果某些东西在您的页面中注入了 javascript,或者您收到了恶意 javascript,那么您的安全性就已经被破坏了。

【讨论】:

  • 我不担心邪恶的JS。我知道这总是可能的。我真正关心的是浏览器突破:任何网站现在都可以与 本地 绑定的 WS 套接字通信并从那里窃取数据。
  • SOP/CORS 不适用于 WebSocket,但浏览器将发送一个 origin 标头,其中包含使用打开 WebSocket 连接的 JS 提供 HTML 的服务器的主机名。然后,WebSocket 服务器可以通过检查 origin 来限制访问。
  • 这没有回答问题。问题是为什么 来自不同域的网页 可以访问本地 WebSocket。在 OPs 场景中,没有任何东西可以“在您的页面中注入 javascript”——这是一个不同的场景。如果没有 WebSocket,远程网页将无法读取 localhost 上的资源,因为这正是 SOP 所阻止的。
【解决方案2】:

oberstet answered the question。谢谢!不幸的是,我无法将其标记为“正确”,因为它是一条评论。浏览器发送可以被应用程序检查的“origin”标头。

在 Java [1] 中:

@Override
public void onOpen(WebSocket clientSocket, ClientHandshake 握手) {
    String clientOrigin = handshake.getFieldValue("origin");

    if (clientOrigin == null || !clientOrigin.equals(WEBSOCKET_ALLOWED_ORIGIN_HEADER)) {
        logger.log(Level.WARNING, "客户端没有发送正确的源头:" + clientOrigin);

        clientSocket.close();
        返回;
    }

    // ...
}

[1] 使用https://github.com/TooTallNate/Java-WebSocket

【讨论】:

  • OWASP 提到在其CSRF cheat sheet 中检查 Origin(可能还有 Referer)标头是第一步也是最重要的一步,但他们也建议更进一步并实施 CSRF 特定防御。对于 WebSockets,这可能是将 XSRF 防伪令牌作为查询参数附加到 WS URI 并在源检查后在服务器端验证它。
【解决方案3】:

解决“为什么?”与 AJAX 调用相反,浏览器不为 WebSockets 强制执行同源策略(其中 CORS 是一种放松)的部分原因是因为 WebSockets 是在建立跨域请求的价值之后引入的,并且因为它们'不受 SOP 约束,CORS 客户端检查的历史原因不适用。

对于 AJAX,在单一来源策略的时代,服务器从不期望经过身份验证的浏览器从不同的域发送请求1,因此不需要确保请求是来自受信任的位置2,只需检查会话 cookie。后来的 CORS 等放松必须进行客户端检查,以避免通过违反此假设来避免 exposing existing applications to abuse(实际上是在执行 CSRF attack)。

如果今天发明了 Web,知道我们现在所知道的,AJAX 就不需要 SOP 和 CORS,并且所有验证都可能留给服务器。

WebSockets 是一种较新的技术,旨在从一开始就支持跨域场景。任何编写服务器逻辑的人都应该意识到跨域请求的可能性并执行必要的验证,而不需要像 CORS 那样采取严厉的浏览器端预防措施。


1 这是一个简化。资源的跨域 GET 请求(包括

2 事实上,检查请求源的安全方法甚至不可用,因为 Referer 标头可以被欺骗,例如使用开放重定向漏洞。这也说明了当时对 CSRF 漏洞的理解是多么糟糕。

【讨论】:

  • 这确实回答了这个问题,所以+1。但是,郑重声明,我强烈不同意这种推理。我预测,由于这一设计决策,大量使用 WebSockets 的站点将无法验证 Origin 标头并因此将私人用户数据泄露给第三方站点。客户端检查 Access-Control-Allow-Origin 标头,就像他们在允许 JS 访问对 Web 上任何其他跨域 HTTP 请求的响应之前所做的那样,将是防止整个攻击类别的一种简单方法(跨站点 WebSocket 劫持) .现在太晚了。
  • 我倾向于同意,设计更改本质上是从基于白名单的方法转向黑名单方法,这是有风险的。公平点。
猜你喜欢
  • 2010-12-22
  • 2012-12-25
  • 2016-06-14
  • 2016-01-20
  • 2012-07-01
  • 2015-05-23
  • 1970-01-01
  • 1970-01-01
  • 2012-07-20
相关资源
最近更新 更多