But, from a security standpoint there are many things to consider when implementing WebSockets in your next project. I don't call them vulnerabilities - but they will most likely create a vulnerability when not dealt with correctly. In this post I describe all these aspects and release socket_io_client - tool for testing & exploiting WebSockets servers.
For example: Socket.IO, the most popular WebSockets server I encountered, in it's short history has used at least 2 incompatible message formats and 2 months ago it could be crashed with trivial payload (it's now fixed). And you need to write an application for Socket.IO with your own invented protocol.
As an example, Socket.IO still handles old handshake protocol for backwards compatibility. While this is understandable from user's perspective, basically it's a rarely tested branch of code that allows attackers to skip some of the security checks introduced in handshake 76 for a reason.
By default, Socket.IO allows all origins, which means that you could establish a connection from any domain. Use origins config parameter to narrow that.
You could also use my prepared payloads like so:
Auth & auth
If the resources are not public, you need to handle authentication & authorization by yourself - the protocol gives you nothing by default (apart from cookies & HTTP Auth, which have some issues themselves).Don't trust the client
Server cannot blindly trust the client. Your application-level protocol should be bullet-proof as the client can be hijacked and/or spoofed. It's best to assume that your protocol will be fuzzed by someone in the future. You need to handle:- data format issues
- charset & encoding issues
- linebreak issues
- logging
- denial of service attacks
For example: Socket.IO, the most popular WebSockets server I encountered, in it's short history has used at least 2 incompatible message formats and 2 months ago it could be crashed with trivial payload (it's now fixed). And you need to write an application for Socket.IO with your own invented protocol.
It's beta time!
WebSockets protocol is evolving - handshake 76 is currently used in browsers, but the standard will change in the next few months - browsers and WebSocket servers need to keep up.As an example, Socket.IO still handles old handshake protocol for backwards compatibility. While this is understandable from user's perspective, basically it's a rarely tested branch of code that allows attackers to skip some of the security checks introduced in handshake 76 for a reason.
Plaintext
The communications in ws:// protocol in handled in plaintext, so consider using only it's encrypted wss:// version. We don't need another Firesheep in two years. With SSL, you protect the clients from connecting to a spoofed server and you're not giving the plaintext version of your conversation to anyone listening.Check the Origin
Unless you want to speak with the whole world, validate the Origin of your clients.By default, Socket.IO allows all origins, which means that you could establish a connection from any domain. Use origins config parameter to narrow that.
XSS can hijack the client
If the client website has a XSS flaw, it has access to your connection and it can:- log all messages, both sent and received
- DoS the server
- send arbitrary messages
It's not only browsers
What is important - don't assume the WebSockets client is a browser, with it's Same Origin Policy, cookies, Javascript engine, Origin headers etc. It can be anything, especially if the attacker is determined. Don't take my word for it and check for yourself - I wrote a simple malicious Socket.IO client in Python. It can:- Handshake with a Socket.IO server
- Ignore all Origin restrictions
- Transparently handle all socket.io heartbeats
- Send arbitrary messages - from a prompt or an input file
- Messages could be raw or properly formatted according to socket.io protocol
- Receive/log all server messages
- Connect (with Chrome or other browser supporting websockets) to http://vuln.nodester.com/chat.html
- Run the command line client
./socket_io_client.py vuln.nodester.com 80
- Start conversation
- Try to inject XSS from the command line client
You could also use my prepared payloads like so:
./socket_io_client.py vuln.nodester.com 80 < payloads.txtOr save all server reponses like so:
./socket_io_client.py vuln.nodester.com 80 > output.txt
Just watch this Youtube video for a quick demo:
Socket_io_client is freely downloadable from github.
1 comment:
Nice post! The best point in my oppinion is, that you point out, that the developer must assume, that the protocol will be fuzzed in the future and hence always validate the client input.
Thankyou for writing this!
Post a Comment