Introduction to HPKP Date problem
A typical Public Key Pinning Header looks like this:
Public-Key-Pins: pin-sha256="iW1rJY5ruUaJqt0gWpO1fOx+qSAmdG/mNA4TH2aivZQ="; pin-sha256="2e+k3qeXV2F7MuGIYeec2Mw4lh0wFPHUv/P0Sr0GzNU="; max-age=86400
You have at least 2 sha256 hashes and a max-age directive in seconds.
In this example we advise the browser to keep this header for 1 day (86400 seconds).
Whenever the user visits a page on the same domain and receives the header again, the browser will update the timestamp until which this header is valid, taking the value of the max-age into account.
Now comes the tricky part. Imagine the following scenario:
What happens if we have a wrong date on our computer? What if our date is set to some time in the future? Today's date is 31st December 2014. If we set the date to 31st December 2015 and then visit an https site with a Public-Key-Pins max-age value of 1 day, the browser will set the expiry time of the header to TODAY + max-age, that is 31st December 2015 + 1 day = 1st January 2016.
If some time later the user notices the wrong date on his device and sets it to the correct date, connecting to the https site will be a matter of luck: If the certificate/public key of the site has changed since the last visit with the wrong date, the user won't be able to connect to the site anymore.
To test this scenario yourself, follow these steps:
- Let's pretend we have a wrong date on our device. Set your local date to some time in the future, e.g. 2016-01-01
- Visit an https site with
a valid certificate (valid until at least the date that you set in step 1.), and with
a key pins header with a max-age of e.g. 1 month
Your browser has saved your Public-Key-Pins now until the date you set in step 1. plus the max-age from the PKP header
- Set your date back to the current date plus at least the max-age value from step 2., e.g. 2015-02-15.
Doing this we pretend that we corrected the wrong date in the first step (to 2014-12-31), and that since the correction, enough
time has passed that the header would need to get invalidated. The date that we set here is the date that a webmaster would assume
is a safe date, to change the certificates (even multiple times, even the backup certificate).
- Now use a different certificate for the https site in question, use one that was not in the header when doing step 2.
- Visit the https site. Chrome 39 will throw a NET::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN error.
The problem is that the max-age directive leaves room for the user to mess up the effective validity of the Public-Key-Pins header.
Hence the webmaster of the site cannot rely on the max-age value. It could well happen, that some users with wrong dates have
an effective max-age of a couple of years instead of a couple of days. Those users will have no chance to connect to the https site again
once the certificates change.
Probably it would be better to use unix timestamps instead of the max-age directive in the HPKP header.
Taking this route would make it easier for the browser to recognize that there's something wrong with the local date.
written by Can Özdemir
December 31st, 2014