Public key pins, a new safeguard for HTTPS websites

2014-04-07 00:00:00 +0100


Public-Key-Pins will be the new HTTP header to inform user browsers what X.509 certificates are identifying the websites and prevent various forms of man-in-the-middle attacks on SSL. The SSL/TLS protocol is seemingly a significant pain for countries and companies monitoring their Internet users, especially since Twitter, Facebook and Google offered SSL-enabled versions of their popular products. Need is mother of invention, so wiretapping solution provides started producing new methods of bypassing SSL, such as SSL striping, downgrade or man-in-the-middle (MITM) attacks.

The latter should be theoretically prevented by the X.509 certification model, but with Windows and Firefox trust anchors now growing to hundreds of certificates and incorporating certification authorities from potentially wiretapping countries, SSL site owners gradually stop trusting the X.509 model.

The first safeguard of the new type was Strict Transport Security HTTP header, which basically allows the website owner to announce that under no circumstances it should be viewed without SSL enabled. If this information is then being memorized in user browsers for sufficiently long time, it significantly reduces possibility of SSL striping attacks. For example, this header would instruct browsers visiting a website to memorize the SSL decision for 185 days, which means for the next half year browser will reject opening this page if it’s not over valid SSL connection:

Strict-Transport-Security: max-age=16070400

Public key pinning goes a step further — it instructs browsers to memorize website’s SSL certificate’s hash, so that the certificate cannot be replaced by a malicious one. This header would instruct the browser to remember the website’s public keys hashes for the next 30 days:

Public-Key-Pins: max-age=2592000; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="; pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="

These BASE64 strings are generated from the PEM encoded public key certificate as used on the SSL/TLS web server:

openssl x509 -noout -in certificate.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key openssl dgst -sha256 -binary public.key | openssl enc -base64

Public key pins status

Public key pins were standardized in RFC 7469: Public Key Pinning Extension for HTTP. My other website WebCookies.org checks for PKP headers among others and as of 2015 there is a few dozens of websites using it (WebCookies.org » HTTP headers » Public-Key-Pins, note that there’s also the Public-Key-Pins-Report-Only variant which is non-enforcing). Hopefully, as the header is now HTTP standard it will get more popularity.

ShodanHQ finds over 200 websites using it, most notably Freenet Project (see WebCookies.org report).

How does it fit X.509 model?

If you look at the history and overall architecture of X.509, the introduction of PKP can be seen as a kind of failure of the X.509 model. But it’s really not — X.509 answers the question of “is this certificate trusted”, implied from “is it signed by a trusted authority”.

But X.509 neither does nor it ever has answered the question of “should this authority actually sign this certificate”, because in the X.509 model all certificate authorities were considered trusted. So PKP seems to be filling this gap, by giving webmasters additional possibility to announce what public key is the right one.