HTTP Public Key Pinning is a very powerful standard that allows a host to instruct a browser to only accept certain public keys when communicating with it for a given period of time. Whilst HPKP can offer a lot of protection, it can also cause a lot of harm too.
I've covered HPKP quite a few times on my blog and I also use it myself. You can see that I get an A+ on my securityheaders.io scan and you can also analyse my policy in more detail on the https://report-uri.io analyser results. I use it because it offers a level of protection that I can't otherwise achieve. My policy tells the browser which public keys I have in my possession and that I will always use one of those keys when the browser visits me again. I have blogs with a lot more detail on HPKP, setting up HPKP and my HPKP Toolset to help you out. The problem with HPKP is that it can be quite a complex idea to get your head around and requires a perfect deployment otherwise things can go wrong.
Sadly there is a term for this and all it involves is a site making a potentially simple error. You enable HPKP, tell the browser which keys you will always use and then you lose those keys. They could be accidentally deleted, stolen in a hack or whatever, it doesn't matter. If you pin yourself to a set of keys and then no longer have the ability to use them, you're in big trouble! The most notable site I've come across that's done this is Smashing Magazine and they wrote about it in their article Be Afraid Of HTTP Public Key Pinning (HPKP).
This is another side effect of HPKP and it's a way to use it to cause harm. In a breach scenario an attacker would gain control of your site via a server compromise or a domain hijack and then enable these headers on your behalf. When your visitors go to your site they pick up the malicious HPKP header set by the bad guys. At some point you then fix the problem and take back control of your site except now, none of the browsers will connect because of the HPKP policy they picked up from the bad guys. I have more details on this in my blog on Using security features to do bad things.
I'm not alone in my view that HPKP can be dangerous and difficult, Ivan Ristic published an article on the Qualys blog titled Is HTTP Public Key Pinning Dead? with many of the same concerns. It's well worth a read and there are some ideas on how we can take the edge off HPKP and make it more friendly to use. Even the infamous Taylor Swift had something to say on the matter right before my publication of this article.
Fascinating thread from a leader in HTTPS ecosystem — providing HPKP capability to unvetted web developers was a mistake, in retrospect. https://t.co/qUjaXym7uT— SwiftOnSecurity (@SwiftOnSecurity) August 24, 2017
In the end the point will always remain that it's hard to deploy and easy to get wrong. When I think about the purpose of HPKP though, to protect the host against mis-issued certificates from a rogue or compromised CA, HPKP existed when we didn't have other mechanisms to help us with that.
CT is an excellent new requirement that will soon be placed on all newly issued certificates. For a browser to trust a certificate it will have to be logged in a series of public CT logs, open for anyone to see. You can read more details in my blog on Certificate Transparency but CT will solve one part of the problem that HPKP is trying to address. Once CT is a requirement no CA will be able to issue a certificate in secret without the owner of the domain knowing about it because it will be present in publicly visible CT logs. This is only half of the story though. Now the site operator will become aware that a rogue certificate has been issued and they need to have it revoked. This is where things aren't so great.
Certificate Authority Authorisation
Later this year all CAs will be required to check a new DNS record called CAA before issuing a certificate. You can read more details in my blog on Certificate Authority Authorisation but the TLDR is that you can set a DNS record that specifies which CA you authorise to issue certs for your domain. This is another step towards controlling issuance of certificates for your domain and whilst it's not a particularly strong technical measure, it is another consideration in deploying HPKP or not.
Revocation is broken
The issue right now is that we have no reliable way to revoke a certificate that will actually work. Both CRL and OCSP mechanisms give us no real hope of revocation actually working and they are all we have right now. If you don't believe me then read my article Revocation is Broken, it's sadly the situation we find ourselves in. There are things on the horizon that might help us to reliably revoke a certificate like OCSP Must-Staple and OCSP Expect-Staple to get us there, but these only help us protect certificates we obtain. They still wouldn't help us revoke a certificate obtained by an attacker so there is a benefit to HPKP here.
One of the biggest concerns for me in almost any deployment of HPKP is that it often pushes you to compromise on something that we really shouldn't be compromising on, key rotation. If, like I do at the time of writing, you pin only your leaf keys for the strongest possible deployment of HPKP, it makes regular key rotation something that has to be carefully planned and executed. Now, this is something I do but I'm probably in the minority of people who appreciate the technical challenge and actually enjoy overcoming it. I'd wager that most others who are pinning a leaf key would probably stick with that key for a long time, too long. Even if you pin at the intermediate and/or root level in your policy it's still a really good idea to have a backup pin for a leaf key so you can break the 'vendor lock' you've imposed upon yourself. Again, it's additional work to rotate your backup key, if you're like me you need an RSA and ECDSA backup key and what happens if the minimum key size changes along the way? You have a 2048bit RSA and 256bit ECDSA key in your safe but when you come to use them those key sizes are no longer acceptable. It's possible to plan for all of these things and have an incredibly robust HPKP strategy, but what's the likelihood of that happening?
What I'd much rather see is people frequently rotating their private and yes, even if you are using Perfect Forward Secrecy. Ideally I'd love to rotate my private key every time I renew my certificate, which I could, but it's extra work imposed by HPKP. This is also a problem I came across when scaling report-uri.io to it's current size. When I add new instances to the pool of servers I use Ansible to configure them and part of that process is to transfer the key and certificate from the Ansible Vault. This would be a necessity if you're using HPKP. What I'd much prefer to do is bring the instance online, have it generate its own set of fresh keys and hit the Let's Encrypt API to grab a fresh certificate. They can all exist for the duration of time the instance is alive and then be destroyed/renewed when required. I think this approach to having ephemeral keys and certificates is far better and is what I will be doing once Let's Encrypt start offering wildcard certificates.
One of the biggest concerns I have with HPKP right now is sites trying to use it and getting it wrong, RansomPKP is much less of a concern. At present securityheaders.io requires the use of HPKP to acquire the highest grade, A+, and this results in sites trying to use it. The number of times I receive emails from those who have broken their site or can't get a valid policy to be accepted by the browser is worryingly high. I also crawl the Alexa Top 1 Million sites every day and one of the things I monitor is the use of HPKP, you can see the blogs here. HPKP has a very low usage rate even in the top 1 million sites as you would expect, but there are still examples of it being deployed wrong. Not just a little wrong either, totally wrong, to the point where the browser wouldn't accept the policy and it's a good job too because it's the only thing saving them. Given the inherent dangers of HPKP I am tempted to remove the requirement to use it from securityheaders.io and allow sites to achieve an A+ with all of the other headers and HTTPS, with a special marker being given for those few who do deploy HPKP instead. It'd be great to hear thoughts and feedback on this idea so drop by the comments below and let me know what you think. If you want to see the effect this will have the changes are already deployed on the test site: https://test.securityheaders.io