HTTP Public Key Pinning
In order to understand HTTP Public Key Pinning (HPKP), let’s take a look at how browsers implement the SSL handshake, which is conducted before establishing a secure connection.
When our users try to access our site securely, we send them our public key that both affirms that they are talking to the right party and will be used to encrypt the shared key. We call this a ‘certificate’ and it holds information like our website’s name, certificate expiration date, and the amount of bits in the cryptographic key.
Certificate Authorities and Fraudulently Issued Certificates
There’s one additional piece of information in the certificate. When the browser receives our certificate, it checks if our certificate was signed by a trusted certificate authority (CA). One of the pieces of information in our certificate is the name of the CA, which will be used by the browser to validate our certificate. A secure connection is established once it is confirmed as genuine.
However, several incidents have revealed that, regardless of the motive, one of these certificate authorities can sign a certificate on behalf of a website without notifying the website owner!
- One example of this occured in the Netherlands in 2011 when the authorized certificate distributer DigiNotar was hacked. Around 500 certificates were fraudulently signed. Multiple Google services, including 300,000 Gmail accounts belonging to Iranian citizens, were monitored with these certificates.
- A similar incident took place in 2008 and 2011, affecting a certificate authority called StartCom. Certificates for paypal.com and verisign.com were published. In 2011, attackers accessed the root key of StartCom, gaining the ability to produce, invalidate, or renew any StartCom certificates.
- In 2011, due to an incident with a certificate authority called Turktrust, an intermediate certificate was issued to sign certificates on behalf of Google domains. One of them was spotted on December 26, 2012 by Google Chrome, and subsequently reported to Google. It’s noteworthy that the Chrome browser figured this out and reported it back to Google.
How to Prevent Fraudulently Issued Certificates
The question is: How can a browser automatically detect a fraudulently issued certificate for a specific domain and even report this certificate back to Google?
The answer to this question is a mechanism called HTTP Public Key Pinning (HPKP). Ever since the introduction of this feature in Chrome 13, websites can make their certificate fingerprints (hash values) known to the browsers using the Public-Key-Pins response header.
Browsers store these hashes on the user’s computer. Every time the website is visited, the browser generates a hash based on the certificate’s public key. If the hash doesn’t match the stored value, the connection won’t be established, and the incident is reported to a URL if the report-uri directive is set.
In conclusion, HTTP Public Key Pinning protects the users and websites from CAs signing fake certificates.
Setting up an HPKP Header
Public-Key-Pins is a security header. We can enable HPKP by sending it back with every response over a secure connection (HTTPS):
Public-Key-Pins:
pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="; report-uri="http://example.com/pkp-report"; max-age=10000; includeSubDomains
HPKP Directives
Various directives are available for the HPKP header, such as max-age and report-uri. This is a complete list.
Directive |
Description |
pin-sha256=””: |
This is the public key fingerprint of our certificate encoded in base64. You can store hashes of multiple certificates here as backups, in case one of the certificates expires. |
max-age: |
This is the length of time (in seconds) this directive should be cached. |
includeSubdomains: |
This states whether the pinning covers the subdomains or not. |
report-uri: |
As outlined in the Google example above, in case of a mismatch, this directive specifies the URL to which the reports of the HPKP policy breach should be sent. The breach information will be sent to this URL using the HTTP POST method. |
You can set the HTTP Public Key Pinning mechanism to work in Report-Only mode, which means the browser will still establish a secure connection if a mismatch occurs, but will report the breach to the URL stated in the report-uri directive:
Public-Key-Pins-Report-Only: pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="; report-uri="http://example.com/pkp-report"; max-age=10000; includeSubDomains
According to RFC 7469, you must set at least 2 pins. One is for your current certificate, and the other is for your backup certificate. The given set of Pins contains at least one Pin that does not refer to an SPKI in the certificate chain. (That is, the host must set a Backup Pin; see Section 4.3.)
Research published on EvenPaths concludes that there are HPKP implementation errors, even in webpages belonging to large companies such as Facebook and WhatsApp. This information was collected using the Alexa Top 1 Million domain list. And while there are websites that did not pin any certificates in their HPKP headers, there were also websites that pinned as many as 17.
Which Browsers Support PKP Security Headers?
After reading the above about HPKP, get ready for a little surprise… Starting with Google Chrome version 69, HPKP – the mechanism that helped Google to catch fraudulently issued certificates in the wild – is no longer supported.
Source: https://caniuse.com/#search=Public%20Key%20Pinning
Even though this is a little surprising at first, it makes sense if you think about it. If even well resourced companies such as Facebook (as outlined in the ElevenPaths study) make mistakes in implementing this security measure, it’s probably too complicated to be used reliably on a large scale.
However, there is a header that promises an equal amount of protection, with a little extra effort.
Check Your Security Headers
HTTP security headers are a fundamental part of website security
‘HTTP Security Response Headers’ allow a server to push additional security information to web browsers and govern how the web browsers and visitors are able to interact with your web application.