Objective
This article describes how to configure HTTP public key pinning in NetScaler ADC load balancer.
Use Case
Protect clients from connecting to attacker’s website which impersonate your website by sending fraudulent certificate.
Introduction to HTTP Public Key Pinning
HTTP Public-Key-Pinning (HPKP) is a purpose built HTTP extension which stores pins in browsers and prevents them to accept a fraudulent certificate for the same host, in future. The HTTP extension looks as follows:
Public-Key-Pins:
pin-sha256=" hQO/AnnPthZU12nzjoZLHw5W5F3MJ/1AYKTvHE503Xc=";
pin-sha256="lERGk61FITjzyKHcJ89xpc6aDwtRkOPAU0jdnUqzW2s=";
max-age=15768000; includeSubDomains
When a server is configured to send HPKP extension in HTTP response, it sends SHA-256 fingerprint of one of the certificates (say cert_A) in its chain of trust along with SHA-256 fingerprint of a certificate (say cert_B) from another chain of trust. The browser stores these values and matches fingerprint of cert_A against the incoming certificates for this host. The match is made against all the certificates in the chain of trust i.e. the root certificate, intermediate certificate(s) and leaf certificate. If there is a successful match against any of them then browser accepts the connection else drops it.
This process ensures that only valid certificates are accepted by clients and thus eliminates any possibility of MITM attack or state-owned CA impersonating real servers (forward proxy). The choice of selection of cert_A from chain of trust is up to the administrator.
Fingerprint of cert_B is stored for the purpose of recovery when leaf certificate’s public key is pinned. When a certificate expires or needs to be changed (if private key is compromised), then this backup fingerprint is used. More details about public-key-pinning is available here https://timtaubert.de/blog/2014/10/http-public-key-pinning-explained/.
Prerequisites
SSL virtual server/Gateway virtual server should be configured.
Instructions
In NetScaler, we can generate SHA-256 hash of public key using OpenSSL in CLI and GUI. The hash can be added by rewriting the header in HTTP response.
Step 1: Generate SHA-256 hash
OpenSSL tool in NetScaler can be used to generate the SHA-256 hash of public key in certificate.CLI:
> shell
root@ns# openssl x509 -in /nsconfig/ssl/<certificate name> -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
GUI:
In the NetScaler GUI, go to Configuration > Traffic Management > SSL. In the landing page, go to OpenSSL interface in Tools.
In the OpenSSL interface use the following command to generate SHA-256 hash:
x509 -in /nsconfig/ssl/<certificate name> -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
Repeat the steps for the certificate from any other certificate chain (cert_B). Copy the hash values of the two certificate which would be used in the next step.
Step 2: Create Rewrite Action and Policy
To insert the needed HPKP header into the HTTP response from NetScaler, create rewrite policy and bind it to SSL virtual server or Gateway virtual server.
CLI:Add rewrite action:
Action type should be “INSERT_HTTP_HEADER” and header name should be “Public-Key-Pins”. In expression, “pin-sha256” has the value of the hash you derived earlier using OpenSSL. “max-age” is the period for which this pin will be stored in the client’s browsers. So this should be typically large value. During the PoC stage of the feature, you can keep this as a small value (say 60 sec) so that you are not locked out for long if something goes wrong.
> add rewrite action Insert_Public-Key-Pins_Header_act insert_http_header Public-Key-Pins "\"pin-sha256=\'YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=\'; pin-sha256=\'gHwovxTrxvWkm KCM9PZpkczE zsjXMlxS uZaUdA2g=\';max-age=5184000;includeSubDomains\""
Add rewrite policy:
The policy expression can be simply set to “true” as you would want to be inserted in every response.
> add rewrite policy <policy name> true <action name>
Bind policy to virtual server:
While binding the policy, make sure to insert this as type RESPONSE because you would want the HTTP header to be inserted in virtual server response.
> bind lb vserver <SSL virtual server name> -policyName <policy name> -priority 100 -type RESPONSE
GUI:
Go to Configuration > AppExpert > Rewrite > Actions and click Add. Add the details as shown below:
To create corresponding policy, go to Configuration > AppExpert > Rewrite > Policies and click Add. Add the details as shown below.
Bind the policy to the SSL/Gateway virtual server as shown below. Edit the virtual server and go to Advanced Settings to find Policies in it. Add Policies choose policy as Rewrite and type as Response. Select the policy created earlier from the list and bind assigning the right priority number.