DANE isn't a solution#
Yesterday, I described how to setup DANE in order to verify HTTPS keys through DNSSEC. I also noted a very important caveat: no one supports it and both Mozilla and Google are unlikely to ever support it. So we can't expect any security gain from implementing DANE in the real world.
Let's be fair: DNSSEC is no panacea. Browser vendors aren't ignoring it out of spite. They are choosing to not implement it for solid technical and social reasons.
Wait, what's the problem, again?#
Let's take a step back and look at why we wanted to use DANE in the first place. The problem is that the HTTPS security model is based on certificate authorities. Your browser has a list of certificate authorities that it trusts and to run a HTTPS site, you ask one (or more) of them to sign your server's public key asserting that your server really is the right one for your domain(s). The catch is that any certificate authority can make assertions about any domain and there's a lot of certificate authorities, many of which are suspected to be under the influence of various governments. This means that you are not just relying on the security of the certificate authority that you choose: you are relying on the security of every single certificate authority in the world. In short, the HTTPS security model is broken.
Key pininng#
If the real problem is the fact that any certificate authority could sign a new key for your domain without your permission. DANE fixes this one way by requiring the key to match the one found via DNS. HTTPS public key pinning solves it another way: every request includes a list of public keys which are valid for that domain. The first request a client makes is still relying on the certificate authority system, but as long as there is no active attack on that connection, for future connections, the client knows to only trust keys it was told about before.
The server sends a Public-Key-Pins
HTTP header. For example, this blog
currently sends
public-key-pins:
pin-sha256="K56b1Qw1QUkhjDDVnwAJBY8vB0q+vbF0rF6rlds5/I4=";
pin-sha256="SaVSDCTwbkUhdDA0Spixx4It8MA1edQJ0wUqvJp4ifU=";
max-age=5184000; includeSubDomains
The pin-sha256
sections are hashes of public keys which are allowed to
be used for this server. While this header is valid (5184000 seconds=60
days), the client is supposed to refuse any connections that do not
use one of those public keys somewhere in the certificate chain. That
is, the pinned key could be a certificate authority's key, which would
fix the problem of trusting every certificate authority. This server's
setup pins the actual server's key which means that the trust on the
certificate authority is entirely removed, but complicates matters if
the server's key is compromised.
Problems with key pinning#
What happens if a key is compromised and needs to be revoked? Naturally, we immediately stop using that key and remove it from the list of pinned keys. There's some set of clients that still have it in their list of pinned keys until the connect to the real server, but actually revoking keys is a separate problem handled by separate protocols.
There's the bigger problem of how those clients are going to know about the new key. If we pin keys for 60 days as in the example above, then clients need to be told about the new key 60 days before the current key is compromised. Which means that the pin has to include a backup key, and our key management must ensure the backup key will not be compromised at the same time the active key is. For example, if our threat model is an attacker gains root access on the server and is able to read the private key, then that backup key better not be on the server or any system the server has access to.
But wait, what if the reason for the key change is a protocol break (admittedly unlikely for RSA+SHA-2), and suddenly our current and backup SHA-256-signed 2048-bit RSA keys are both no longer considered secure and we need to transition to a new keysize/algorithm that we were not aware of a month ago? Yeah, I don't have an answer either. Although, admittedly, in this case, pins are probably not your biggest problem as that would likely invalidate many trusted certificate authorities' certificates as well.
We could try to mitigate the outage caused by a botched key transition
by limiting the max-age
in the Public-Key-Pins
header, but that's a
trade-off against security if the client accesses the website rarely.
For example, if max-age
is one day and the client visits the website
weekly, then pinning provides very limited additional security because
the pin will always expire before the client visits the site again.
DANE lacks these problems due to having a much shorter expiry time on its information and due to not relying on the information being stored by the client from a previous visit. Of course, as linked to above, DANE has other issues, and HTTP public key pinning is actually implemented in Firefox and Chrome so it can be used today.
Putting it all together#
To actually setup TLS on your web server, I recommend this comprehensive blog post and these step-by-step instructions for getting a free certificate from StartSSL. If that post has insufficient sarcasm for your needs, I recommend these instructions instead. You can verify that your setup is valid using Qualys SSL Labs's SSL Server Test. As described in this blog post, you can verify your pinning settings using Chrome (or Chromium) by looking at chrome://net-internals/#hsts.
Comments
Have something to add? Post a comment by sending an email to comments@aweirdimagination.net. You may use Markdown for formatting.
There are no comments yet.