Nginx – Public Key Pinning headers correct setup and failure test

httpsnginx

I'm trying to set up Public Key Pinning header in nginx 1.7.12 (Public-Key-Pins) but I seem to be missing something. I know how to generate the relevant pin-sha256 fields.

I thought it will work like this:

  1. If I include the pin-sha256 value of the current certificate in the header, then everything works fine.
  2. If I don't include the certificate's pin-sha256 (nor any intermediate or root certificate's), then it should mean an error, and the browser should:
    • prevent visiting the page,
    • output an error regarding the pins to the console,
    • and if provided, hit the report-uri endpoint with info on the request

What really happens

In the case of 2. in Firefox a mere The site specified an invalid Public-Key-Pins header. warning in the console and the visit proceeds as usual (in case 1 no warnings, so the header should be correct). In Chrome no sign that none of the sha256 values can be matched to the current certificate, the visit works all the time.

(using Firefox 37 and Chrome 41 on Arch Linux for testing).

What am I missing? What should be the actual behaviour of the Public-Key-Pins header, and how can I trigger an error in the setup so I can test the failure case?

My current header is in a form something like this (short max-age for testing, properly filled out FQDN:

Public-Key-Pins: pin-sha256="XOwgEECL9p3X2PctwnsIvbV+ySJ975dNYbm8wxkjzXg="; pin-sha256="NxVoMtbt/y2GI3lV/ROFIcDyz8kj/W8JTtoszmBezOg="; pin-sha256="aM2laE5XUTDaWo6RnfKZ9OZHrNz/KQmRxCRO6YmWHGE="; max-age=900; report-uri="https://<FQDN>/hpkp";

Best Answer

To be accepted, your pin must :

  1. Contains at least one key of the current certificate chain
  2. Contains at least one key NOT in the current certificate chain (a "Back up key"). I think this one was missing in your case.

To test it :

  • use firefox developper edition, go in the network tab, select a request, select the security tab of the right. It must indicate "Public Key Pinning" with the status
  • if you really want to produce the error, use the option "include subdomains", and sign any subdomain with a new key. Firefox should refuse the connection.

Some docs : https://developer.mozilla.org/en-US/docs/Web/Security/Public_Key_Pinning

To be more specific : "If I don't include the certificate's pin-sha256 (nor any intermediate or root certificate's)", then the browser don't save the pin. The browser display at connection error only when an already saved pin list doesn't match the current certificate chain.

https://scotthelme.co.uk/hpkp-toolset and https://report-uri.io/home/pkp_analyse can help