# WebSocket Attacks {{#include ../banners/hacktricks-training.md}} ## WebSockets nedir WebSocket bağlantıları başlangıçta bir **HTTP** handshake ile kurulur ve **long-lived** olacak şekilde tasarlanmıştır; bu sayede transactional bir sisteme ihtiyaç duymadan her zaman çift yönlü mesajlaşmaya izin verir. Bu, canlı finansal veri akışları gibi **düşük gecikme veya server-initiated communication** gerektiren uygulamalar için WebSockets'i özellikle avantajlı kılar. ### WebSocket Bağlantılarının Kurulması WebSocket bağlantılarının kurulmasına dair detaylı bir açıklamaya [**burada**](https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc) ulaşılabilir. Özetle, WebSocket bağlantıları genellikle aşağıda gösterildiği gibi istemci tarafı JavaScript ile başlatılır: ```javascript var ws = new WebSocket("wss://normal-website.com/ws") ``` `wss` protokolü **TLS** ile güvenli hale getirilmiş bir WebSocket bağlantısını ifade ederken, `ws` **güvenli olmayan** bir bağlantıyı gösterir. Bağlantı kurulurken, HTTP üzerinden tarayıcı ile sunucu arasında bir handshake gerçekleştirilir. Handshake süreci tarayıcının bir istek göndermesini ve sunucunun yanıt vermesini içerir; aşağıdaki örneklerde gösterildiği gibi: Tarayıcı bir handshake isteği gönderir: ```javascript 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 ``` Sunucunun handshake yanıtı: ```javascript HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: websocket Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk= ``` Bağlantı kurulduktan sonra iki yönlü mesaj alışverişi için açık kalır. **WebSocket Handshake'in Temel Noktaları:** - The `Connection` and `Upgrade` headers signal the initiation of a WebSocket handshake. - The `Sec-WebSocket-Version` header indicates the desired WebSocket protocol version, usually `13`. - A Base64-encoded random value is sent in the `Sec-WebSocket-Key` header, ensuring each handshake is unique, which helps to prevent issues with caching proxies. This value is not for authentication but to confirm that the response is not generated by a misconfigured server or cache. - The `Sec-WebSocket-Accept` header in the server's response is a hash of the `Sec-WebSocket-Key`, verifying the server's intention to open a WebSocket connection. Bu özellikler handshake sürecinin güvenli ve güvenilir olmasını sağlar ve verimli gerçek zamanlı iletişim için zemin hazırlar. ### Linux konsolu `websocat` kullanarak bir websocket ile ham bağlantı kurabilirsiniz. ```bash websocat --insecure wss://10.10.10.10:8000 -v ``` Veya bir websocat sunucusu oluşturmak için: ```bash websocat -s 0.0.0.0:8000 #Listen in port 8000 ``` ### MitM websocket bağlantıları Eğer istemcilerin mevcut yerel ağınızdan bir **HTTP websocket**e bağlı olduğunu tespit ederseniz, istemci ile sunucu arasında bir MitM saldırısı gerçekleştirmek için bir [ARP Spoofing Attack ](../generic-methodologies-and-resources/pentesting-network/index.html#arp-spoofing) deneyebilirsiniz.\ İstemci size bağlanmaya çalışırken şu araçları kullanabilirsiniz: ```bash websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v ``` ### Websockets keşfi Websockets üzerinde bilinen **vulnerabilities**'ları otomatik olarak keşfetmek, fingerprint almak ve aramak için **araç** [**https://github.com/PalindromeLabs/STEWS**](https://github.com/PalindromeLabs/STEWS) kullanabilirsiniz. ### Websocket Debug araçları - **Burp Suite** MitM websockets iletişimini, normal HTTP iletişimine yaptığına çok benzer bir şekilde destekler. - The [**socketsleuth**](https://github.com/snyk/socketsleuth) **Burp Suite extension** Burp içinde Websocket iletişimlerini daha iyi yönetmenizi sağlar; **history**'yi görme, **interception rules** ayarlama, **match and replace** kuralları kullanma, **Intruder** ve **AutoRepeater** kullanma gibi imkanlar sunar. - [**WSSiP**](https://github.com/nccgroup/wssip)**:** Short for "**WebSocket/Socket.io Proxy**", Node.js ile yazılmış bu araç, client ve server arasındaki tüm WebSocket ve Socket.IO iletişimlerini görüntülemek ve mesajları **capture, intercept, send custom** etmek için bir kullanıcı arayüzü sağlar. - [**wsrepl**](https://github.com/doyensec/wsrepl) pentesting için özel olarak tasarlanmış bir **interactive websocket REPL**'dir. **incoming websocket messages and sending new ones**'ı gözlemlemek ve yeni mesajlar göndermek için bir arayüz sağlar; bu iletişimi **automating** etmek için kullanımı kolay bir framework içerir. - [**https://websocketking.com/**](https://websocketking.com/) **diğer web'lerle iletişim kurmak için bir web** sağlayan ve **websockets** kullanan bir web aracıdır. - [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) diğer iletişim/protokol türleri arasında, **websockets** kullanarak diğer web'lerle iletişim kurmak için bir **web** sağlar. ## Decrypting Websocket - [https://github.com/Anof-cyber/PyCript](https://github.com/Anof-cyber/PyCript) - [https://github.com/Anof-cyber/PyCript-WebSocket/](https://github.com/Anof-cyber/PyCript-WebSocket/) ## Websocket Lab [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course) içinde websockets kullanan bir web başlatmak için örnek kod bulunur ve [**this post**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/) içinde bir açıklama bulabilirsiniz. ## Websocket Fuzzing Burp uzantısı [**Backslash Powered Scanner**](https://github.com/PortSwigger/backslash-powered-scanner) artık WebSocket mesajlarını da fuzz etmeye izin veriyor. Bu konuda daha fazla bilgiyi [**here**](https://arete06.com/posts/fuzzing-ws/#adding-websocket-support-to-backslash-powered-scanner) adresinde bulabilirsiniz. ### WebSocket Turbo Intruder (Burp extension) PortSwigger'ın WebSocket Turbo Intruder'ı Turbo Intruder–tarzı Python scripting ve yüksek hızda fuzzing'i WebSockets'e getirir. BApp Store'dan veya kaynaktan yükleyin. İki bileşenden oluşur: - Turbo Intruder: custom engines kullanarak tek bir WS endpoint'ine yüksek hacimli mesaj gönderimi. - HTTP Middleware: yerel bir HTTP endpoint'i açar ve gövdeleri persistent bir bağlantı üzerinden WS mesajları olarak iletir, böylece herhangi bir HTTP‑tabanlı scanner WS backend'lerini test edebilir. Bir WS endpoint'ini fuzz etmek ve ilgili yanıtları filtrelemek için temel script yapısı: ```python 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) ``` Tek bir mesaj birden fazla yanıt tetiklediğinde gürültüyü azaltmak için `@MatchRegex(...)` gibi dekoratörler kullanın. ### HTTP arkasında WS Köprüsü (HTTP Middleware) Sürekli bir WS bağlantısını sarın ve HTTP gövdelerini WS mesajları olarak ileterek HTTP tarama araçlarıyla otomatik testler yapın: ```python 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) ``` Sonra HTTP'yi yerel olarak gönder; body WS mesajı olarak iletilir: ```http POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1 Host: 127.0.0.1:9000 Content-Length: 16 {"message":"hi"} ``` Bu, WS backend'lerini kontrol etmenizi ve "ilginç" olaylar (örn. SQLi hataları, auth bypass, command injection davranışı) için filtreleme yapmanızı sağlar. ### Socket.IO handling (handshake, heartbeats, events) Socket.IO, WS'nin üzerine kendi çerçevelemesini ekler. Zorunlu sorgu parametresi `EIO` (örn. `EIO=4`) ile tespit edin. Oturumu Ping (`2`) ve Pong (`3`) ile canlı tutun ve konuşmayı `"40"` ile başlatın; ardından `42["message","hello"]` gibi olaylar gönderin. Intruder example: ```python 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 adaptör varyantı: ```python 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 aracılığıyla server-side prototype pollution tespiti PortSwigger’ın güvenli tespit tekniğini takip ederek, Express iç yapılarını şu gibi bir payload göndererek kirletmeyi deneyin: ```json {"__proto__":{"initialPacket":"Polluted"}} ``` Eğer selamlaşmalar veya davranış değişiyorsa (ör. echo içinde "Polluted" görünüyorsa), muhtemelen server-side prototypes kirlendi. Etki, ulaşılabilir sinks'e bağlıdır; Node.js prototype pollution bölümündeki gadgets ile korelasyon kurun. Bakın: - Check [NodeJS – __proto__ & prototype Pollution](deserialization/nodejs-proto-prototype-pollution/README.md) for sinks/gadgets and chaining ideas. ### WebSocket race conditions with Turbo Intruder Varsayılan engine mesajları tek bir connection üzerinde batch'ler (büyük throughput, yarışlar için zayıf). Paralel olarak mantık yarışlarını tetiklemek (double‑spend, token reuse, state desync) için birden fazla WS connection oluşturmak ve payloadları paralel ateşlemek üzere THREADED engine'i kullanın. Örnek script ile başlayın ve `config()` içinde concurrency'i ayarlayın. - Learn methodology and alternatives in [Race Condition](race-condition.md) (see “RC in WebSockets”). ### WebSocket DoS: malformed frame “Ping of Death” Header'ı büyük bir payload length olarak beyan eden fakat body göndermeyen WS frame'leri oluşturun. Bazı WS server'ları length'e güvenip buffer ön‑ayırır; bunu `Integer.MAX_VALUE` civarına ayarlamak Out‑Of‑Memory ve uzaktan yetkisiz DoS'e yol açabilir. Örnek script'e bakın. ### CLI and debugging - Headless fuzzing: `java -jar WebSocketFuzzer-.jar ` - WS Logger'ı etkinleştirerek mesajları internal IDs ile yakalayın ve korelasyon kurun. - Karmaşık adapter'larda mesaj ID işleme davranışını ince ayarlamak için `Connection` üzerinde `inc*`/`dec*` helper'larını kullanın. - `@PingPong`/`@Pong` gibi dekoratörler ve `isInteresting()` gibi helper'lar gürültüyü azaltır ve oturumları canlı tutar. ### Operational safety Yüksek hızlı WS fuzzing, çok sayıda connection açabilir ve saniyede binlerce mesaj gönderebilir. Malformed frame'ler ve yüksek hızlar gerçek DoS'a neden olabilir. Yalnızca izin verilen yerlerde kullanın. ## Cross-site WebSocket hijacking (CSWSH) Cross-site WebSocket hijacking, diğer adıyla cross-origin WebSocket hijacking, WebSocket handshakes'i etkileyen özel bir [Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md) vakası olarak tanımlanır. Bu zafiyet, WebSocket handshakes'in yalnızca HTTP cookies ile kimlik doğrulaması yaptığı ve CSRF token'ları veya benzeri güvenlik önlemleri kullanılmadığı durumlarda ortaya çıkar. Saldırganlar bunu, savunmasız uygulamaya cross-site WebSocket bağlantısı başlatan bir kötücül web sayfası barındırarak suistimal edebilir. Sonuç olarak, bu bağlantı uygulama ile kurbanın oturumunun bir parçası olarak değerlendirilir; bu, oturum yönetim mekanizmasında CSRF koruması eksikliğinin suistimal edilmesidir. Bu saldırının işe yaraması için gereksinimler şunlardır: - websocket authentication must be cookie based - Cookie'nin saldırganın sunucusundan erişilebilir olması gerekir (genellikle bu **`SameSite=None`** anlamına gelir) ve Firefox'ta **Firefox Total Cookie Protection** etkin olmamalı ve Chrome'da **blocked third-party cookies** engellenmemiş olmalıdır. - websocket server bağlantının origin'ini kontrol etmemeli (veya bu bypass edilebilir olmalı) Ayrıca: - Eğer authentication localhost veya yerel ağ gibi lokal bir bağlantıya dayanıyorsa, mevcut herhangi bir koruma bunu yasaklamadığı için saldırı **mümkün olacaktır** (daha fazla bilgi için bakın: [more info here](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/)) ### Simple Attack websocket connection kurulduğunda cookie'nin server'a gönderildiğini unutmayın. Server, gönderilen cookie'ye dayanarak her bir specific user'ı onun websocket session'ı ile ilişkilendirmek için bunu kullanıyor olabilir. Örneğin, eğer websocket server bir kullanıcıya ait konuşma geçmişini bir msg ile "**READY**" gönderildiğinde geri döndürüyor ise, bağlantıyı kuran basit bir XSS (cookie, victim user'ı yetkilendirmek için otomatik olarak gönderilecektir) "**READY**" göndererek konuşma geçmişini elde edebilecektir. ```html ``` ### Cross Origin + Cookie with a different subdomain In this blog post [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) saldırgan, web socket iletişiminin gerçekleştiği domain'in bir **subdomain**inde **execute arbitrary Javascript in a subdomain** çalıştırmayı başardı. Çünkü orası bir **subdomain** olduğu için, **cookie** was being **sent**, ve çünkü **Websocket didn't check the Origin properly**, onunla iletişim kurulup **steal tokens from it** mümkün oldu. ### Stealing data from user Taklit etmek istediğiniz web uygulamasını (.html files for example) kopyalayın ve websocket iletişiminin gerçekleştiği script içinde şu kodu ekleyin: ```javascript //This is the script tag to load the websocket hooker ; //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