Posted: September 17, 2017 at 12:21 PM
Or how security continues to suck because: It’s Hard and Someone Else’s Problem™¶
For a personal project, I’ve decided to use WAMP to move some events and messages around between different components. I decided on the AutoBahn libraries and Crossbar.io as the router. I was already somewhat familiar w/ AutoBahn from previous work, and the Crossbar.io router seems to just work. As a security person, I decided to evaluate how to make things as secure as possible.
First off, my projects must be both authenticated and encrypted. WAMP does not appear to have it’s own encryption layer, but it does have it’s own authentication layer. You really don’t want to have to trust two different authentication layersThe encryption layer must be authenticated, otherwise any attacker could MiTM the connection. Most uses of TLS make use of the CA system for authentication (which has serious issues in trust), and most web apps add their own authentication layer on top of it (not using Basic Auth, or other scheme). The issues w/ this is that if there is no binding between the two layers, the lower layer (application layer) cannot be sure that the upper layer has not been compromised., so being able to use TLS Channel Bindings would be an improvement. This would ensure that a strong authentication method in WAMP would ensure that the channel is properly encrypted. I received confirmation from the Crossbar.io team that it was present.
Autobahn and Crossbar.io supports a number of different authentication schemes. As I plan on putting this behind a reverse proxy (which I realize will have it’s own issues w/ channel binding), I wanted the strongest security binding between my client and the server (and I’m a glutton for punishment for using unproven tech). The only one that satisfies this requirement is WAMP-Cryptosign.
After I got basic functionality working to make sure things would be workable w/ this framework, I decided to start working on the authentication piece. First problem I ran into was that the AutoBahn|JS library does not support TLS channel binding. There is a good reason the library doesn’t support it, and it’s for a very bad reason. There is no support in the browser WebSocket API to query the channel binding information necessary. The fact that WebSockets was standardized after Channel bindings were demonstrates that the people involved in standardizing the web do not take security seriously. As usual, they assume that security is not their problem and leaves it up to someone else to solve (or at another layer).
Disappointed that I wouldn’t be able to use channel bindings w/ the web client for this project (I still had the crappy CA authentication of TLS, so not all was lost), I moved forward w/ CryptoSign. As has been demonstrated many times, the only way to get security baked in, is to make it as easy as possible to use. I’ve been long familiar w/ Crypto Box by djb (and used by the Autobahn libraries), and also the noise protocol (which my friend Trevor created). Both of these have goals of making it simple to let developers include security in their projects and not mess it up, resulting in a broken system. As currently implemented, Autobahn’s CryptoSign is most definitely not easy to use.
Though the documentation is decent, some examples are not present
client_ssh_key.py for example from
WAMP-cryptosign Static Authentication).
helper class does not document how to make use of authentication. Though
the static authentication page has examples, they make you write quite
a bit of boiler plate.
Then even once you do that, you find out that the code doesn’t even work on Python 2.7 and have to fix it for them. Hopefully the pull request (PR) will not be ignored because of the failing CI tests, because the current CI tests are problems with their CI environment, and not the PR. For CI checks like this, it should only ding your PR on checks that are newly failing, and ignore any checks that were previously failing. This isn’t the first project that their CI environment was broken.
Even w/ the fixes in place, there is no documented method of extracting a public key from a generated ssh key. I will be adding a method to print this out.
If I (who knows cryptography decently) have to fix and spend hours making this work, it’s no wonder than everyone things that strong cryptography is hard. It is hard, but it shouldn’t be.