Pentest WebSocket: sesje, Origin i autoryzacja
Techniczna metodyka pentestu WebSocket: handshake, CSWSH, Origin, cookies, tokeny, autoryzacja wiadomości, subskrypcje, limity, detekcja i hardening.
- AUTOR
- Karol Rapacz / CEO Breachroad · OSCP · PNPT
- PUBLIKACJA
- 6 kwietnia 2026
- CZAS CZYTANIA
- 21 min czytania
- TEMAT
- Pentest i AppSec
Pentest WebSocket sprawdza znacznie więcej niż możliwość zestawienia połączenia wss://. Po handshake aplikacja otrzymuje długotrwały, dwukierunkowy kanał, przez który klient i serwer niezależnie wysyłają wiadomości. Kontrole znane z HTTP — middleware autoryzacyjny, limit per endpoint, log request/response czy wymuszenie wygasania sesji — nie zawsze działają automatycznie dla każdej ramki i operacji.
Najkrótsza odpowiedź: bezpieczny WebSocket wymaga uwierzytelnienia podczas handshake, ścisłej allowlisty
Origindla klientów przeglądarkowych oraz autoryzacji każdej akcji i subskrypcji po stronie serwera. Pentest powinien używać co najmniej dwóch kont w różnych tenantach, porównywać wiadomości i zdarzenia w macierzy ról, sprawdzać odnowienie oraz unieważnienie sesji, a testy limitów prowadzić w uzgodnionych progach. Sam fakt, że ramki są maskowane albo kanał używa TLS, nie chroni logiki aplikacji.
WebSocket występuje w czatach, powiadomieniach, platformach tradingowych, grach, panelach administracyjnych, systemach IoT, współdzielonych edytorach i konsolach chmurowych. Najpoważniejsze błędy wynikają zwykle nie z formatu ramki, lecz z tego, że serwer ufa identyfikatorowi pokoju, obiektu lub użytkownika przesłanemu przez klienta.
Jak działa WebSocket z perspektywy bezpieczeństwa
RFC 6455 definiuje opening handshake kompatybilny z HTTP, a następnie wymianę wiadomości złożonych z ramek tekstowych, binarnych i kontrolnych. W HTTP/1.1 klient prosi o upgrade, a serwer potwierdza zmianę protokołu statusem 101. RFC 8441 opisuje uruchamianie WebSocket na pojedynczym strumieniu HTTP/2 przez Extended CONNECT.
W modelu bezpieczeństwa trzeba rozdzielić cztery poziomy:
| Poziom | Co jest ustalane | Czego nie gwarantuje |
|---|---|---|
TLS (wss) | poufność, integralność transportu i tożsamość serwera | uprawnień użytkownika do akcji |
| handshake | host, origin, cookies, token i subprotocol | autoryzacji wszystkich późniejszych wiadomości |
| ramka WebSocket | opcode, maskowanie, długość i fragmentacja | poprawności JSON, Protobuf lub logiki biznesowej |
| protokół aplikacyjny | typ zdarzenia, obiekt, tenant, korelacja | bezpieczeństwa, jeżeli serwer ufa polom klienta |
Maskowanie ramek klient→serwer, wymagane przez RFC, chroni infrastrukturę pośrednią przed wybranymi atakami protokołowymi. Nie jest szyfrowaniem ani kontrolą dostępu. Serwer musi traktować zawartość po zdemaskowaniu jak niezaufane dane wejściowe.
Handshake, Origin i Cross-Site WebSocket Hijacking
Przeglądarka może dołączyć cookies do handshake zgodnie z ich zakresem. Jeżeli serwer uwierzytelnia połączenie wyłącznie cookie, ale nie sprawdza Origin, złośliwa strona może spróbować otworzyć kanał w kontekście zalogowanej ofiary. Ta klasa jest nazywana Cross-Site WebSocket Hijacking (CSWSH lub CSWH) i przypomina CSRF, lecz daje również możliwość odbierania zdarzeń z dwukierunkowego kanału.
OWASP WSTG — Testing WebSockets podkreśla odpowiedzialność serwera za weryfikację Origin. Poprawna kontrola powinna:
- porównywać pełny origin: schemat, host i port;
- używać jawnej listy zaufanych wartości, a nie dopasowania suffixu tekstowego;
- odrzucać brak lub wartość
null, jeżeli nie są wymagane przez zatwierdzonego klienta; - nie traktować
Originjako uwierzytelnienia klienta nieprzeglądarkowego, ponieważ taki klient może go ustawić dowolnie; - działać identycznie na wszystkich regionach, gatewayach i ścieżkach.
Token w query string może trafić do access logów, historii, systemu APM albo komunikatu błędu. Preferowany jest bezpieczny mechanizm handshake lub krótko żyjący, jednorazowy ticket wymieniany na sesję kanału. Jeżeli aplikacja używa cookies, potrzebuje ochrony Origin i spójnej polityki wylogowania.
Autoryzacja na poziomie wiadomości
Uwierzytelnione połączenie nie oznacza, że każda wiadomość jest dozwolona. Typowa koperta protokołu aplikacyjnego zawiera nazwę operacji, request_id, identyfikator obiektu, kanału lub tenanta oraz payload. Każde z tych pól może być sterowane przez klienta.
Serwer powinien wyznaczać podmiot z kontekstu sesji i dla każdej operacji sprawdzać:
- czy typ wiadomości jest dozwolony dla roli;
- czy obiekt należy do użytkownika albo jego tenanta;
- czy użytkownik może nie tylko odczytać, ale wykonać konkretną zmianę;
- czy subskrypcja obejmuje wyłącznie dozwolony zakres;
- czy stan workflow pozwala na operację w tej chwili;
- czy wiadomość nie jest powtórzeniem zakończonej transakcji;
- czy zmiana uprawnień lub wylogowanie unieważniły kanał.
Najgroźniejszy wzorzec to autoryzacja tylko przy subscribe, po której broker przesyła wszystkie zdarzenia do klienta nawet po zmianie roli. Drugi problem to zaufanie polu userId lub tenantId z wiadomości zamiast wartości związanej z serwerową sesją. Testy te są odpowiednikiem BOLA/BFLA opisanych w OWASP API Security Top 10.
Zakres bezpiecznego pentestu WebSocket
Rules of engagement powinny określać endpointy, subprotocols, konta, tenantry, role, środowisko oraz ograniczenia wolumenu. Do testu autoryzacji potrzebne są co najmniej dwa konta zwykłe w osobnych tenantach i konta dla każdej roli uprzywilejowanej. Dane testowe muszą mieć unikalne znaczniki.
Osobnej zgody wymagają:
- testy dużych wiadomości i fragmentacji;
- wysoka liczba połączeń, subskrypcji lub wiadomości na sekundę;
- kompresja danych i próby wyczerpania pamięci;
- długotrwałe utrzymywanie bezczynnych kanałów;
- wywołanie procesów płatności, powiadomień masowych lub urządzeń fizycznych.
Weryfikacja limitu może polegać na stopniowym dojściu do uzgodnionego progu i potwierdzeniu kodu zamknięcia, nie na powodowaniu awarii. Metodyka powinna być częścią profesjonalnego pentestu aplikacji webowej i korzystać z podobnych zasad minimalnego dowodu.
Techniczna metodyka pentestu WebSocket
1. Inwentaryzacja kanałów i protokołów
Przejrzyj kod frontendowy, aplikację mobilną, ruch sieciowy, konfigurację gatewayu i dokumentację. Zanotuj adres, wersję protokołu, Sec-WebSocket-Protocol, sposób uwierzytelniania, format wiadomości, heartbeat, reconnect, limity i broker. Sprawdź także stare ścieżki, środowiska staging i endpointy administratora.
Ustal, czy aplikacja korzysta z czystego WebSocket, Socket.IO, GraphQL subscriptions, STOMP, MQTT over WebSocket albo własnego protokołu binarnego. Biblioteka może dodawać własny handshake i semantykę pokojów, które trzeba testować niezależnie.
2. Ocena handshake
Porównaj połączenie anonimowe, zalogowane, po wylogowaniu, z wygasłym tokenem i z różnych originów. Sprawdź, czy gateway oraz backend podejmują tę samą decyzję. Negocjowany subprotocol musi należeć do listy oferowanej przez klienta i obsługiwanej przez serwer; nie może służyć do obejścia polityki routingu.
Zweryfikuj wss, certyfikat, SNI, HSTS strony inicjującej i brak downgrade’u do ws. Oceniaj logowanie: token nie powinien pojawiać się w URL ani diagnostyce. Po nieudanym handshake serwer nie może ujawniać stosu, kluczy lub pełnej konfiguracji.
3. Zbuduj katalog typów wiadomości
Przechwyć legalne przepływy i utwórz schemat: typ zdarzenia, kierunek, wymagane pola, obiekt, rola, stan, skutek uboczny i oczekiwana odpowiedź. Dla JSON zweryfikuj typy, pola dodatkowe, null, powtórzone klucze i limity zagnieżdżenia. Dla formatu binarnego pozyskaj schemat w uzgodnionym trybie grey-box.
Nie rozpoczynaj od losowego fuzzingu. Najpierw zrozum kontrakt, ponieważ różnica między „nieznane pole zignorowane” a „nieznane pole przejmuje wartość domyślną” może mieć znaczenie autoryzacyjne.
4. Macierz ról, obiektów i tenantów
Powtórz tę samą legalną wiadomość, zmieniając wyłącznie kontekst: konto A/B, tenant A/B, rola zwykła/admin, obiekt własny/cudzy. Sprawdź komendy, zapytania, subskrypcje i unsubscribe. Obserwuj zarówno bezpośrednią odpowiedź, jak i zdarzenia rozgłaszane później.
Serwer powinien odrzucić niedozwoloną akcję w sposób jednoznaczny, nie wykonywać skutku ubocznego i nie ujawniać, czy cudzy obiekt istnieje. W testach używaj syntetycznych rekordów. Szerszą macierz kontroli dostępu opisuje checklista pentestu API.
5. Stan, kolejność, race condition i replay
WebSocket ułatwia równoległe operacje. Sprawdź, czy wiadomość można wysłać przed wymaganym krokiem, powtórzyć po sukcesie, wykonać jednocześnie na dwóch kanałach albo dostarczyć po wygaśnięciu uprawnienia. Używaj niewielkiej, uzgodnionej współbieżności i operacji odwracalnych.
Wrażliwe zmiany powinny być idempotentne albo chronione unikalnym identyfikatorem, wersją obiektu lub transakcją. request_id przekazany przez klienta służy korelacji, lecz nie może sam być dowodem autoryzacji.
6. Subskrypcje, pokoje i fan-out
Przetestuj nazwy tematów, wildcardy, filtry, zmianę tenanta i odgadnięte identyfikatory pokojów. Po usunięciu członka, zmianie roli, wylogowaniu i resetowaniu hasła kanał powinien utracić dostęp zgodnie z polityką. Jeśli serwer nie potrafi reautoryzować długiej sesji, powinien wymuszać krótki czas życia i ponowny handshake.
Sprawdź wyciek metadanych: liczba użytkowników, stan obecności, nazwy tematów i błędy „pokój istnieje, ale brak dostępu” mogą ujawniać strukturę cudzej organizacji.
7. Walidacja ramek i odporność zasobowa
W środowisku testowym oceniaj długość wiadomości, liczbę fragmentów, niepoprawne UTF-8, typ opcode, ramki kontrolne, kompresję i nieukończone wiadomości. Celem jest potwierdzenie kontrolowanego zamknięcia połączenia oraz zwolnienia zasobów. Nie testuj maksymalnej pojemności produkcji bez planu testu wydajnościowego.
Limity powinny istnieć per wiadomość, połączenie, użytkownika, tenant, IP i typ operacji. Szczególne znaczenie ma limit subskrypcji oraz bufora wiadomości oczekujących na wolnego klienta. Backpressure musi zapobiegać nieograniczonemu wzrostowi pamięci.
8. Reconnect, expiry i revocation
Zbadaj, co dzieje się po chwilowej utracie sieci. Klient nie może automatycznie wznowić uprzywilejowanej sesji za pomocą starego ticketu. Rotacja refresh tokenu, wylogowanie, blokada konta i odebranie roli powinny zakończyć lub ograniczyć aktywne kanały. Jeżeli token wygasa w trakcie połączenia, serwer potrzebuje jawnej strategii: reauth albo zamknięcie.
Detekcja i logowanie WebSocket
Loguj zdarzenia semantyczne, nie pełne wiadomości z danymi klientów. Minimalny rekord powinien zawierać connection ID, użytkownika, tenant, origin, subprotocol, typ akcji, identyfikator obiektu chroniony zgodnie z klasyfikacją, wynik autoryzacji, rozmiar, latency i kod zamknięcia.
Warto alarmować na:
- dużą liczbę odrzuconych originów lub handshake;
- nagły wzrost połączeń i subskrypcji jednego podmiotu;
- próby dostępu do wielu tenantów lub pokojów;
- wiadomości po unieważnieniu sesji;
- rosnący bufor outbound i powtarzalne przekroczenia limitu;
- nietypowe opcodes, błędy fragmentacji i niepoprawne UTF-8;
- powtarzanie tego samego identyfikatora operacji;
- tokeny lub dane uwierzytelniające wykryte w URL i logach.
Korelacja z logami HTTP, IdP i brokera jest niezbędna. Jedno connection ID powinno prowadzić od handshake przez subskrypcje do rozłączenia i skutków biznesowych.
Hardening WebSocket
- Wymuszaj
wssi aktualną konfigurację TLS. - Uwierzytelniaj handshake, ale autoryzuj osobno każdą wiadomość i subskrypcję.
- Dla przeglądarek stosuj ścisłą allowlistę pełnego
Origin. - Nie przekazuj długowiecznych tokenów w query string.
- Wiąż podmiot i tenant z serwerowym kontekstem, nie z polem wiadomości.
- Waliduj kopertę i payload przez jawny schemat, odrzucając nieznane typy operacji.
- Ogranicz rozmiar, fragmenty, kompresję, częstotliwość, kolejkę i subskrypcje.
- Wdrażaj backpressure i deterministyczne czyszczenie po rozłączeniu.
- Reautoryzuj kanał po zmianie roli albo używaj krótkich sesji.
- Unieważniaj aktywne połączenia po wylogowaniu, blokadzie i krytycznej zmianie konta.
- Izoluj tematy brokera per tenant i kontroluj publishera oraz consumera.
- Testuj identyczne polityki na HTTP/1.1, HTTP/2, wszystkich regionach i gatewayach.
Wymagania warto połączyć z OWASP ASVS 5, szczególnie obszarami sesji, kontroli dostępu, walidacji i komunikacji. Jeżeli broker lub gateway działa w środowisku cloud-native, pentest chmury powinien uwzględniać polityki sieciowe i tożsamości usług.
Checklista WebSocket przed produkcją
- Endpointy, subprotocols, formaty i właściciele są zinwentaryzowani.
-
Originma pełną allowlistę i testy negatywne. - Tokeny nie trafiają do URL ani access logów.
- Każda operacja sprawdza rolę, obiekt, tenant i stan workflow.
- Subskrypcje są reautoryzowane po zmianie uprawnień.
- Wylogowanie i blokada konta zamykają aktywne kanały.
- Schemat odrzuca nieznane typy i niepoprawne wartości.
- Obowiązują limity rozmiaru, tempa, połączeń i subskrypcji.
- Backpressure ogranicza pamięć wolnego konsumenta.
- Logi korelują handshake, wiadomości i skutki biznesowe.
- Testy ról używają dwóch tenantów i syntetycznych danych.
- Retest obejmuje gateway, broker i wszystkie wersje transportu.
Źródła techniczne
- RFC 6455 — The WebSocket Protocol
- RFC 8441 — Bootstrapping WebSockets with HTTP/2
- OWASP WSTG — Testing WebSockets
- OWASP WebSocket Security Cheat Sheet
- OWASP API Security Top 10 2023
Potrzebujesz ocenić aplikację czasu rzeczywistego? Dobry pentest WebSocket łączy analizę handshake, macierz autoryzacji wiadomości, cykl życia sesji, broker i kontrolowane testy odporności. Wynikiem jest dowód konkretnego scenariusza oraz poprawka możliwa do sprawdzenia w retescie.


