WebSockets安全漏洞

WebSockets安全漏洞

1. WebSockets

WebSockets广泛用于现代Web应用程序中。它们通过HTTP发起,并通过双向双向通信提供长期连接。

WebSocket用于各种目的,包括执行用户操作和传输敏感信息。几乎与常规HTTP一起出现的任何Web安全漏洞也可能与WebSockets通信有关。

image-20201016085345616

2. HTTP和WebSockets有什么区别?

Web浏览器和网站之间的大多数通信使用HTTP。使用HTTP,客户端发送请求,服务器返回响应。通常,响应立即发生,并且事务完成。即使网络连接保持打开状态,这也将用于请求和响应的单独事务。

一些现代网站使用WebSockets。WebSocket连接是通过HTTP发起的,通常是长期存在的。消息可以随时向任一方向发送,并且本质上不是事务性的。在客户端或服务器准备发送消息之前,连接通常将保持打开和空闲状态。

WebSocket在需要低延迟或服务器启动消息的情况下(例如财务数据的实时提要)特别有用。

3. 如何建立WebSocket连接?

WebSocket连接通常是使用客户端JavaScript创建的,如下所示:

1
var ws = new WebSocket("wss://normal-website.com/chat");

注意

wss协议建立在一个加密的TLS连接的WebSocket,而ws协议使用未加密的连接。

为了建立连接,浏览器和服务器通过HTTP执行WebSocket握手。浏览器发出WebSocket握手请求,如下所示:

1
2
3
4
5
6
7
GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket

如果服务器接受连接,则它将返回WebSocket握手响应,如下所示:

1
2
3
4
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=

此时,网络连接保持打开状态,并且可以用于向任一方向发送WebSocket消息。

注意

WebSocket握手消息的几个功能值得注意:

  • 请求和响应中 的ConnectionUpgrade标头表示这是WebSocket握手。
  • 请求头的Sec-WebSocket-Version指定WebSocket协议版本的客户端希望使用。通常是这样13
  • 请求头的Sec-WebSocket-Key包含Base64编码的随机值,这应该在每个握手请求是随机产生的。
  • 响应头的Sec-WebSocket-Accept包含在提交的值的散列Sec-WebSocket-Key请求头,具有在协议规范中定义的特定的字符串串联。这样做是为了防止由于服务器配置错误或代 理缓存错误而引起的误导响应。

4. WebSocket消息是什么样的?

建立WebSocket连接后,客户端或服务器可以在任一方向上异步发送消息。

可以使用客户端JavaScript从浏览器发送一条简单消息,如下所示:

1
ws.send("Peter Wiener");

原则上,WebSocket消息可以包含任何内容或数据格式。在现代应用程序中,JSON通常用于在WebSocket消息中发送结构化数据。

例如,使用WebSockets的聊天机器人应用程序可能会发送如下消息:

1
{"user":"Hal Pline","content":"I wanted to be a Playstation growing up, not a device to answer your inane questions"}

5. WebSockets安全漏洞

原则上,实际上与WebSockets有关的任何Web安全漏洞都可能出现:

  • 传输到服务器的用户提供的输入可能会以不安全的方式进行处理,从而导致漏洞,例如SQL注入或XML外部实体注入。
  • 通过WebSockets达到的某些盲目漏洞可能仅使用带外(OAST)技术才能检测到。
  • 如果攻击者控制的数据通过WebSockets传输到其他应用程序用户,则可能导致XSS或其他客户端漏洞。

5.1 处理WebSocket消息以利用漏洞

可以通过篡改WebSocket消息的内容来发现和利用影响WebSocket的大多数基于输入的漏洞。

例如,假设聊天应用程序使用WebSockets在浏览器和服务器之间发送聊天消息。用户键入聊天消息时,将向服务器发送如下所示的WebSocket消息:

1
{"message":"Hello Carlos"}

消息的内容(再次通过WebSockets)传输到另一个聊天用户,并在用户的浏览器中呈现,如下所示:

1
<td>Hello Carlos</td>

在这种情况下,只要没有其他输入处理或防御措施在起作用,攻击者就可以通过提交以下WebSocket消息来执行概念验证XSS攻击:

1
{"message":"<img src=1 onerror='alert(1)'>"}

靶场url:https://portswigger.net/web-security/websockets/lab-manipulating-messages-to-exploit-vulnerabilities

复现详情:

首页存在实时聊天功能,对话框直接插入xss,抓包修改:

image-20201016234300384

修改为:

image-20201016234321766

可以看到payload已成功插入:

image-20201016234448709

成功弹窗:

image-20201016234509914

5.2 操纵WebSocket握手以利用漏洞

只能通过操纵WebSocket握手来发现和利用某些WebSocket漏洞。这些漏洞往往涉及设计缺陷,例如:

  • 在HTTP标头中放错位置的信任以执行安全性决策,例如X-Forwarded-For标头。
  • 会话处理机制存在缺陷,因为处理WebSocket消息的会话上下文通常由握手消息的会话上下文确定。
  • 应用程序使用的自定义HTTP标头引入的攻击面。

靶机url:https://portswigger.net/web-security/websockets/lab-manipulating-handshake-to-exploit-vulnerabilities

复现详情:

同理,直接在实时聊天的对话框中插入xss,观察到攻击已被阻止,并且WebSocket连接已终止。重新加载后,观察到连接尝试失败,因为IP地址已被禁止。

image-20201017004507988

重新请求并抓包,修改请求头,添加xff:

image-20201017004656270

可以重新连接WebSocket,并尝试有效的xss:

image-20201017010007974

成功弹窗:

image-20201017005721299

5.3 使用跨站点WebSocket利用漏洞

当攻击者从攻击者控制的网站建立跨域WebSocket连接时,会出现一些WebSockets安全漏洞。这称为跨站点WebSocket劫持攻击,它涉及利用WebSocket握手上的跨站点请求伪造(CSRF)漏洞。攻击通常会产生严重的影响,使攻击者可以代表受害者用户执行特权操作或捕获受害者用户可以访问的敏感数据。

5.3.1 什么是跨站点WebSocket劫持?

跨站点WebSocket劫持(也称为跨域WebSocket劫持)涉及WebSocket握手上的跨站点请求伪造(CSRF)漏洞。当WebSocket握手请求仅依靠HTTP cookie进行会话处理并且不包含任何CSRF令牌或其他不可预测的值时,就会出现这种情况。

攻击者可以在自己的域上创建恶意网页,从而建立与易受攻击的应用程序的跨站点WebSocket连接。该应用程序将在受害用户与该应用程序的会话的上下文中处理连接。

然后,攻击者的页面可以通过连接向服务器发送任意消息,并读取从服务器接收回的消息内容。这意味着,与常规CSRF不同,攻击者可以与受感染的应用程序进行双向交互。

5.3.2 跨站点WebSocket劫持有什么影响?

成功的跨站点WebSocket劫持攻击通常会使攻击者能够:

  • 执行伪装成受害者用户的未授权操作。与常规CSRF一样,攻击者可以将任意消息发送到服务器端应用程序。如果应用程序使用客户端生成的WebSocket消息执行任何敏感操作,则攻击者可以跨域生成合适的消息并触发这些操作。
  • 检索用户可以访问的敏感数据。与常规CSRF不同,跨站点WebSocket劫持使攻击者可以通过劫持的WebSocket与易受攻击的应用程序进行双向交互。如果应用程序使用服务器生成的WebSocket消息将任何敏感数据返回给用户,则攻击者可以拦截这些消息并捕获受害用户的数据。

5.3.3 执行跨站点WebSocket劫持攻击

由于跨站点WebSocket劫持攻击本质上是WebSocket握手上的CSRF漏洞,因此执行攻击的第一步是检查应用程序执行的WebSocket握手,并确定是否针对CSRF进行了保护。

就CSRF攻击的正常情况而言,您通常需要查找仅依赖HTTP cookie进行会话处理并且在请求参数中不使用任何令牌或其他不可预测值的握手消息。

例如,以下WebSocket握手请求可能容易受到CSRF的攻击,因为唯一的会话令牌是在cookie中传输的:

1
2
3
4
5
6
7
GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket

注意

Sec-WebSocket-Key头包含一个随机值,以防止缓存代理的错误,而不是用于身份验证或会话处理的目的。

如果WebSocket握手请求容易受到CSRF的攻击,则攻击者的网页可以执行跨站点请求以在易受攻击的站点上打开WebSocket。攻击的下一步将完全取决于应用程序的逻辑以及它如何使用WebSockets。攻击可能涉及:

  • 发送WebSocket消息以代表受害者用户执行未经授权的操作。
  • 发送WebSocket消息以检索敏感数据。
  • 有时,只是等待包含敏感数据的传入消息到达。

6. 如何保护WebSocket连接

为了将WebSocket引起的安全漏洞的风险降至最低,请使用以下准则:

  • 使用wss://协议(基于TLS的WebSockets)。
  • 硬编码WebSockets终结点的URL,当然不要将用户可控制的数据合并到此URL中。
  • 保护WebSocket握手消息免受CSRF的攻击,以避免跨站点WebSocket劫持漏洞。
  • 双向将通过WebSocket接收的数据视为不可信。在服务器和客户端上安全地处理数据,以防止基于输入的漏洞,例如SQL注入和跨站点脚本。
0%