Déploiement de HPKP avec NGINX et Let’s Encrypt

1/52/53/54/55/5 (1 votes, moyenne: 1,00 sur 5)
Loading...
D

Attention, cet article a plus d'une année d'ancienneté. Il est possible que les informations présentées ne soient plus à jour, spécialement dans le cadre d'un article technique.


Bonjour à tous,

Retour après deux mois de vide rédactionnel, aujourd’hui on va voir ensemble comment déployer HPKP (HTTP Public Key Pinning) avec NGINX et l’autorité de certification Let’s Encrypt.

 

Prérequis :

  • Avoir ma version custom de NGINX (ou le module more headers) : GitHub | Article
  • Avoir des certificats ECDSA générés à la main (surtout pour avoir une clé privée qui ne se renouvelle pas automatiquement) : Article 

 

HPKP c’est quoi ?

Vu que Wikipédia a encore fait une bonne description de la chose, on va citer :

 

HTTP Public Key Pinning (HPKP) est un mécanisme de sécurité qui protège les sites internet de l’usurpation d’identité contre les certificats frauduleux émis par des autorités de certification compromises.

À la première connexion réussie, le site présente une liste représentant les clés de confiances. Le navigateur mémorise cette liste.

Lors des connexions suivantes, si la clé de chiffrement présentée n’est pas présente dans la liste mémorisée, le navigateur refuse la connexion et bloque le site puis s’y reconnecte.

 

Source

 

Vous l’aurez compris, c’est moyen dangereux comme histoire et vous aurez vite fait de rendre votre site inaccessible si vous loupez un truc, on va donc voir comment faire pour éviter que ça se produise.

 

Création des clés de secours :

Première chose, dans le cas où cela merde vous aurez besoin de clés de secours pour créer de nouveaux certificats.

Les algorithmes qui sont déjà acceptés et seront toujours acceptés par les émetteurs de certificats à moyen terme sont :

  • le RSA en 4096 bits
  • Le ECDSA avec la courbe prime256v1

 

Créez donc un répertoire pour les clés :

mkdir /tmp/hpkp
cd /tmp/hpkp/

 

Générez la clé RSA et son CSR, rentrez bien le common name :

openssl req -nodes -sha256 -newkey rsa:4096 -keyout "abyssproject.net.rsa.key" -out "abyssproject.net.rsa.csr"

 

Générez la clé ECDSA et son CSR, rentrez bien le common name :

openssl req -nodes -newkey ec:<(openssl ecparam -name prime256v1) -keyout "abyssproject.net.ec.key" -out "abyssproject.net.ec.csr"

 

Maintenant, générez les hashs SHA256 des clés publiques :

openssl req -pubkey < abyssproject.net.rsa.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
openssl req -pubkey < abyssproject.net.ec.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

 

Chez moi ça donne ça :

Ih7zlQOi8s4JRJA0Wb/McTpjCc2gLSgJxKWi/a1ewSw=
lRaHRedXUsH0Y+OvYYyJhQpwCmBQQusTn9Ts5q2QaEw=

 

Création du HASH de la clé privée :

Maintenant, rendez vous dans le dossier qui contient la clé privée que vous utilisez actuellement :

cd /etc/letsencrypt/live-ecdsa/abyssproject.net

 

Et générez le hash SHA256 de la clé publique :

openssl ec -in privkey-p384.pem -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

 

Chez moi ça donne ça :

ymaHD/rAGZy9JlRlqcc8E36+JCxvW/QduCTbw0BOH+o=

 

Mise en place dans NGINX et test :

Maintenant, vous pouvez ajouter la ligne suivante dans la partie SERVER de votre vhost :

more_set_headers 'Public-Key-Pins pin-sha256="PIN_LIVE"; pin-sha256="PIN_BACKUP1"; pin-sha256="PIN_BACKUP2"; max-age=10';

 

Ce qui donne chez moi :

more_set_headers 'Public-Key-Pins pin-sha256="ymaHD/rAGZy9JlRlqcc8E36+JCxvW/QduCTbw0BOH+o="; pin-sha256="Ih7zlQOi8s4JRJA0Wb/McTpjCc2gLSgJxKWi/a1ewSw="; pin-sha256="lRaHRedXUsH0Y+OvYYyJhQpwCmBQQusTn9Ts5q2QaEw="; max-age=10';

 

Redémarrez NGINX :

service nginx restart

 

Et vérifiez que le header HPKP s’affiche :

curl -I https://www.abyssproject.net/

 

 

Allez sur le site suivant : https://report-uri.io/home/pkp_analyse/ pour vérifier que votre header est correct :

 

 

Si tout est bon, remplacez :

max-age=10

 

Par

max-age=5184000

 

C’est la recommandation (60 jours) du RFC 7469 qui définit le HPKP : https://tools.ietf.org/html/rfc7469#section-4.1 (début de la page 19)

 

Et revérifiez :

 

 

 

Sauvegarde de ses clés privées :

Maintenant la grande question de la sauvegarde des clés privées.

  1. Déjà, ne gardez évidemment pas les clés de secours sur le même serveur.
  2. Gardez une copie papier et / ou offline chez vous sur une partition chiffrée
  3. Envoyez une copie chiffrée sur Online.net C14 ou OVH Cloud Archive
  4. Mettez une copie papier à la banque

 

En cas de soucis :

Virez le header et patientez 60 jours avant de retrouver vos visiteurs 🙂

 

Merci à Aeris pour ses conseils éclairés 🙂

 

A propos de l'auteur

Nicolas Simond

Ingénieur Systèmes et Réseaux et guitariste hard rock et metal à mes heures perdues.
Je suis le créateur et l'unique rédacteur d'Abyss Project, c'est ici que je note la plupart de mes procédures et quelques divagations.

Si vous l'article vous a aidé, pensez à me payer un café :)

Subscribe
Notify of
guest

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

3 Commentaires
Plus récents
Plus anciens Populaires
Inline Feedbacks
View all comments
Qwaser
6 années plus tôt

Merci pour cet article très intéressant !

Comment cela se passe lorsque nos certificats sont renouvelés ?

Qwaser
Reply to  Nicolas Simond
6 années plus tôt

D’accord merci pour ta réponse. 🙂
Donc rien de spécifique à faire pour un renouvellement, par contre en cas de migration ou réinitialisation de serveur, si l’on veut rien casser il faudra bien veillez à sauvegarder son dossier let’s encrypt pour ne pas changer de clé privée est-ce exact ?

En tout cas cela faisait un moment que je souhaitais mettre cela en place sur mes sites, grâce à toi je vais pouvoir y arriver !