A couple of months ago, Chrome, Firefox and perhaps other browser have begun to 'pin' the HTTPS certificates used by Google, Twitter and others for their web pages. This significantly improves security for these web pages as their certificates can no longer be signed by any of the hundreds of Certificate Authorities (CAs) that are trusted by web browsers but only by one or a few select ones. So far, this functionality was part of the web browser's code. Recently, however, most desktop and mobile browsers have added support for the generic HTTPS Public Key Pinning (HPKP) method standardized in RFC 7469 that enables any HTTPS protected web site to do the same. Time for me to add it to my Owncloud and Selfoss servers too to protect myself from man-in-the-middle attacks.
HPKP works by adding a public key pin header string to the HTTP response header section that is returned to the web browser each time a web page is loaded. On first request, the web browser stores these and whenever the page from the same domain is loaded again afterward compares the hashes of the HTTPS certificate it receives with those previously stored. If they don't match the page load process is aborted and an error message is shown to the user that can't be overridden. For the details of how to generate the hashes and how to configure your webserver have a look here and here.
The first screenshot on the left (taken from Firefox'es Webdeveloper Network console) shows how the public key pin looks like in the HTTPS response header of my web server. In my case I set the validity of the pinning to 86400 seconds, i.e. to one day. This is long enough for me as I access my Owncloud and Selfoss servers several times a day. As I don't change my certificate very often I decided not to pin one of the CA certificates in the chain of trust but be even more restrictive and pin my own certificate at the end of the chain.
On the PC I successfully verified that Firefox stores the pin hashes and blocks access to my servers by first supplying a valid certificate and a corresponding public pin hash and then removing the pin header and supplying a different valid certificate. Even after closing and reopening the browser, access was still blocked and I could only access my Owncloud instance again after I reinstated the original certificate again. Beautiful.
On Android, I tried the same with Firefox Mobile and Opera Mobile. At first I was elated as both browsers block access when I used a valid certificate that was different from the one I pinned before. The second screenshot on the left shows how Opera Mobile blocks access. Unfortunately, however, both browsers only seem to store the pin hashes in memory. After restarting them, both allowed access to the server again. That's a real pity as Android frequently terminates my browser when I switch to other large apps. That's more than an unfortunate oversight, that's a real security issue!
I've opened bug reports for both Firefox and Opera mobile so let's see how long it takes them to implement the functionality properly.