Distributed Verification of SSL Certificates
Securing the (not so) Secure Socket Layer (SSSL)
Every security researcher faces the following well-known paradox early on in their career: in order to rely on the security of our SSL channel, we must verify the target server’s SSL certificate; in order to do so, we must first rely on the certificate authority (‘CA’). It might have all made sense in the early days of the internet, when these ‘CA’s’ were a handful of known corporates, but in our current reality where modern browsers support hundreds of CA’s, it is becoming increasingly difficult to simply trust the mechanism. In this article (and the attached POC code) I’ll present an alternative approach to certificate verification that attempts to overcome these difficulties.
(tl;dr: check out the POC code for quick use)
Wait, is my communication really not secure?!
The first question we want to answer is whether we face a real problem — i.e. are there really attacks exploiting the current SSL verification issue? Unfortunately, the answer is yes, yes indeed. Even if you ignore the possibility that the CA itself might be malicious, disregard the reality that government agencies probably hold root CA certificates themselves, or even if you are simply unaware of how incredibly unprofessional some CA’s tend to be, it is clear that malicious attackers have managed to lay their hands on root CA certificates in the past.
What this all means is that when it comes to the modern-day internet, financed, resourceful attackers can launch Man-In-The-Middle attacks against SSL protected websites by issuing fake, ‘valid’ certificates. This is the problem that we attempt to solve.
Past work and fix attempts
Over the years there have been several attempts to overcome the CA issue. Public Key Pinning, for example, was developed exactly for this purpose. However, due mainly to complexity and overheads, the idea didn’t stick and is not widely used. An interesting idea that is causing some buzz is the use of blockchain for SSL, however it is not exactly clear whether, or how, this will become a reality.
Komodo’s approach: Distributed Certificate Verification
The idea is simple and generally derives from the notion that you can cheat someone for some time, but cannot cheat everyone all of the time. In technical terms, it is feasible to alter the certificate for one victim (or let’s say one communication channel, or even one country), but unfeasible to alter the certificates for everyone coming from different internet providers and different GEO locations (unless you are in control of the target domain, in which case it is pointless).
Hence I propose the following algorithm for certificate verification:
- The user accesses a domain and receives the server’s certificate.
- The user then asks the ‘crowd’ if the certificate is valid.
- Next, different members of the ‘crowd’ (‘validators’) access the same domain, receive the certificate, and send it to the user.
- The user now compares the certificate with those received by the crowd. If the certificates match, it is valid (as we said, you cannot cheat everyone all the time). No CA is needed.
The crowd — isn’t it just another CA?
The whole point of the solution is that the client does not have to trust any ‘authority.’ In that sense, the ‘crowd’ must be an open network where anyone can join.
An added value for the above scenario, is that even domain owners can check if their clients are being targeted by simply asking the ‘crowd’ what certificate they receive, and verifying that this is indeed the certificate the owner is using.
Ah, but what if I serve more than one certificate…?
Some sites do offer different (legitimate) certificate to different users based on GEO location, browser version, and other criteria. To deal with this issue, the DHT must be quite varied itself and consist of validators from different localities. The client-side will also need to be adaptable, access a large number of validators, and determine what minimal number of ‘correct’ verifications are acceptable.
Following the above algorithm, I’ve created the following model for implementation. It comprises two parts: a Distributed Hash Table (DHT) that serves as the ‘crowd;’ and a client-side:
- DHT network:
This is the network of validators. Each validator will watch for incoming requests to retrieve a given domain certificate fingerprint. The validators will also be connected to each another, holding each other’s fingerprints on a DHT. The DHT must freely allow new validators to join to ensure that no authority controls the network. It will also be the DHT’s responsibility to identify ‘malicious’ validators (i.e. lying validators) and remove them from the DHT.
Ideally, the verification will be built into the browser itself. The client-side has several duties:
- Maintain a list of validators (their IP and their certificate), and periodically extend it (retrieve more validators from the DHT).
- For every SSL request, randomly pick a few validators and ask them to verify a given domain.
- If enough validators receive the same certificate, they will either allow the SSL communication, or deny it.
I’ve developed a rough POC based on the above. The source code is available for anyone to use, extend, or correct. Currently, the client-side is developed as a separate proxy, and not integrated into the browser itself, and only uses a pre-configured list of validators. Hopefully, with the help of the community, we can extend and improve the current development and create a more robust solution.
Zohar Shachar, tech lead