In light of recent widespread MiTM goings on with Superfish and Lenovo products, I dusted off an old technique introduced in the anti-spam communities several years ago that would have prevented this, and could more importantly put a giant dent in the capabilities of government sponsored SSL MiTM.
The Core Problem
The core of the problem with SSL is twofold; after all these years, thousands of Snowden documents, and more reason to distrust governments and be paranoid about hackers more than ever, we’re still putting an enormous amount of trust into certificate authorities to:
- Play by the rules according to their own verification policies and never be socially engineered
- Never honor any secret FISA court order to issue a certificate for a targeted organization
- Be secure enough to never be compromised, or to always know when they’ve been compromised
- Never hire any rogue employees who would issue false certificates
Not only are we putting an immense trust in our CAs, but we’re also putting even more trust into our own computers, and that the root certificates loaded into our trust store are actually trustworthy. Superfish proved that to not be the case, however Superfish has only done what we’ve been doing in the security community for years to conduct pen-tests: insert a rogue certificate into the trust store of a device. We’ve done this with iOS, OSX, Windows PCs, and virtually every other operating system as well in conducting pen-tests and security audits.
Sure, there is cert pinning, you say… however in most cases, when it comes to web browsers at least, cert pinning only pins your certificate to a trusted certificate authority. In the case of Superfish’s malware, cert pinning doesn’t appear to have prevented the interception of SSL traffic whatsoever. In fact, Superfish broke the root store so badly, that in some cases, self-signed certificates could even validate! In the case of CAs that have been compromised (either by an adversary, or via secret court orders), cert pinning can also be rendered ineffective, because it still primarily depends on trusting the CA and the root store.
We have existing solid means of validating the chain of trust, but SSL is still missing one core component, and that’s a means of validating with the (now trusted) host itself, to ensure that it thinks there’s nothing fishy about your connection. Relying on the trust store alone is why, after potentially tens of thousands of website visits, none of the web browsers thought to ask, “hey why am I seeing the same cert on every website I visit?”
Who to Trust
Reason would tell us that we can’t trust our certificate authorities and we can’t trust our own root store… at least 100%. These validation checks that we already do are very important, obviously, but in today’s world are only likely to catch the low hanging fruit. If a nation state wants to compel a certificate authority to quietly cut a cert, distribute a bogus root cert with an operating system, or even inject one into someone’s trust store through malware, then that little lock will still pop up in your browser, and you’ll be none the wiser.
In effect, the chain of trust today should work more like a blacklist, rather than a white list: it’s good in telling you that a certificate is bad, but we shouldn’t be relying on it anymore to be the authority that a cert is good.
When the chain of trust can no longer be 100% reliable, the next logical step is to not only validate the chain of trust, but also to validate with the target host itself – which is really validating ourselves and the validity of the SSL cert we’ve been handed. After validating a cert using existing methods to verify the host the best you can, wouldn’t it make sense to also go to the host (that would, in this case, already be trusted) to tell you with certainty that the cert you’re using doesn’t smell funny?
Sender Policy Framework
SPF (Sender Policy Framework) came out of the anti-spam movement. One of the benefits to being so old is that I remember when many of the techniques we use today were first introduced. Back in my hey-day in anti-spam, we used to hang out at the MIT Spam Conference every year, and toss around ideas (like SPF). SPF is an “out of band” technique designed to prevent spammers from spoofing legitimate domains. Lets say you’re a company for a minute, and you don’t want spammers spoofing email as if it came from your .com. If you want to tell the world that they should only accept mail with your domain from your own mail servers, you’d use SPF by advertising the list of your servers in a TXT record in your DNS. For example:
worldwidemail.ru. 13733 IN TXT "v=spf1 a mx ip4:188.8.131.52/2 ip4:184.108.40.206/2 ip4:220.127.116.11/2 ip4:18.104.22.168/2 -all"
The TXT record is publicly available and can be retrieved with a simple DNS query. For example, here’s part of Google’s SPF record:
Pestilence:~ jonz$ dig txt gmail.com ;; ANSWER SECTION: gmail.com. 60 IN TXT "v=spf1 redirect=_spf.google.com" Pestilence:~ jonz$ dig txt _spf.google.com ;; ANSWER SECTION: _spf.google.com. 168 IN TXT "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all" Pestilence:~ jonz$ dig txt _netblocks2.google.com ;; ANSWER SECTION: _netblocks2.google.com. 559 IN TXT "v=spf1 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all"
SPF won’t prevent a spammer from sending email spoofed with the company’s domain, but any mail servers that are SPF savvy will reject incoming mail that doesn’t match the sender policies for the domain listed in the From header of the message.
SPF… for SSL?
SPF is specifically designed for email, but the concept is pretty solid: using a secondary service (DNS) as a lightweight means to read information directly from the host you’re interested in connecting to (via SSL here). So how can SPF be used to help validate SSL? Well, when you connect to a server via SSL, there’s a certificate and key exchange taking place. If you are being MiTM’d, the certificate on the server is being swapped out for a third party’s certificate. If your root store has been compromised or (for arguments sake) a government has used something like a FISA order to obtain a certificate that will validate against your root store, then the certificate you think represents the website actually isn’t the certificate on the web server.
This is where CVF (Certificate Validation Framework) could help. If web browsers were to look for certificate validation data within the TXT record of the destination’s DNS records, they could obtain a hash of the certificate that the server is using; the website you’re visiting would effectively be advertising a hash of its own certificate so that any other certificate in the world, regardless of who’s signed it, would fail.
Here’s an example. When you connect to www.google.com using OpenSSL’s s_client command, you’ll see Google’s public certificate (and certificate chain)…
CONNECTED(00000003) depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA verify error:num=20:unable to get local issuer certificate --- Certificate chain 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com i:/C=US/O=Google Inc/CN=Google Internet Authority G2 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2 i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority --- Server certificate -----BEGIN CERTIFICATE----- MIIHgzCCBmugAwIBAgIIM0yeg6/uf0swDQYJKoZIhvcNAQEFBQ AwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx ... tUa2UA5ETydhoj3BcgHJoiP7m+GZABeyaFwtuf4fD2Dm8FtG== -----END CERTIFICATE----- subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
If you were to make a hash of the certificate only, you’d end up with d8e6ad1a68720b8737829597f314b7ebd25ad3eb5d063a210dec03cea9321e37. What if Google were to advertise that hash in a TXT record that conformed to a CVF standard? For example:
google.com. 3188 IN TXT "v=cvf1 sha256:d8e6ad1a68720b8737829597f 314b7ebd25ad3eb5d063a210dec03cea9321e37"
Or if you’re really paranoid, use sha512.
google.com. 3188 IN TXT "v=cvf1 sha512:9cd96ed78bf2083ce1036f9ba d5a31e694d713314414cc8c2c60a58b7116701aab58a947ddcb2911594193630 13fbcb8d3d50945593dce8025019345cd80ac90"
Alternatively, using the certificate fingerprint would work too.
google.com. 3188 IN TXT "v=cvf1 fingerprint:78:35:38:C6:0F:AD:A5:8E:81:D2:67:DA:2B:10:06:36:1C:C7:DA:8F"
Lets say your trust store has been compromised by Superfish. When your browser goes to visit Google, it would get Superfish’s certificate back. Since that cert is in your root store, you’d normally see a lock icon and be none-the-wiser that someone was eavesdropping in on your traffic. Using the CVF example above, however, if your browser was CVF-aware, the certificate Superfish would give to the browser would be its own, and the hashes wouldn’t line match. The browser would then fail SSL validation, where today’s browsers, unfortunately will validate it.
What About DNS Poisoning?
Of course, DNS can be poisoned or spoofed, just like anything else. The difference here is that MiTM attacks need to be covert in order to succeed, and spoofing the TXT record in DNS would make the attack publicly visible to entire networks, or possibly the entire Internet. This ups the ante considerably for both hackers and nation states: not only would they need to be able to compromise a CA in one way or another (or compromise the target’s trust store) in order for existing SSL validations to fail, but they’d also need to be able to conduct a long-term DNS attack without being detected, in order to compromise CVF. Once an MiTM attack is made publicly known, it becomes inert. Certificate revocations occur, and the attacker risks being exposed.
Why Not Try It?
This is only one idea, and I’m sure the Internet has many on how to solve the problem with both trust stores and certificate authorities. If companies started using this technique, however, to advertise their certificate’s hash, then it’s possible that browser or plugin-in authors might pick it up and start incorporating CVF-aware logic into their code. Even before that happens, publicly advertising the hash of the SSL certificates you’re using can be good for the general public; people in the security field can easily look these records up and validate that nothing fishy is going on. It becomes much easier to sound the alarm when a certificate mismatch becomes so publicly visible. Bots could even be easily written to validate this information on a large scale, from multiple networks, just like many websites already do to monitor other analytics for HTTP traffic.
If there is interest, I will be glad to write up a draft to mimic the popular SPF mechanism that already exists. As you can see, however, this kind of advertising can be done rather easily. If you are a large company interested in implementing this, please reach out to me and I’ll be glad to lend you my support.
Q Why hasn’t anyone done this already?
A Probably because there hasn’t been such an urgent need for host-direct validation of SSL until recently. Superfish certainly highlights the problem with trusting the root store. The domestic spying / Internet dragnet stories have only broken over the past couple of years. Our Internet was originally built around a trust model; unfortunately both governments and malware have demonstrated that the trust model can be broken. This is one fix that could help to identify certain types of attacks that are only recently beginning to happen (to our knowledge).
Q What about browsers that break the trust chain intentionally, like Chrome?
A From what I’ve read (thanks 0xabad1dea), the reason Chrome was susceptible to Superfish was because it bypasses its internal list of cert pins when custom root certs are added, possibly to allow for corporate intercepts. CVF obviously won’t fix broken browsers that intentionally bypass security mechanisms. CVF definitely can help browsers that are trying to be secure to do their job. CVF could also be implemented in SSL libraries to forcibly prevent verifiable mismatches from occurring, even in browsers that are intentionally breaking security.
Q What about DNS spoofing? DNS is pretty insecure, you know.
A DNS can certainly be attacked, just like any other service. OCSP is DDoS’d frequently as well, which has resulted in several SSL related issues. What’s great about this technique, however, is that a DNS attack is very visible, whereas certain types of attacks (such as compromising or compelling certificate authorities) are very low visibility. So if we can see that there’s an active DNS attack going on that looks like it may be related to obtaining CVF records, then the browser can warn the user; the online community would also be able to detect that something was up, which would bring attention to anyone looking to quietly slip in a rogue certificate somewhere.
Q What about preloading certificate pins, like some browser do?
A Some browsers preload lists of cert pins, so that they can further attempt to validate their SSL sessions. This could almost be looked at as a predecessor to a more standardized and publicly visible solution as CVF. The beauty in CVF is that it allows participating websites to help make the problem of key distribution a lot easier by creating an easy-to-read (both by humans and computers) hash of their cert publicly available by all (including people, browsers, and backend public services that can easily monitor DNS for changes to a cert). Preloading SSL pins is inherently good, except that it’s somewhat proprietary, the data is subject to change, and isn’t scalable enough to cover all of the smaller websites that aren’t on the radar (including new sites that pop up). Using CVF, a new site could come up overnight and instantly add this layer of SSL validation by advertising their cert hashes via TXT record.
Q You do know that this couldn’t possibly replace trusted root certs, right?
A Oh, definitely; you’d be crazy to try and implement this as a whitelisting mechanism. It only serves as a good way to establish a forged certificate. There’s a reason we have a root cert store on every computer, and validate through a certificate chain: DNS TXT records could be proxied just as easily as SSL certs. Where this technique can help to enhance existing techniques is in making the typically opaque cert exchange much more visible to the public eye, and gives the host the direct ability to invalidate any certs except their own. There would be a very publicly visible trace of a government or other attacker attempting to MiTM DNS, whereas today MiTMing certs is a very low visibility task.
Q Can you circumvent this?
A Of course, you can break anything. You’d have to proxy and break DNS, however, in order to circumvent this technique, and breaking DNS is has many visible consequences. Similarly, browsers can (and should) get smarter about detecting MiTM in all things (certs, dns, etc). Performing checks of control certs and txt records is one way the browser can ensure that it’s not getting tampered data back. Additionally ensuring that it’s not getting the same cert and/or txt record back every time, regardless of website, is some pretty basic logic that can and should be in browsers already.
What this technique offers is another layer of security that in most cases requires things to get very visible to the public in order to tamper.