Améliorer la sécurité des échanges SSL effectués par votre serveur web

Mon site personnel https://vincent.composieux.fr est maintenant disponible en HTTPS depuis un petit bout de temps, grâce à Let's Encrypt. Après avoir observé les résultats du test et m'être renseigné sur les différentes actions à mettre en place pour améliorer le score, je vais finalement vous partager les actions à mettre en place dans la configuration du serveur web afin d'obtenir un meilleure score : A+.

Ce score permettra de mieux sécuriser les échanges entre votre serveur et les clients de votre site ou application web car il est basé sur les différentes vulnérabilitées trouvées par des chercheurs au fur et à mesure du temps sur le protocole TLS.

Quelles sont les vulnérabilitées ?

Voici une liste des différents problèmes et vulnérabilitées connus :

CLR / OCSP : Initialiement, les certificats étaient validés en utilisant la méthode CLR (Certificate Revocation List). Le problème est que cette liste a tellement grossie que le téléchargement de celle-ci prend énormément de temps. Il est donc préférable aujourd'hui d'utiliser la méthode Online Certificate Status Protocol (OCSP) qui est bien plus légère car un seul enregistrement est retourné et c'est l'autorité de certification qui va se charger de cette vérification.

Logjam - Weak Diffie-Hellman (DH) : Cette attaque "man-in-the-middle" permet en effet de réduire l'algorithme de cryptographie TLS à 512 bits ce qui permet ensuite à l'attaquant de lire et modifier les données échangées. Nous allons pouvoir corriger cette vulnérabilité en précisant à notre serveur web une clé spéciale, sécurisée, que nous verrons par la suite. Pour plus d'informations sur cette attaque : https://weakdh.org.

SSLv2 et SSLv3 : Ces versions de SSL sont vulnérables et doivent donc être désactivées, nous mettrons donc uniquement les protocoles TLS non vulnérables dans notre configuration de serveur web. Pour plus d'informations sur ces vulnérabilitées : http://disablessl3.com.

Certains ciphers : Certaines suites de ciphers sont également compromises et utiliserons donc dans la configuration de notre serveur web uniquement les ciphers fiables. Notez qu'OpenSSL utilisera uniquement les ciphers dont il a connaissance, pas d'inquiétude à spécifier une liste trop évoluée donc, en fonction de votre version d'OpenSSL.

Heartbleed : Cette vulnérabilité a été découverte en avril 2014 dans la cryptographie utilisée par OpenSSL et maintenant corrigée dans les versions récentes de l'outil. Je vous invite donc à mettre à jour votre version d'OpenSSL pour corriger.

  • OpenSSL 1.0.1 jusqu'à 1.0.1f (inclus) sont vulnérables
  • OpenSSL 1.0.1g n'est pas vulnérable
  • La branche OpenSSL 1.0.0 n'est pas vulnérable
  • La branche OpenSSL 0.9.8 n'est pas vulnérable

Pour connaitre votre version d'OpenSSL (et surtout la mettre à jour) :

$ openssl version
OpenSSL 1.0.1t  3 May 2016

Voyons maintenant comment corriger ces vulnérabilitées dans notre serveur web ! J'ai utilisé nginx dans mon cas mais je vais également vous fournir l'équivalent Apache dans cet article.

Configuration à spécifier dans votre vhost

Commençons par modifier la configuration de votre vhost afin de lui spécifier les clés SSL et y ajouter un petit header HSTS afin de spécifier que ce site peut être appelé uniquement en HTTPS.

Pour Nginx :

ssl_certificate /etc/ssl/domain.tld/fullchain.pem;
ssl_certificate_key /etc/ssl/domain.tld/privkey.pem;
ssl_trusted_certificate /etc/ssl/domain.tld/chain.pem;

# HSTS (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;

Pour Apache :

SSLEngine             on
SSLCertificateFile    /ets/ssl/domain.tld/fullchain.pem
SSLCertificateKeyFile /ets/ssl/domain.tld/privkey.pem

# HSTS (mod_headers is required) (15768000 seconds = 6 months)
Header always set Strict-Transport-Security "max-age=15768000"

Protocoles SSL et Ciphers

Pour ce qui concerne nginx, je vous invite à créer un fichier à l'emplacement /etc/nginx/conf.d/ssl.conf et à mettre la suite de la configuration de cet article dedans. Nous allons maintenant définir les protocoles et ciphers que nous souhaitons utiliser sur notre serveur (et surtout ne pas ajouter ceux que nous ne souhaitons pas utiliser).

Pour Nginx :

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

Pour Apache :

SSLProtocol         all -SSLv3
SSLCipherSuite      ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder on

Utilisation du protocole OCSP

Nous allons spécifier à notre serveur web que nous souhaitons utiliser ce protocole :

Pour Nginx :

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;

Pour Apache :

# OCSP Stapling, only in httpd 2.3.3 and later
SSLUseStapling                   on
SSLStaplingResponderTimeout      5
SSLStaplingReturnResponderErrors off
SSLStaplingCache                 shmcb:/var/run/ocsp(128000)

Paramètres Diffie-Hellman (DH)

Nous allons ici générer une clé (d'au moins 2048 bits, j'ai donc choisi une clé de 4096 bits) permettant de sécuriser les échanges de clés. Je vous conseille de lancer cette commande dans un screen car elle a pris, pour moi, environ 8 heures :

$ openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

Une fois la clé générée, mettez à jour la configuration de votre serveur web :

Pour Nginx :

# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
# openssl dhparam -out dhparam.pem 2048
ssl_dhparam /etc/ssl/certs/dhparam.pem;

resolver 8.8.4.4 8.8.8.8;

Pour Apache :

Il vous faudra modifier la clé fournie dans la valeur de configuration SSLCertificateFile afin d'y ajouter une section DH PARAMETERS, comme suit :

-----BEGIN DH PARAMETERS-----
MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
-----END DH PARAMETERS-----

Pour plus d'informations, rendez-vous sur la documentation d'Apache : https://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh.

Nous en avons terminé, je vous invite maintenant à vous assurer que la configuration de votre serveur web est correcte, le relancer et de regarder votre score sur SSLLabs qui devrait être grandement amélioré !

Conclusion

Si vous utilisez un autre type de serveur ou que vous souhaitez adapter la configuration de celui-ci, je vous invite également à jeter un oeil à cet outil proposé par Mozilla : https://mozilla.github.io/server-side-tls/ssl-config-generator.