1. WebSocket API安全测试概述
WebSocket作为HTML5规范中的重要组成部分,已经广泛应用于实时通信场景。与传统HTTP协议不同,WebSocket建立的是持久化全双工连接,这种特性在带来高效实时交互的同时,也引入了独特的安全风险。在SRC(安全应急响应中心)漏洞挖掘实战中,WebSocket接口往往成为突破边界的关键路径。
我曾在金融和物联网领域多次通过WebSocket漏洞获取关键系统权限。与常规API测试相比,WebSocket测试需要特殊的工具链和方法论。主要挑战在于:协议握手过程的复杂性、消息序列的上下文依赖、以及缺乏成熟的自动化扫描方案。本文将分享针对高级漏洞场景的实战经验,包括工具配置、流量分析和漏洞利用的全套方案。
2. 测试环境搭建与工具链配置
2.1 必备工具组合
基础工具栈建议采用以下组合:
- Burp Suite:配置WebSocket流量拦截(需Professional版)
- WSSiP:作为Burp的WebSocket代理中间件
- Chrome开发者工具:用于前端WS连接分析
- Python websockets库:用于自定义POC开发
配置Burp拦截WebSocket流量的关键步骤:
- 在Proxy → Options中启用WebSocket代理
- 安装WSSiP并配置上游代理(示例配置):
node ws_sip.js -b 127.0.0.1 -p 8081 -u http://127.0.0.1:8080- 浏览器设置代理指向WSSiP监听端口
注意:部分WSS(WebSocket Secure)连接需要处理证书错误,建议提前安装Burp根证书到系统信任区。
2.2 自定义测试脚本开发
对于复杂业务场景,推荐使用Python编写自动化测试脚本。以下是基础框架示例:
import asyncio import websockets import ssl async def exploit(): # 绕过TLS验证(仅测试环境使用) ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE async with websockets.connect( 'wss://target.com/api', ssl=ssl_context ) as ws: # 构造恶意消息 payload = {'cmd': 'getUser', 'params': {'id': 'admin'}} await ws.send(json.dumps(payload)) # 接收响应 resp = await ws.recv() print(f"Response: {resp}") asyncio.get_event_loop().run_until_complete(exploit())该脚本可实现:
- 自动建立WSS连接
- 绕过证书验证(仅限授权测试)
- 发送结构化攻击载荷
- 捕获并解析服务端响应
3. 高级漏洞挖掘技术
3.1 协议层攻击手法
3.1.1 握手过程注入
WebSocket建立连接时的HTTP Upgrade请求常被忽略安全校验。重点测试:
- Origin头伪造:修改Origin为可信域名尝试CSRF
- 协议降级:强制使用ws://非加密协议
- 版本协商漏洞:伪造Sec-WebSocket-Version触发异常处理
典型案例:
GET /socket HTTP/1.1 Host: target.com Origin: https://trusted.com Sec-WebSocket-Key: xxxxxxxxxx Upgrade: websocket Connection: Upgrade3.1.2 消息序列攻击
利用WebSocket的消息序特性实施攻击:
- 帧分割注入:将单个消息拆分为多个帧发送,测试边界条件
- 乱序消息:打乱消息顺序观察业务状态
- 大消息DDOS:发送超长消息(如10MB+)测试服务端处理能力
使用Python构造异常帧的示例:
from websockets import WebSocketClientProtocol class MaliciousClient(WebSocketClientProtocol): async def send_exploit(self): # 发送不符合RFC标准的异常帧 self.write_frame(opcode=0x3, data=b'corrupted')3.2 业务逻辑漏洞挖掘
3.2.1 权限控制缺失
WebSocket接口常见的权限问题:
- 未授权订阅:直接订阅敏感频道(如/admin/notifications)
- 水平越权:修改消息中的用户ID参数
- 功能滥用:重复调用消耗型接口(如积分兑换)
测试流程:
- 捕获正常业务消息
- 修改JSON字段中的身份标识
- 观察服务端是否校验权限
3.2.2 反序列化漏洞
当WebSocket消息采用二进制协议时,常存在反序列化风险。检测方法:
- 发送精心构造的序列化数据(Java/Python/.NET格式)
- 监控服务端异常响应
- 结合DNS/HTTP外带通道确认漏洞
Java反序列化POC示例:
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(new EvilPayload()); oos.flush(); ws.sendBinary(ByteBuffer.wrap(bos.toByteArray()));4. 典型漏洞案例解析
4.1 在线文档协作系统越权
某Google Docs类产品的WebSocket实现存在设计缺陷:
- 文档编辑操作通过WS消息传递
- 消息格式:
{"type":"edit","docId":"123","content":"..."} - 漏洞点:服务端未校验docId所属关系
利用过程:
- 创建合法文档获取正常WS消息
- 修改docId为其他用户的文档ID
- 成功获取任意文档编辑权限
修复建议:在WS连接建立时绑定文档权限,消息处理时二次校验
4.2 股票交易系统订单篡改
某券商系统的实时交易接口:
- 使用WSS协议传输交易指令
- 消息结构:
{"cmd":"order","stock":"AAPL","price":150,"qty":100} - 漏洞:未防重放攻击
攻击步骤:
- 拦截正常订单消息
- 重复发送相同消息100次
- 导致用户账户超额买入
解决方案:
- 添加消息唯一ID
- 服务端维护已处理ID集合
- 设置交易频率限制
5. 防御方案与测试要点
5.1 安全开发规范
连接鉴权:
- 在HTTP Upgrade阶段进行身份验证
- 使用JWT等令牌机制绑定会话
消息校验:
// 消息结构验证示例 const schema = Joi.object({ cmd: Joi.string().valid('get', 'set', 'delete'), params: Joi.object({ id: Joi.string().regex(/^[a-z0-9]{24}$/) }).required() }); ws.on('message', msg => { const { error } = schema.validate(JSON.parse(msg)); if (error) ws.terminate(); });资源控制:
- 限制单个连接的消息频率
- 设置消息大小上限(如1MB)
5.2 渗透测试Checklist
完整测试流程应包含:
| 测试项 | 检测方法 | 风险等级 |
|---|---|---|
| 握手过程安全 | 修改Origin/Protocol头 | 中 |
| 消息权限控制 | 篡改用户身份参数 | 高 |
| 反序列化漏洞 | 发送恶意序列化数据 | 严重 |
| 业务逻辑缺陷 | 重复发送消耗型指令 | 中 |
| 连接持久化攻击 | 维持大量空闲连接 | 低 |
6. 实战经验与技巧
上下文保持技巧:
- 使用Burp的Match/Replace功能自动添加认证头
- 保存WebSocket会话到文件供后续分析:
websocat -E wss://target.com/api | tee session.log
隐蔽测试方法:
- 通过WebSocket over TLS(WSS)规避网络监控
- 使用分帧技术绕过WAF检测:
# 分片发送敏感指令 await ws.send('{"cmd":"get') await asyncio.sleep(1) await ws.send('User","id":"admin"}')
性能边界测试:
- 快速连续发送1000+消息测试服务端队列处理
- 构造深度嵌套的JSON消息(超过解析层限制)
在最近一次金融行业测试中,通过组合使用分帧技术和慢速发送方式,成功绕过了某WAF的WebSocket防护策略,最终获取到交易系统的管理权限。这提醒我们,WebSocket安全需要从协议实现、业务逻辑到基础设施的全方位防护。