WebSocket Security Cheat Sheet¶
Introduction / 介绍¶
WebSockets enable real-time, bidirectional communication between clients and servers, powering applications like chat systems, live trading platforms, and collaborative tools. Unlike traditional HTTP requests, WebSocket connections remain open and allow continuous data exchange.
However, WebSockets introduce security challenges that differ from standard web application security:
- Cross-Site WebSocket Hijacking (CSWSH): Attackers hijack authenticated connections from malicious websites
- Authentication bypass: No built-in authentication makes access control easy to forget
- Injection attacks: WebSocket messages can carry XSS, SQL injection, and other malicious payloads
- Denial-of-service: Persistent connections enable new DoS attack vectors like connection exhaustion
- Monitoring gaps: Traditional HTTP logs only capture the initial upgrade request, missing all message traffic
Real-world vulnerabilities:
现实世界漏洞:
- Gitpod CSWSH (2023): Insufficient origin validation allowed full account takeover via hijacked WebSocket connections
中文:Gitpod CSWSH (2023): 原点验证不足 允许通过劫持 WebSocket 连接实现完全账户接管。 - Spring RCE vulnerability: CVE-2018-1270 let attackers execute code through crafted STOMP messages
中文:Spring RCE 漏洞:CVE-2018-1270 允许攻击者通过精心制作的 STOMP 消息执行代码。
Primary Defenses / 主要防御¶
Transport Security / 传输安全¶
Always Use WSS (WebSocket Secure) / 始终使用 WSS (WebSocket 安全)¶
Never use unencrypted ws:// connections in production. Unencrypted ws:// connections allow eavesdropping and tampering.
在生产环境中切勿使用未加密的 ws:// 连接。未加密的 ws:// 连接允许窃听和篡改。
// Secure - always use this
const socket = new WebSocket('wss://app.example.com/socket');
// Insecure - never use in production
// const socket = new WebSocket('ws://app.example.com/socket');
See the Transport Layer Security Cheat Sheet for more details.
有关更多详细信息,请参阅传输层安全速查表。
WebSocket Protocol Configuration / WebSocket 协议配置¶
Use modern protocol versions:
使用现代协议版本:
Only support RFC 6455 (the current WebSocket standard). Drop backward compatibility for outdated versions like Hixie-76 and hybi-00 which have known security vulnerabilities.
仅支持 RFC 6455(当前 WebSocket 标准)。放弃对已知存在安全漏洞的旧版本,如 Hixie-76 和 hybi-00。
Compression security:
压缩安全:
Disable permessage-deflate compression unless specifically needed. Compression can introduce security vulnerabilities similar to CRIME/BREACH attacks where compression combined with secret data can leak information.
除非特别需要,否则请禁用 permessage-deflate 压缩。压缩可能会引入类似于 CRIME/BREACH 攻击的安全漏洞,其中压缩与秘密数据结合可能导致信息泄露。
// Node.js - disable compression for security
const wss = new WebSocket.Server({
perMessageDeflate: false
});
Infrastructure Configuration / 基础设施配置¶
Proxy and load balancer support:
代理和负载均衡器支持:
Ensure reverse proxies, load balancers, and CDNs are configured to handle WebSocket upgrades:
确保反向代理、负载均衡器和 CDN 配置以处理 WebSocket 升级:
- Configure proxy to support HTTP/1.1 upgrade mechanism
中文:配置代理以支持 HTTP/1.1 升级机制。 - Pass
UpgradeandConnection: upgradeheaders correctly
中文:正确传递Upgrade和Connection: upgrade头部信息 - Set proper read timeouts for long-lived connections
中文:为长连接设置适当的读取超时 - Ensure WebSocket traffic isn't blocked by security policies
中文:确保 WebSocket 流量不会被安全策略阻止
WAF support:
WAF支持:
Check that your WAF supports WebSocket traffic inspection beyond the initial handshake. If not, rely on server-side validation and application logging.
检查您的WAF是否支持WebSocket流量检查,而不仅仅是初始握手。如果不支持,则依赖于服务器端验证和应用程序日志记录。
Authentication and Authorization / 身份验证和授权¶
For general identity and session controls, see the Authentication Cheat Sheet and Session Management Cheat Sheet.
有关通用身份和会话控制,请参阅身份验证速查表和会话管理速查表。
WebSockets don't have built-in authentication. Browsers include cookies in WebSocket handshake requests, making WebSocket applications vulnerable to Cross-Site WebSocket Hijacking (CSWSH).
WebSocket没有内置的身份验证。浏览器会将cookie包含在WebSocket握手请求中,这使得WebSocket应用程序容易受到跨站WebSocket劫持(CSWSH)的攻击。
CSWSH allows attackers to hijack authenticated WebSocket connections from malicious websites:
CSWSH允许攻击者从恶意网站劫持经过身份验证的WebSocket连接:
- User logs into your application (session cookie established)
中文:用户登录到您的应用程序(建立会话cookie) - User later visits a malicious website
中文:用户后来访问恶意网站 - Malicious site opens WebSocket to your application, browser sends cookies automatically
中文:恶意网站向您的应用程序打开WebSocket,浏览器自动发送cookie - Server accepts the connection → attacker gets live, authenticated WebSocket access
中文:服务器接受连接 → 攻击者获得实时、认证的WebSocket访问
Origin Header Validation / 源头验证¶
Validate the Origin header on every handshake. Always use an explicit allowlist of trusted origins. Browsers include this header and malicious JavaScript cannot override it.
在每次握手时验证Origin头。始终使用显式的受信任源允许列表。浏览器包含此头,恶意JavaScript无法覆盖它。
For Node.js ws, validate the Origin header in the HTTP server's upgrade event before calling handleUpgrade; the library discourages verifyClient (ws documentation).
对于Node.js的ws,在调用handleUpgrade之前,在HTTP服务器的upgrade事件中验证Origin头;该库不鼓励使用verifyClient(ws文档)。
Important: Use an allowlist, not a denylist. Avoid wildcards or substring matching which are error-prone.
重要: 使用允许列表,而不是拒绝列表。避免使用通配符或子字符串匹配,这些容易出错。
Additional CSWSH Protections / 额外的CSWSH保护¶
For applications already using CSRF protection, include CSRF tokens in WebSocket handshakes.
对于已经使用CSRF保护的应用程序,在WebSocket握手时包含CSRF令牌。
Session Management / 会话管理¶
WebSocket connections often outlive normal sessions, requiring special handling.
WebSocket连接通常比正常会话持续时间更长,需要特殊处理。
Use SameSite cookies (SameSite=Lax or Strict) to prevent cross-site cookie transmission and strengthen CSWSH defenses.
使用SameSite cookie (SameSite=Lax 或 SameSite=Strict) 以防止跨站cookie传输并加强CSWSH防御。
Handle session expiration by implementing server-side validation for long-running connections. Close WebSocket connections when sessions expire. Re-validate user sessions periodically (every 30 minutes is common) to ensure they remain valid.
处理会话过期 通过实现针对长时间运行的连接的服务器端验证。当会话过期时关闭WebSocket连接。定期(例如每30分钟)重新验证用户会话以确保其有效性。
// Example: Close WebSocket on session expiry
function validateSession(ws, sessionId) {
if (!isSessionValid(sessionId)) {
ws.close(1008, 'Session expired');
return false;
}
return true;
}
When users log out, close all their WebSocket connections immediately. Maintain a mapping of sessions to active connections so you can invalidate WebSocket access the moment logout occurs.
当用户注销时,立即关闭他们所有的WebSocket连接。维护会话到活动连接的映射,以便在注销时立即使WebSocket访问无效。
Token-based authentication:
基于令牌的认证:
For browser clients using tokens, prefer sending the token in the first message over WSS. Avoid tokens in URL query strings because they can leak into access logs; see the websockets authentication guidance.
对于使用令牌的浏览器客户端,优先在WSS中发送第一个消息中的令牌。避免在URL查询字符串中使用令牌,因为它们可能会泄露到访问日志中;参见websockets认证指南。
Until token validation succeeds, accept only the authentication message and do not send protected data. Close the connection on authentication failure or timeout, and limit unauthenticated connections. Message-based authentication keeps tokens out of the handshake URL, but tokens must also be excluded from message logs.
在令牌验证成功之前,仅接受认证消息,不要发送受保护的数据。在认证失败或超时时关闭连接,并限制未认证的连接。基于消息的认证将令牌排除在握手URL之外,但令牌也必须排除在消息日志之外。
Token refresh:
令牌刷新:
Rotate tokens in long-lived connections to prevent hijacked sessions from persisting.
在长连接中轮换令牌,以防止被劫持的会话持续存在。
Message-Level Authorization / 消息级别授权¶
Don't assume WebSocket connection equals unlimited access. Check authorization for each action:
不要假设WebSocket连接等于无限访问。检查每个操作的授权:
ws.on('message', (data) => {
const message = JSON.parse(data);
// Check authorization for each action
if (message.action === 'delete_user' && !user.hasRole('admin')) {
ws.send(JSON.stringify({type: 'error', message: 'Access denied'}));
return;
}
handleAuthorizedMessage(ws, user, message);
});
Input Validation / 输入验证¶
Treat all WebSocket messages as untrusted input. WebSocket messages can carry injection payloads such as SQLi, XSS, and command injection.
将所有WebSocket消息视为不受信任的输入。WebSocket消息可以携带注入有效载荷,如SQL注入、XSS和命令注入。
Validate message structure and content using JSON schemas and allow-lists. Set reasonable size limits (typically 64KB or less) and implement rate limiting to prevent message flooding.
使用JSON模式和白名单验证消息结构和内容。设置合理的尺寸限制(通常不超过64KB)并实现速率限制,以防止消息洪水攻击。
For binary data, verify file types using magic numbers rather than trusting content-type headers. Scan uploads for malware when appropriate, and use safe deserialization for protocols like protobuf or MessagePack.
对于二进制数据,使用魔数而不是信任内容类型头来验证文件类型。在适当的时候扫描上传文件以检测恶意软件,并为像protobuf或MessagePack这样的协议使用安全的反序列化。
ws.on('message', (data, isBinary) => {
if (isBinary) {
// Validate binary data
if (data.length > MAX_BINARY_SIZE) {
ws.close(1009, 'Message too large');
return;
}
// Check file type by magic numbers
if (!isValidFileType(data)) {
ws.close(1008, 'Invalid file type');
return;
}
}
processBinaryData(data);
});
To prevent message replay attacks include timestamps or nonces in messages and reject duplicates to ensure old messages cannot be maliciously resent.
为了防止消息重放攻击,在消息中包含时间戳或nonce,并拒绝重复项,以确保旧消息不能被恶意重发。
ws.on('message', (data) => {
const message = JSON.parse(data);
// Check timestamp or nonce to prevent replay
if (!isValidNonce(message.nonce)) {
ws.close(1008, 'Replay detected');
return;
}
processMessage(message);
});
Always use JSON.parse() instead of eval() for JSON processing - eval() enables code execution from untrusted input.
// Safe
const message = JSON.parse(data);
// Dangerous - enables code execution
// const message = eval('(' + data + ')');
See the Input Validation Cheat Sheet, Cross Site Scripting Prevention Cheat Sheet, and SQL Injection Prevention Cheat Sheet for more details.
Service Tunneling Risks¶
While WebSockets can tunnel TCP services (VNC, FTP, SSH), this creates security risks. If your application has XSS vulnerabilities, attackers could access these services directly from victims' browsers. If tunneling is necessary, implement additional authentication and access controls beyond the WebSocket layer.
Denial-of-Service Protection¶
Persistent WebSocket connections increase DoS risk.
Limit connections and resources by restricting total connections and implementing per-user limits (preferred) or per-IP limits where user identification isn't available. Set message size limits (typically 64KB or less) and implement rate limiting to prevent message flooding - 100 messages per minute is a common starting point.
Handle idle and dead connections by implementing idle timeouts to close inactive connections. Use heartbeat monitoring with ping/pong frames to detect and clean up dead connections.
Implement backpressure controls to prevent memory exhaustion from fast message producers. Many WebSocket implementations lack proper flow control, allowing attackers to overwhelm server memory by sending messages faster than they can be processed.
实现背压控制以防止快速消息生产者导致内存耗尽。许多WebSocket实现缺乏适当的流量控制,允许攻击者通过发送比处理速度更快的消息来耗尽服务器内存。
const wss = new WebSocket.Server({
maxPayload: 64 * 1024
});
Security Monitoring and Logging / 安全监控与日志记录¶
Traditional HTTP access logs only capture the initial WebSocket upgrade request, not subsequent message traffic. You'll miss auth failures, injection attempts, rate-limit violations, and abuse.
传统的HTTP访问日志仅捕获初始WebSocket升级请求,而不是后续的消息流量。您将错过认证失败、注入尝试、速率限制违规和滥用等情况。
Log WebSocket events including connection establishment and termination (with user identity, IP, and origin), authentication and authorization events during handshake and message processing, security violations like rate limiting triggers and message validation failures, and abnormal disconnections and protocol errors.
记录WebSocket事件包括连接建立和终止(包括用户身份、IP和来源)、握手和消息处理期间的认证和授权事件、安全违规如速率限制触发和消息验证失败,以及异常断开连接和协议错误。
Avoid logging sensitive data - never log complete message contents, authentication tokens, session IDs, or personal information that could violate privacy regulations.
避免记录敏感数据 - 永远不要记录完整消息内容、认证令牌、会话ID或可能违反隐私法规的个人资料信息。
See the Logging Cheat Sheet for more details.
查看日志作弊表获取更多详细信息。
Testing WebSocket Security / 测试WebSocket安全¶
Key security tests:
关键安全测试
- Origin validation: Connect from unauthorized domains
中文:源验证:来自未经授权域的连接 - Authentication bypass: Attempt connections without proper credentials
中文:身份验证绕过:尝试无正确凭证的连接 - Message injection: Send XSS, SQL injection, and command injection payloads
中文:消息注入:发送 XSS、SQL 注入和命令注入载荷 - DoS resistance: Test connection limits, message flooding, and oversized messages
中文:拒绝服务(DoS)抵抗:测试连接限制、消息洪泛和 oversized 消息 - Session management: Test session expiration and logout handling
中文:会话管理:测试会话过期和注销处理
Testing tools:
测试工具:
- Browser developer tools for manual testing
中文:浏览器开发者工具进行手动测试 - wscat for command-line WebSocket connections
- Custom scripts for automated vulnerability testing
中文:用于自动化漏洞测试的自定义脚本 - OWASP ZAP (includes WebSocket security testing features)
中文:OWASP ZAP(包含WebSocket安全测试功能)
Framework-Specific Best Practices / 框架特定最佳实践¶
Node.js: With ws, perform origin and authentication checks in the HTTP server's upgrade event; set maxPayload limits and disable perMessageDeflate compression unless needed.
Node.js: 使用ws,在HTTP服务器的upgrade事件中执行源和身份验证检查;设置maxPayload限制并禁用perMessageDeflate压缩除非需要。
Python: With Django Channels, implement authentication middleware and origin validation. Use async exception handling to prevent application crashes from malformed WebSocket messages.
Python: 使用Django Channels,实现身份验证中间件和源验证。使用异步异常处理防止应用程序因格式错误的WebSocket消息而崩溃。
Java Spring: Configure allowed origins explicitly and integrate Spring Security for authorization. Set message size limits in your WebSocket container configuration to prevent resource exhaustion.
Java Spring: 明确配置允许的源并集成Spring Security进行授权。在WebSocket容器配置中设置消息大小限制以防止资源耗尽。
Go: When using Gorilla WebSocket, implement validation in your CheckOrigin function - don't just return true. Set read limits, implement timeouts, and use context cancellation for graceful connection cleanup.
Go: 使用Gorilla WebSocket时,在CheckOrigin函数中实现验证 - 不要只是返回true。设置读取限制,实现超时,并使用上下文取消进行优雅的连接清理。
Keep Dependencies Updated / 保持依赖项更新¶
Regularly update WebSocket libraries and monitor security advisories. Past versions of popular libraries (ws, Spring STOMP, Python websockets) have had critical security vulnerabilities including DoS and RCE issues.
定期更新 WebSocket 库并监控安全通告。流行的库(如 ws、Spring STOMP、Python websockets)的旧版本存在包括拒绝服务(DoS)和远程代码执行(RCE)在内的关键安全漏洞。
References / 参考¶
- RFC 6455: The WebSocket Protocol) (RFC 6455:WebSocket 协议)
- CWE-1385: Missing Origin Validation in WebSockets) (CWE-1385:WebSocket 中缺少源验证)