nextcloud

HTTP Public Key Pinning v.4

nextcloud-square-logoFollowing this guide you will increase nginx security due to HTTP Public Key Pinning (HPKP) in less than ten minutes. As minimal pre-requirements ensure your nginx is running with ssl enabled, let’s encrypt certificates are active and embedded and your Nextcloud is reachable via internet.

Update series (history)
v. 4 – Dec. 01st, 2016: enhancement with regards to etc/ssl/certs // permisissions.sh
v. 3 – Nov. 27th, 2016: added backup-pins (PIN4) & (PIN5) for HKPK and achieve A+ Ranking
v. 2 – Nov. 16th, 2016: update to Calculate PIN3
v. 1 – Nov. 02nd, 2016: Initial Post

Change to your working directory:

sudo -s
cd /usr/local/src
Let’s encrypt: Chain of Trust

Download the intermediate certificate from Let’s Encrypt (lets-encrypt-x3-cross-signed.pem):

wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem

The certificate will be stored in /usr/local/src/lets-encrypt-x3-cross-signed.pem.

Calculate PIN1:

openssl x509 -pubkey < /etc/letsencrypt/live/<yourcloud.desec.io>/fullchain.pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Substitute <yourcloud.desec.io> and store the result of the openssl command as PIN1.

Calculate PIN2:

Then calculate the second PIN (PIN2) based on Let’s Encrypt Authority X3 -IdenTrust cross-signed certificate:

openssl x509 -pubkey < lets-encrypt-x3-cross-signed.pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Store the result of the openssl-command as PIN2.

Calculate PIN3:

In addition copy the following lines from DST Root CA X3.pem and paste them to (dst_root_ca_x3.pem)

vi dst_root_ca_x3.pem

Add both “—–BEGIN CERTIFICATE—–” and “—–END CERTIFICATE—–“and paste the copied rows in between:

-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----

Save & quit (:wq!) the new file and calculate PIN3:

openssl x509 -pubkey < dst_root_ca_x3.pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Store the result of the openssl-command as PIN3.

Calculate PIN4 (Backup-PIN1):

Change to /etc/ssl/certs and start building the first Backup-PIN (PIN4):

cd /etc/ssl/certs
openssl genrsa -out yourcloud.dedyn.io.first.key 4096
openssl req -new -key yourcloud.dedyn.io.first.key -sha256 -out yourcloud.dedyn.io.first.csr

Now calculate the PIN4:

openssl req -pubkey < yourcloud.dedyn.io.first.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Store the result of the openssl-command as PIN4.

Calculate PIN5 (Backup-PIN2):

Now start building the second Backup-PIN (PIN5):

openssl genrsa -out yourcloud.dedyn.io.second.key 4096
openssl req -new -key yourcloud.dedyn.io.second.key -sha256 -out yourcloud.dedyn.io.second.csr

Now calculate the PIN5:

openssl req -pubkey < yourcloud.dedyn.io.second.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Store the result of the openssl-command as PIN5.

Set the permissions to the new created certificates:

chmod 0600 yourcloud.dedyn.io.*

or, if you use my permissions.sh, add the following line to the script:

chmod 0600 /etc/ssl/certs/youcloud.dedyn.io.*

gateway.conf

Now we have to enhance the gateway.conf with the following row:

add_header Public-Key-Pins 'pin-sha256="PIN1"; pin-sha256="PIN2"; pin-sha256="PIN3"; pin-sha256="PIN4"; pin-sha256="PIN5"; max-age=2592000; includeSubDomains';

Please substitue PIN1, PIN2, PIN3, PIN4 and PIN5 with the results of the openssl-commands above and add the “add_header”-command to your gateway.conf:

vi /etc/nginx/conf.d/gateway.conf

Add ans substitute the red ones:

...
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Xss-Protection "1; mode=block" always;
add_header Public-Key-Pins 'pin-sha256="PIN1"; pin-sha256="PIN2"; pin-sha256="PIN3"; pin-sha256="PIN4"; pin-sha256="PIN5"; max-age=2592000; includeSubDomains';
add_header X-Robots-Tag none;
...

nginx

Test nginx and restart nginx if no errors appear:

nginx -t
service nginx restart

Verify your new server security including HPKP:

(1.) security headers at https://securityheaders.io/

© c-rieger.de

(2.) mozilla obversatory at https://observatory.mozilla.org/

© c-rieger.de

(3.) Qualys SSL Labs at https://www.ssllabs.com/

© c-rieger.de

You can check the use of hpkp in your browser: in  firefox press “STRG+SHIFT+K” and call your Nextcloud.

© c-rieger.de

The Public-Key-Pins should appear in the header-outputs. Please keep in mind to renew the PINs synchronized to your certificate renewals (currently no later than 90 days).

Enjoy your Nextcloud…