2

I have seen many implementations of certificate pinning for HTTPS connections originated from client-side apps running on mobile devices using native libraries and plugins.

I would like to know whether such certificate pinning implementations are available for websockets. In the client side (say a mobile device or web browser), can we actually implement certificate pinning for websockets?

If such approach is available, it would be really nice to have an explanation, ideally with links to resources/ articles/ code snippets/ libraries.

  • 1
    I've never experimented so I'm not 100% sure, but websockets are just an upgraded HTTP connection. In fact, they literally start with an HTTP connection with an extra UPGRADE header or two. Since it starts life as a standard HTTPS connection, I expect that websockets will respect certificate pinning just like any other connection in the browser. – Conor Mancone Jul 12 at 14:39
  • Theoretically, it's a huge yes, but unfortunately, I haven't seen any such implementation or any clue on that. My current observation is that certificate pinning cannot be implemented for websockets of the web apps due to protocol limitations (still I'm evaluating mobile apps, so cannot make any comment about them). – Thilina Ashen Gamage Jul 13 at 3:53
4

Securing secure websockets

Secure Websockets start life as a standard HTTPS request and only connect if a valid HTTPS connection can be established with the server. As a result, websockets will automatically respect any public key pinning, strict transport policies, etc, which the server sets in the response headers when the client first attempts to establish a websocket connection.

Therefore, for web browsers, it's simply a matter of providing a standard Public-Key-Pins header. I couldn't say how it works for mobile clients. It may vary from platform-to-platform, but it wouldn't surprise me if many simply follow the same security headers as browsers.

A Caveat

Note though that you may not want to actually bother with public key pinning, as it seems that support for it is waning or even already gone. The trouble with public key pinning is that it is one of the only security measures that can literally lock people out of your website in a way that cannot be fixed, as has happened to businesses.

Understanding Websockets

You linked to an article which discusses the fact that you cannot set request/response headers over a websocket connection. This is true, but it also doesn't change my above answer. The article is actually talking about something different, although it is a common source of misunderstanding (I ran into the same question myself when I enabled authentication on my first websocket server and client). To explain though it's important to understand the lifecycle of a websocket request:

  1. The client sends a standard HTTP request to the server with a special UPGRADE header.
  2. The server sees the header and sends a response letting the client know it accepts the request to upgrade to a new protocol
  3. Having been officially upgraded, the client and server both keep the original TCP connection open and send data back and forth through it directly as needed

Your article is referring to step 3 of this process. Once the websocket connection has been established, you can no longer send request or response headers because there are no longer HTTP requests being sent. Instead the client and server exchange data directly over the TCP connection in whatever format they want.

However, the initial attempt to establish the websocket connection still happens over a standard HTTP request and requires a standard HTTP request to be properly established. As a result, the browser should still respect any response headers sent back down by the websocket server when initially establishing a connection. And indeed, the server can send additional headers back down at that phase of the process.

  • 1
    @ThilinaAshenGamage That link is talking about the client sending headers to the server when sending messages. Once the connection is established, there is no longer an exchange of HTTP requests, and therefore neither server nor client can send headers to eachother. However, that doesn't change the fact that a standard HTTP request is still used to establish the connection, and that standard security headers will be respected at that point. I'll edit my answer when I have a chance. – Conor Mancone Jul 13 at 10:15
  • 1
    @ThilinaAshenGamage Have you tried it or setup public key pinning on a standard HTTPS request first? Honestly, I'm suspicious that you might be a bit confused about how to implement it in the first place. In particular, you mention that there is no way to "intercept the HTTP headers" but when implementing public key pinning you don't have to anyway - it is automatically enforced by the browser. There's no need to get it out of the javascript client API in the first place. In browsers, it's all completely transparent and handled automatically by the client. – Conor Mancone Jul 13 at 23:07
  • 1
    @ThilinaAshenGamage I made some attempts to test this myself to find out for sure, but unfortunately had a lot of trouble doing so, in part because it appears that google chrome has deprecated parts of public key pinning, and also ignores it for self-signed certs even when the root certificate is imported into the browser (which is all I had on hand). All the more reason why I think you should probably just not bother. Google is leading an initiative to take things in the direction of "Certificate Transparency". At this point in time I'd just aim to be an early adopter of that program. – Conor Mancone Jul 13 at 23:10
  • 1
    @ThilinaAshenGamage Yeah, those are all in reference to mobile clients, for which the situation can be different. I've only worked with web browsers, so I can't make any promises. On the bright side though, when doing it for mobile clients you don't run the risk of accidentally disabling access to your site (since you have to handle it yourself instead of the browser doing it automatically). In short, mobile clients can have a different security "architecture". – Conor Mancone Jul 15 at 12:08
  • 1
    @ThilinaAshenGamage If the client you are using doesn't support it, then it may be that you'll have to find a lower-level API to enable the support yourself. For instance, for the websocket servers I run, I use a popular package in my language. However, I had some more complicated use cases and so had to dig through all the source code for the package. As a result I can tell you that in this case, the package is using the lowest level network integration possible, as it is actually running a raw TCP socket server and implements the initial HTTP response and websocket communication itself. – Conor Mancone Jul 15 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.