Bonnes pratiques SSL/TLS

Une implémentation sécurisée de SSL/TLS est essentielle pour protéger les données en transit contre l'interception, la modification et les attaques man-in-the-middle qui peuvent compromettre la confidentialité et l'intégrité de communications sensibles. Bien que SSL/TLS soit largement adopté (pratiquement tous les sites modernes utilisent HTTPS), de nombreuses implémentations contiennent encore des vulnérabilités issues de configurations inadéquates : l'utilisation de versions obsolètes du protocole (SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1) officiellement dépréciées par des organismes tels que l'IETF et PCI-DSS en raison de vulnérabilités connues comme POODLE, BEAST et CRIME, des cipher suites faibles ou cassées telles que RC4, DES, 3DES et MD5 qui peuvent être attaquées avec des ressources de calcul modernes, des certificats avec des algorithmes de signature SHA-1 désormais considérés comme non sécurisés, l'absence de Perfect Forward Secrecy (PFS) qui permet de déchiffrer rétroactivement le trafic capturé si la clé privée du serveur est compromise à l'avenir, l'absence de HSTS (HTTP Strict Transport Security) rendant possibles les downgrade attacks où un attaquant force une connexion HTTP non chiffrée, et un certificate pinning inadéquat ou absent dans les applications mobiles critiques permettant l'interception via des certificats malveillants installés sur l'appareil. Une configuration optimisée de SSL/TLS améliore non seulement la posture de sécurité mais influe aussi sur les performances (les handshakes TLS 1.3 sont plus rapides que TLS 1.2), la compatibilité (les clients très anciens peuvent ne pas prendre en charge les configurations modernes) et la compliance (LGPD, GDPR, PCI-DSS exigent un chiffrement fort pour les données en transit). Cet article fournit des recommandations techniques détaillées pour implémenter SSL/TLS en suivant les best practices du secteur, les recommandations du NIST, le Mozilla SSL Configuration Generator et OWASP.

Versions de protocole : TLS 1.2 et TLS 1.3

Désactivez complètement SSL 2.0, SSL 3.0, TLS 1.0 et TLS 1.1 sur tous les serveurs : ces versions présentent des vulnérabilités documentées et ne doivent pas être utilisées, même pour assurer la compatibilité avec des clients hérités. Configurez votre serveur web (nginx, Apache, IIS) ou votre load balancer (AWS ALB, Azure Application Gateway) pour n'accepter que TLS 1.2 et TLS 1.3. TLS 1.3, ratifié en 2018 sous la RFC 8446, offre des améliorations significatives par rapport aux versions précédentes : un handshake plus rapide (1-RTT au lieu de 2-RTT, avec prise en charge du 0-RTT pour les resumed sessions), la suppression des cipher suites non sécurisées (il ne prend plus en charge le RSA key exchange, les chiffrements en mode CBC, RC4, 3DES), la forward secrecy obligatoire dans toutes les cipher suites, et un handshake chiffré qui masque les métadonnées de négociation du protocole. Sous nginx, configurez avec "ssl_protocols TLSv1.2 TLSv1.3;". Sous Apache, "SSLProtocol -all +TLSv1.2 +TLSv1.3". AWS ALB permet de sélectionner une security policy qui définit les protocoles et les chiffrements : choisissez "ELBSecurityPolicy-TLS13-1-2-2021-06" pour des environnements modernes ou "ELBSecurityPolicy-2016-08" si vous devez prendre en charge certains clients anciens. Surveillez vos logs d'accès pour identifier combien de clients utilisent encore TLS 1.0/1.1 : si le nombre est négligeable (moins de 0,1 % du trafic), vous pouvez le désactiver sans impact matériel. Pour les API B2B où vous contrôlez les deux endpoints, exigez TLS 1.3 exclusivement. N'oubliez pas que la version du protocole est négociée pendant le handshake : le serveur doit annoncer les versions prises en charge et le client sélectionne la plus élevée qu'il prend également en charge.

Cipher suites : ECDHE et AES-GCM

Les cipher suites définissent les algorithmes utilisés pour le key exchange, l'authentification, le chiffrement symétrique et le HMAC pendant une connexion TLS : un choix inadéquat peut compromettre toute la sécurité de la communication, même en utilisant TLS 1.2+. Privilégiez les cipher suites avec ECDHE (Elliptic Curve Diffie-Hellman Ephemeral) pour le key exchange car il offre la Perfect Forward Secrecy, et AES-GCM (Galois/Counter Mode) ou ChaCha20-Poly1305 pour le chiffrement symétrique car ce sont des chiffrements AEAD (Authenticated Encryption with Associated Data) qui garantissent à la fois la confidentialité et l'intégrité. Exemple de cipher suite sécurisée : TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ou TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. Évitez complètement : les cipher suites avec RC4 (vulnérables à des biais statistiques), les export ciphers (limités à 40 ou 56 bits par d'anciennes réglementations d'exportation), les NULL ciphers (sans chiffrement), DES et 3DES (petite taille de bloc vulnérable à Sweet32), le mode CBC dans TLS 1.0-1.1 (vulnérable à BEAST et Lucky13), et le RSA key exchange sans DHE/ECDHE (sans forward secrecy). Sous nginx, configurez "ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';" et "ssl_prefer_server_ciphers on;" pour forcer l'ordre du serveur. Utilisez des outils tels que ssllabs.com/ssltest pour valider votre configuration et obtenir une note A+. Pour TLS 1.3, les cipher suites sont simplifiées et plus sécurisées par défaut (TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256).

HSTS : HTTP Strict Transport Security

HSTS est un mécanisme qui demande aux navigateurs d'utiliser toujours HTTPS pour un domaine donné, prévenant les attaques de SSL stripping où un man-in-the-middle force une connexion HTTP non chiffrée en interceptant la première requête avant que la redirection 301 vers HTTPS ne se produise. Implémentez HSTS en ajoutant l'en-tête "Strict-Transport-Security" à toutes les réponses HTTPS de votre serveur : "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload". Le paramètre max-age (en secondes) définit pendant combien de temps le navigateur doit se souvenir d'utiliser uniquement HTTPS : 31536000 secondes = 1 an est la valeur recommandée. "includeSubDomains" applique la politique à tous les sous-domaines (à utiliser avec prudence car vous devez garantir que TOUS les sous-domaines prennent en charge HTTPS). "preload" indique que vous voulez que votre domaine soit inclus dans la HSTS preload list maintenue par les navigateurs : une liste codée en dur de domaines qui doivent toujours utiliser HTTPS, même lors de la première visite, avant la réception de tout en-tête HSTS. Pour être inclus dans la preload list, soumettez votre domaine sur hstspreload.org après avoir confirmé que : l'ensemble du site fonctionne parfaitement en HTTPS, vous disposez d'un certificat valide couvrant le domaine et les sous-domaines, vous redirigez tout le trafic HTTP vers HTTPS, vous servez l'en-tête HSTS sur le domaine de base avec les directives includeSubDomains et preload, et que max-age est supérieur ou égal à 31536000. IMPORTANT : preload est une décision à sens unique ; retirer un domaine de la liste peut prendre des mois et cassera l'accès des utilisateurs pendant cette période si vous ne pouvez plus prendre en charge HTTPS. Sous nginx : "add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload' always;". Sous Apache : "Header always set Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload'".

Certificate pinning pour les applications critiques

Le certificate pinning est une technique où votre application (en particulier les applications mobiles et les API critiques) code en dur ou intègre le hash/fingerprint du certificat attendu du serveur, en validant pendant le TLS handshake que le certificat présenté correspond au pin stocké : cela prévient les attaques où un attaquant installe un certificat malveillant sur l'appareil de la victime (via un malware ou un accès physique) et intercepte le trafic HTTPS qui serait normalement approuvé par la chaîne de CA par défaut du système d'exploitation. Il existe deux types de pinning : le pin du certificat leaf (spécifique à ce certificat, doit être mis à jour lorsque le certificat expire/se renouvelle), ou le pin de la clé publique/clé publique de la CA (plus flexible, autorise la rotation des certificats tant qu'ils sont signés par la même CA). Implémentez le pinning dans les applications mobiles à l'aide de frameworks natifs : le framework iOS Network permet le pinning via les callbacks URLSessionDelegate, Android utilise la Network Security Configuration XML avec l'élément pin-set, React Native peut utiliser la bibliothèque react-native-ssl-pinning. Pour les API, envisagez le mutual TLS (mTLS) où le client présente également un certificat au serveur, validé via le pinning. ATTENTION : un pinning incorrect peut casser votre application si vous perdez l'accès au certificat épinglé (pinned) et n'avez aucun mécanisme de fallback ; implémentez toujours : un pin de backup (un second certificat/CA valide), des mises à jour de pin over-the-air, et une période de grâce avant d'appliquer les pins pour permettre un rollback en cas d'urgence. Utilisez le Public Key Pinning plutôt que le Certificate Pinning lorsque c'est possible (plus résilient aux renouvellements). Exemple de configuration sous Android avec un digest SHA-256 et le hash en base64 de la clé publique. Des outils tels qu'openssl peuvent extraire le hash de la clé publique des certificats pour l'utiliser dans les pins.

Perfect Forward Secrecy (PFS)

La Perfect Forward Secrecy est une propriété cryptographique où la compromission de la clé privée à long terme du serveur (la clé privée du certificat SSL) ne permet pas de déchiffrer des sessions passées qui ont été capturées : elle est obtenue en utilisant des clés éphémères générées dynamiquement pour chaque session et détruites après usage. Sans PFS, si un attaquant capture tout le trafic chiffré (chose triviale avec des network taps) et parvient des années plus tard à voler votre clé privée (via une fuite, une menace interne, une décision de justice), il peut revenir aux pcaps stockés et déchiffrer TOUTES les sessions historiques : un scénario connu sous le nom de "retrospective decryption". La PFS empêche cela en générant des clés de session uniques via des algorithmes Diffie-Hellman qui ne dépendent pas de la clé privée du certificat pour la dérivation : même si la clé privée est compromise, les clés de session précédentes restent sûres car elles ont été générées avec des composants éphémères qui n'existent plus. Pour garantir la PFS, n'utilisez que des cipher suites avec DHE (Diffie-Hellman Ephemeral) ou ECDHE (Elliptic Curve DHE) dans le key exchange ; évitez le RSA key exchange, qui n'offre pas la PFS car la clé de session est chiffrée avec la clé publique du serveur et déchiffrée avec la clé privée. Dans TLS 1.3, la PFS est obligatoire (toutes les cipher suites utilisent ECDHE). Dans TLS 1.2, configurez le serveur pour préférer les chiffrements ECDHE à RSA. Validez avec : openssl s_client -connect votresite.com:443 -cipher 'ECDHE' ; si la connexion réussit, la PFS fonctionne. Un avantage supplémentaire de la PFS est la compliance : de nombreux frameworks (PCI-DSS, NIST) recommandent ou exigent la PFS pour la protection des données sensibles. Inconvénient : un léger overhead de performance car les opérations DHE sont plus coûteuses en calcul que RSA, mais avec du matériel moderne (AES-NI, accélération cryptographique du CPU) l'impact est négligeable.