Application

Pentesting Websockets

HTML5 has introduced many new powerful APIs, one of the more interesting components being websockets. These highlight a trend in web application development to remove or reduce the overhead of HTTP. Websockets are a direct TCP connection between the client browser and the webserver. For application components that require extremely low latency such as financial trading applications, real time chat, or even multiplayer games, websockets are an ideal way to remove any unnecessary overhead such as HTTP headers.

For ethical hackers these may present their own unique challenge; the first and most obvious is simply being able to identify a websocket. Many tools currently do not support websockets, and if not careful can go unnoticed. At the time of this writing, common tools such as Burp proxy simply drop the connection. While portswigger has acknowledged they plan to support websockets by the end of 2013, ZAP proxy is the only proxy that supports this.

Websockets use a URI that begins with either ws:// or wss:// and connect to port 80 or 443 respectively. Below shows the construction of the socket:

Game.connect('ws://' + window.location.host + '/examples/websocket/snake');

For this example we are looking at an example multiplayer snamke game which ships with Apache Tomcat. After the JavaScript is invoked we can see the browser start the websocket handshake:

GET http://192.168.17.133:8080/examples/websocket/snake HTTP/1.1
Host: 192.168.17.133:8080
Sec-WebSocket-Version: 13
Origin: http://192.168.17.133:8080
Sec-WebSocket-Key: 13mKTb9b4fVEyLnEy6Sbrg==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Content-length: 0

One of the first interesting things to take note of is the ‘Upgrade’ header. This was originally proposed for browsers to negotiate a higher version of HTTP (1.0 to 1.1), however is re-purposed for websockets. Below shows the server responds with a 101 status code:

HTTP/1.1 101 Switching Protocols
Server: Apache-Coyote/1.1
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: ARgpi5+ARVDt5ERTfpkib9/kTX4=
Date: Wed, 10 Jul 2013 09:42:23 GMT
Content-length: 0

This is the last HTTP exchange made before the websocket is opened. The handshake only exists so clients must identify themselves as a proper websocket client (and prevents non-websocket clients from being abused into interacting with the application), so the values seen are not as sensitive as one may think at first glance.

To actually start manipulating the websockets we will open up OWASP’s ZAP proxy and configure our browser as normal. ZAP has its own tab to interact with websockets, so we will using that view. One of the cool things about ZAP is the dropdown menu for each “channel”.

zad_channels

Once you have the appropriate channel highlighted you can replay an modify websocket payloads in either direction. As shown below we can change the coordinates with this to change the location and direction of the snake in the game. While this is a very basic example, it is the simple ability to modify the payloads which is the core of all websocket testing. Burp users will find this similar to the repeater function:

zad_replay

Now that we have the ability to view and manipulate websocket data, we are free to use this against the application. In addition to the obvious injection and logical vectors we normally test for there are a few other key items we will want to keep in mind:

  • Is authentication properly enforced on the websocket components?
  • Are timeouts enforced? can we still use the socket after we log out?
  • Is the socket encrypted? remember ws:// and wss://
  • Is any data leaked on an unauthenticated connection?