This article is Part 3 out of three in my series about SSL/TLS encryption. Part 1 covers the basics of well-known encryption concepts. Part 2 gives a brief introduction to OpenSSL and PKI. This part broaches the issue of PKI weakness and introduces two countermeasures.
First, I would like to introduce the term relying party. A relying party is a web browser, email client, chat application, etc., that is trying to validate an x.509 certificate. Most of the time, the relying party achieves that by checking whether a CA in its trust anchors signed the certificate.
[ You might also like: How to manage multiple SSH key pairs ]
Excursion: Protect your private key
As you may know from Part 1, the private key is the one you must protect. This starts with the creation, which should happen on a trustworthy machine.
Now you might ask: "What's a trustworthy machine?"
Well, an online service run by someone you don't know is certainly not trustworthy. You must never create your private key using some web service in your browser because you simply don't know if the service provider keeps a copy of the created key. To prevent that from happening, you could use an offline machine instead.
Store your private key only where you need it and keep it safe. A directory on some anonymous FTP server is certainly not a safe place. A network share where only privileged users have access to or a password manager allowing to store attachments is certainly a better place to put it.
In case you accidentally copied your unprotected private key to some network share or public Git repo, just drop it and create a new one. You cannot be certain that it has not been compromised. Even if you delete it immediately, you cannot be sure that some kind of snapshot mechanism has not already stored it.
What PKI is and how it works was discussed in Part 2 of this series. In case you don't know, read that part first.
In a nutshell, the whole reason that we deal with this certificate mess is that we want to help the relying party to ensure that it communicates with the correct server and not some fraud. So we get a certificate signed by some CA the relying party trusts, and we're all happy, right?
Well, we could be if there wasn't a serious design flaw in PKI.
There are several hundred CAs that have the trust of our relying party out there on the Internet. Some of these CAs even have Sub CAs capable of signing certificates and having the trust of the relying party. And all of these CAs can issue a certificate for any valid domain name.
So, in general, any CA could issue a certificate for your domain, and you wouldn't even know about it. This certificate could be used for man-in-the-middle attacks on your domain because the relying party would trust this certificate since it was signed by a trusted CA.
And this is not a theoretical threat. In March 2015, some unauthorized certificates issued by CNNIC used to decrypt traffic passing through the Great Firewall. In 2012, a security company admitted that they have issued at least one certificate to a private company that used it to spy on their employees. And back in 2011, a certificate authority company experienced a devastating hack where some of their signing certificates were stolen.
The three examples above show you what's wrong with PKI at its core. The design is flawed. So how to fix it? The following are two techniques that could help to mitigate the issue.
Certificate Authority Authorization (CAA)
From the abstract of DNS Certification Authority Authorization (CAA) Resource Record in RFC 8659: "The Certification Authority Authorization (CAA) DNS Resource Record allows a DNS domain name holder to specify one or more Certification Authorities (CAs) authorized to issue certificates for that domain name. CAA Resource Records allow a public CA to implement additional controls to reduce the risk of unintended certificate mis-issue."
Well, I couldn't have explained it any better. CAA enables domain name holders to specify which CAs are allowed to issue certificates for our domain, and the CAs themselves promise us to respect our CAA records. The RFC 8659 defines the following three properties:
- issue contains as value the domain of the CA, which is authorized by the CAA record to issue certificates for a certain domain.
- issuewild is basically the same as issue but for wildcard certificates. If no issuewild is set, the value from issue is used instead.
- iodef contains contact information to be used in case there are any issues regarding the CAA policy.
Let us look at the following example records:
example.com. IN CAA 0 issue "letsencrypt.org" example.com. IN CAA 0 iodef "mailto:firstname.lastname@example.org"
The first line from the example above means that only the CA Let's Encrypt would be allowed to issue certificates for any host under the domain example.com. Any other CA MUST NOT issue certificates for this domain. The second line gives you an email address you could contact in case of any problems.
Since DNS is hierarchically organized, the above CAA record applies to web.example.com as well as to host.web.example.com and host.sub.web.example.com. Let's look at another example:
example.com. IN CAA 0 issue "letsencrypt.org" example.com. IN CAA 0 iodef "mailto:email@example.com" sub.web.example.com IN CAA 0 issue "example-pki.org"
Here only the CA example-pki.org is allowed to issue certificates for, e.g., host.sub.web.example.com. The record in the third line overwrites the policy from example.com. I think you got the idea.
Of course, CAA resource records wouldn't prevent non-compliant CAs from issuing certificates for domains they don't have permission for. But they would risk being removed from embedded trust anchors, which would mean going out of business in most cases.
And there is still a chance that an authorized CA could mis-issue a certificate to someone who is not authorized to use it. Choose some CA of your trust and choose wisely.
As you see, CAA does not bring 100% security, but it's easy to implement and mitigates the risk of certificate mis-issuance.
Certificate Transparency (CT)
Certificate Transparency is "...an experimental protocol for publicly logging the existence of Transport Layer Security (TLS) certificates as they are issued or observed, in a manner that allows anyone to audit certificate authority (CA) activity and notice the issuance of suspect certificates as well as to audit the certificate logs themselves. The intent is that eventually, clients would refuse to honor certificates that do not appear in a log, effectively forcing CAs to add all issued certificates to the logs." (Abstract RFC 6962)
CT offers a form of accounting for TLS certificates and enables you to examine which CA-issued certs for your domain names. To do so, you could use services like Cert Spotter by sslmate, which is available as an on-premises version, too. I used to run the on-premises version on my virtual private server, but due to the log growth over the past two years, it seems impossible to crawl the logs from start to end. The job ran for weeks and didn't finish; it was aborted when I needed to restart my host to complete updates.
Today no CA is forced to add issued certs to CT logs, but the log growth suggests that many of them already add their certs. In my opinion, it's only a matter of time until major browsers start only to trust certs with a CT log entry and make them mandatory.
[ Get this free ebook: Managing your Kubernetes clusters for dummies. ]
The original design of the PKI is flawed and not very trustworthy anymore. With RFC 8659 and RFC 6962, two methods are offered to regain trust and help domain name holders keep track of who issued certificates for their domains.
So from now on, keep in mind to protect your private keys, set CAA resource records for your domains, and start monitoring CT logs.