无法阻止的劫持:跨站WebSocket劫持(CSWSH)技术剖析
WebSocket协议基础
WebSocket协议于2011年通过RFC 6455标准化,实现了客户端与Web服务器之间通过单一持久连接进行全双工通信,解决了HTTP协议在双向通信方面的长期限制。例如,若要获取实时体育比赛更新,传统HTTP需要浏览器每秒向服务器发送轮询请求,而WebSocket允许服务器在事件发生时主动推送更新,消除了持续轮询的需求,显著降低了带宽消耗和用户延迟。
WebSocket与HTTP连接差异
传统HTTP连接在每次事务完成后立即终止,需要为新请求重新建立连接。而WebSocket在握手完成后保持持久连接,支持双向数据传输。下图展示了这两种协议的连接差异:
漏洞发现与检测
检测WebSocket使用
首先需要确定目标Web应用是否使用WebSocket。最佳实践是配置Burp Suite捕获流量并遍历所有页面。通常只有站点的特定组件使用WebSocket,需要仔细搜索。
在Burp Suite中打开Proxy → WebSockets history标签页查看捕获的WebSocket流量。如图示,/chat端点通过WebSocket发送和接收数据:
连接建立机制
WebSocket连接起始于HTTP协议。访问/chat端点返回的HTML文档包含JavaScript文件引用:
|
|
该JavaScript代码打开新的WebSocket连接,并引用聊天表单的action属性获取URL:
|
|
HTML表单片段显示action属性值(红色高亮):
|
|
注意:wss://表示使用TLS的安全WebSocket连接。如果服务器通过未加密的ws://传输敏感数据,这本身就是一个安全发现。
WebSocket握手过程
JavaScript执行后,浏览器发起HTTP请求进行客户端-服务器握手。服务器返回101 Switching Protocol响应,停止HTTP通信并切换到WSS。
重要说明:Sec-WebSocket-Key请求头与TLS加密或密码学无关,这是一个常见误解。实际上它提供了挑战-响应机制,确保接收连接请求的服务器具备WebSocket能力(RFC 6455章节11.3.1)。
连接建立后,服务器向客户端发送JSON消息:
协议特性与安全缺陷
WebSocket规范中一个文档记录不足的"特性"是:它不受同源策略(SOP)约束,即使在HTTP握手阶段也是如此。RFC 6455第10.2节明确指出:
不打算处理来自任何网页而只针对特定站点的输入服务器,应验证|Origin|字段是否为预期来源。如果指示的来源对服务器不可接受,则应在WebSocket握手中回复包含HTTP 403禁止状态码的响应。
同源策略是浏览器默认启用的严格安全功能,防止一个源(域)的脚本向不同源发起请求。虽然RFC未明确说明不强制执行SOP,但将Origin头验证责任留给了Web服务器(实质相同)。
跨源资源共享(CORS)通过允许网页从不同域请求和共享资源来放宽SOP限制。服务器上的CORS头定义允许访问资源的源,在启用受控跨源交互的同时增强安全性。
跨站WebSocket劫持(CSWSH)
当服务器未验证HTTP握手中的Origin头,且应用程序使用设置了samesite=None身份验证cookie时,就会发生CSWSH攻击。通过诱使用户访问恶意站点,攻击者可以在受害者浏览器中建立和操纵WebSocket通信。
漏洞验证步骤
-
发送WebSocket到Repeater:右键点击WebSocket请求选择"Send to Repeater"或按Ctrl+R
-
修改Origin头:在Repeater标签页中,点击铅笔形状的编辑连接按钮,将Origin头值伪造成恶意域名
-
测试连接:如果服务器未返回403未授权响应并允许发送接收数据,则可能存在CSWSH漏洞
-
验证连接:通过WebSocket ID确认连接使用了伪造的源
Cookie要求
CSWSH生效的最后一个要求是发送的cookie必须设置samesite=None标志。这允许浏览器在跨站请求中发送网站cookie。自2020年起,Chrome和Firefox如果省略此值则默认设置为Lax。
可通过开发者工具(Ctrl+Shift+I)的存储标签页中的cookie部分,或使用Firefox的Cookie Quick Manager扩展检查该值。如图所示,网站会话cookie的samesite标志设置为None:
也可以删除请求中的cookie来验证建立WebSocket是否需要身份验证。如果不需要,根据上下文这可能是一个值得报告的安全发现。
漏洞利用实战
攻击场景
- 攻击者发现存在漏洞的WebSocket条件
- 开发本地概念验证(POC),模拟社会工程攻击
- 在攻击者控制的站点托管恶意POC
- 诱使受害者访问攻击者控制的站点
- 恶意站点劫持受害者的认证WebSocket连接
- 攻击者窃取受害者数据或发送未经授权的WebSocket命令
利用代码示例
|
|
攻击效果
如图所示,恶意网站成功劫持了受害者的WebSocket连接,即使不在原始域名上下文下也能自动填充用户聊天历史:
拦截流量可见受害者的cookie被自动附加到恶意网站向服务器发出的请求中,这是因为会话cookie的samesite标志设置为None。Origin头显示为null,因为网页托管在本地硬盘而非具有域名的Web服务器上。
防御措施
有效防御此攻击的方法包括:
- WebSocket服务器应在HTTP握手期间阻止来源值不在严格白名单内的请求
- 用户会话cookie应设置samesite=Lax或Strict
真实攻击案例
在实际渗透测试中多次发现此漏洞,且都能将CSWSH与其他发现结合,产生更高影响:
-
权限提升案例:某应用有两个门户(志愿者和政府工作人员),动态功能完全依赖WebSocket。恶意页面能够劫持政府工作人员的WebSocket执行管理任务
-
RCE漏洞链:在管理门户中发现CSWSH漏洞,结合WebSocket内的远程代码执行漏洞,构建了攻击链:恶意站点劫持受害者WebSocket,然后通过WebSocket建立到攻击者基础设施的反向shell