Do you check HTTPS certificates in your API clients?
I was reading some blogs this weekend about how HTTPS works and stuff. I never actually looked into that before, just kinda believed it just works. But now, as I understand a little bit more about it, I’m starting to wonder: are my applications, which are using HTTPS APIs, really safe?
It seems that HTTPS works like this:
- As soon as the connection is established, the server sends its SSL-certificate.
- The certificate contains a server’s public key and an “issuer’s statement” about this key, namely that this key is actually a valid key. The issuer is another party, which is to be trusted.
- The clients trusts only a number of issuers it knows. For example, who do browsers trust:
All browsers use a ‘certificate store’ which contains the list of trusted root CAs.
The certificate store can either be provided by the OS, or by the browser.
On Windows, Chrome and IE use the operating-system provided certificate store. So they have the same points of trust. However, this means that the trust list is governed by the OS vendor, not the browser. I’m not sure how often this list is updated for Windows XP, which is still used by 50% of the world’s internet users.
On Mac, Chrome and Safari use the operating system provided store.
On Linux, there is no operating system provided certificate store, so each browser maintains its own certificate store, with its own set of roots.
Firefox, on all platforms (I believe, I might be wrong on this) uses its own certificate store, independent of the operating system store.
Finally, on mobile devices, everyone has their own certificate store. I’d hate to guess at how many there are or how often they are updated.
If the issuer is not in the list, the browser ask the issuer for their certificate, and decides if it trusts the next issuer in the chain. Lather, rinse, repeat.
Okay, so for browsers and web pages HTTPS totally makes sense. But what about APIs? APIs are not (mostly) used by browsers, they’re used by programming languages. For example, I have dozens of web projects, mostly written in Python, mostly using APIs. They are deployed on Linux, which does not have its system-wide ‘certificate-store’ (see above). Oh. So, maybe Python has its store?
Warning This HTTPSConnection class does not do any verification of the server’s certificate.
As I googled, Ruby has the ability to set its store up. Node.js seem to have its ability only since 0.7:
I needed to upgrade to v0.7.8 (although any v0.7 should be fine) where the rejectUnauthorized functionality has been added to https.get
I haven’t done much research, but I have some experience as a software developer, and I can tell you what I don’t remember to be forced or even reminded to set up my certificate store. I didn’t even know anything about that. I don’t think I’m alone in that, so I’m trying to panic.
Okay. So now we have the whole security system set up, but API users (at least some of them, if Python is the only offender) does not do that’s necessary to protect themselves. That sound frightening.
(The other possibility is just that I don’t understand what’s going on and everything is fine. I can expect that from myself.)
Everyone has set up some google DNS servers to their local systems. But do people even know whose DNS is on their servers? Are they sure about
/etc/hosts file not being hacked? Or something like that? You know what - it can probably be hard to distinguish a phishing site in the browser for your parents, but your app is not just unexperienced, it’s dumb. Someone substitues its API for the API you’re using, and you’ll never know.
What am I proposing?
- API maintainers, put a big fat warning what every user of your API should check your certificate. Add a link to that very certificate so user can add it to his certificate store without any hesitation.
- API libraries maintainers, distribute valid certificates for the API servers as a part of the library. Check against this certificate by default. Tell user that he can rest assured, and live up to that promise.
- HTTPS libraries/utilites maintainers, check for certificate by default. Educate users about what the certificate store is. Add a really simple option to use some good certificate list, so they can do that with minimum work.
- Developers, check if you’re using only HTTPS versions of APIs. Check if your application is checking the certificate. Write a unit-test which overwrites
/etc/hostsand tries to do something evil. Be scared, but determined.
Please send your comments, ideas, rants and job offers at email@example.com.
Made with Nginx, Jekyll, Git, EC2 and Emacs.