La dernière version sécurisée de TLS étant la 1.2, sans entrer dans les détails, il serait facile de croire que TLS 1.3 n’est qu’une simple évolution, alors qu’en réalité, il s’agit d’une véritable rupture. Il aurait été préférable de l’appeler TLS 2.0, mais la dénomination est un sujet complexe (voir la vidéo à la fin, à 38:54).
Cette version apporte plusieurs changements notables :
Meilleure vitesse lors de la négociation, en réduisant les allers-retours entre le client et le serveur à un seul échange (contre deux auparavant), appelé "RTT" (Round Trip Time Resumption). Et où est le dernier R, vous demandez-vous ? Bonne question ! Si le client s'est déjà connecté au serveur, on est alors dans un cas d'optimisation appelé "0-RTT" (zero round trip) permettant de reprendre une connexion antérieure ;
Désactivation de toutes les suites cryptographiques faibles ou risquées, encore supportées par TLS 1.2. Avec TLS 1.3, vous êtes obligé d’utiliser des algorithmes forts, que ce soit pour le chiffrement, les fonctions de hachage ou les protocoles de chiffrement par blocs ;
Fin des clés statiques dans les échanges de clés RSA et Diffie-Hellman. La confidentialité persistante est désormais obligatoire, c’est-à-dire que les clés changent tout au long de l’échange et il n’est plus possible d’enregistrer le trafic, de retrouver la clé et de déchiffrer le trafic ensuite ;
Alternatives cryptographiques aux recommandations de NIST et NSA, offrant plus de confiance. Cela est dû au DualECDRBG, l’algorithme de génération de nombres pseudo-aléatoires compromis par la NSA, standardisé dans le FIPS 140-2 et largement distribué (voir "Security NSA and PRNG", "FUN NSA backdoor in OpenSSL never worked (FIPS 140-2)", "Crypto NIST removes Dual EC DRBG (NSA) from its guide", "Security Dual EC DRBG all history / NSA"). La courbe elliptique 25519 est prise en charge et présente une alternative libre aux courbes NIST et NSA ;
De même, l'algorithme de chiffrement symétrique libre ChaCha20 et l’asymétrique EdDSA sont supportés, afin de fournir des alternatives aux deux courbes de NIST et NSA ;
Exigence d'authentifier les messages chiffrés, avec en particulier 2 modes : GCM (Galois Counter Mode) et CCM (Counter with CBC-MAC). Pour plus de détails, je vous réfère au schéma de Wikipedia qui est plutôt bien fait : https://en.wikipedia.org/wiki/Galois/Counter_Mode ;
Et bien d'autres ajustements : optimisations des échanges, réduction de la quantité de données échangées en clair... Une autre différence longuement débattue est la possibilité d’intercepter des flux en les décryptant. Cela est tout à fait possible avec TLS 1.3, et un protocole dédié a même été ajouté : ETLS (Enterprise TLS), parfois appelé "TLS interception for grostocards".
https://www.etsi.org/deliver/etsi_ts/103500_103599/10352303/01.01.01_60/ts_10352303v010101p.pdf#page=8
Ce protocole, ou option de TLS 1.3, utilise, entre autres, une clé Diffie-Hellman statique et permet à une tierce partie de récupérer le trafic chiffré et une copie de cette clé. Pour simplifier, cela désactive la confidentialité persistante. Pour rendre les choses encore plus simples : c'est de la m**** 💩😋.
Si vous voulez faire une interception SSL/TLS propre, normale, éco-responsable et intelligente pour l'homme, faites ce que vous faisiez avant : faites passer tout le trafic par un proxy avec une autorité de certification qui signe dynamiquement des certificats (tous les proxys savent faire cela, que ce soit Bluecoat, Ironport ou Zscaler) et déployez la partie publique de cette autorité de certification dans le magasin de certificats de vos stations de travail, serveurs (qui ne devraient pas accéder directement à Internet en mode "party"), vos smartphones... comme une autorité racine de confiance.
Voici un document de Symantec sur l'interception "éthique" 😇 : https://www.symantec.com/content/dam/symantec/docs/other-resources/responsibly-intercepting-tls-and-the-impact-of-tls-1.3-en.pdf
En revanche, vous ne pourrez pas mettre d’IDS/IPS sur votre infrastructure exposée à Internet avec une réplication du trafic (TAP) pour le déchiffrer sans être dans la coupure (sauf en utilisant eTLS mais je ne vous raconte pas la galère). Franchement, l’intérêt d’un IDS/IPS dans ce cas me semble très limité si vous respectez les bonnes pratiques (mise à jour, partitionnement, audits...) et si vous avez par exemple un WAF ou équivalent portant le chiffrement (ou s’il est porté avant, comme par exemple avec un CDN).
TLS 1.3 est donc un très bon protocole, mais il avait encore deux faiblesses :
Pour se connecter à un service, il faut résoudre le nom de domaine, ce qui se fait avec le protocole DNS, qui n’est pas chiffré (Non, DNSSEC ne chiffre pas le DNS mais garantit seulement que l'intégrité de la réponse n'a pas été altérée) ;
Le nom de domaine que l'on essaie d’atteindre, situé dans le champ SNI de TLS, n'est pas chiffré, car il est présent dans la première requête du client, avant l'établissement du canal chiffré. Cette information seule (le nom de domaine) suffit à espionner un réseau Wi-Fi ou à effectuer une censure à l’échelle d’un État. Heureusement, ESNI permet de résoudre ce problème, ce que je vais détailler maintenant.
Trusted Recursive Resolver / TRR
Avant de parler de DNS over HTTPS, il faut introduire une notion simple : les résolveurs DNS de confiance (les résolveurs malveillants sont malheureusement fréquents, sans parler nécessairement de hacking). En gros, plusieurs éditeurs de navigateurs se sont associés avec des entreprises comme CloudFlare pour créer des services de résolution de noms de domaine avec la garantie qu'ils ne modifieront pas les réponses. Ainsi, le navigateur, qui utilisait auparavant le serveur DNS configuré dans le système d'exploitation, peut se passer de celui-ci et interroger directement des services de résolution DNS de confiance.
Il s’agit simplement d’une liste blanche de serveurs de confiance qui agissent comme relais pour les requêtes DNS. Ces serveurs relaient ensuite la demande DNS à la partie appropriée.
En fait... il y en a deux 😉 : https://mozilla.cloudflare-dns.com/dns-query et https://dns.google.com/experimental(https://wiki.mozilla.org/Trusted_Recursive_Resolver).
Je passe rapidement sur le fait que ces serveurs de confiance permettent (partiellement) la géolocalisation, utile pour les CDN, et, idéalement, c’est le serveur le plus proche de l’utilisateur qui est utilisé (avec un fonctionnement classique de type CDN).
DNS over HTTPS / DoH
Ce protocole, décrit dans le RFC 8484, nécessite la prise en charge de HTTP/2 et de ses flux afin de ne pas perdre trop de temps de réponse.
Il s'agit d'une encapsulation de DNS dans HTTP sur TLS. C’est donc le contenu d'une requête DNS classique qui est envoyé dans HTTP, encodé en base64 dans le cas des requêtes GET et sans encodage dans le cas des requêtes POST.
Voici un outil en Perl (désolé) effectuant ce type de requête : https://github.com/bagder/dns2doh
Sinon, il y a CURL (dans les versions récentes) :
arduino
Copier le code
~# curl -doh-url https://dns-server.example.com
Vous me direz que, pour pouvoir effectuer cette résolution de nom de domaine sur HTTPS, vous devez d'abord effectuer une requête DNS classique pour obtenir l'adresse IP correspondant au serveur TRR, ce qui n'est pas chiffré et ressemblerait au problème du "œuf et de la poule", mais au final, ce n’est que la résolution du serveur DNS, ce qui ne fuit aucune information sur vos vraies requêtes DNS. Pour avoir une solution parfaite, il faudrait coder en dur les adresses IP des serveurs, ce qui semble infaisable.
Encrypted Server Name Indication / ESNI
Pour chaque problème, il existe une solution. Il s'agit donc encore une fois d'une extension de TLS qui a résolu le problème des noms de domaine en clair lors de la connexion à un service : l'Encrypted Server Name Indication.
L’hôte ou l’entreprise souhaitant utiliser l’ESNI doit posséder un enregistrement DNS contenant une structure de données avec notamment une clé publique. À partir de cette clé publique est dérivée une clé symétrique utilisée pour chiffrer le nom de domaine dans la requête.
Notez que cette norme potentielle est encore en brouillon : https://datatracker.ietf.org/doc/draft-ietf-tls-esni/?include_text=1
Par exemple, voici l'enregistrement DNS pour CloudFlare (la structure de données en rouge est encore en base64) :
arduino
Copier le code
~# dig TXT _esni.cloudflare.org +short "/wH7nPYtACQAHQAgGFV9e448B0Nkg0dLwKX3cMwHMcJ4PX29THIg/kguXXEAAhMBAQAAAAAXWlIAAAAAABdcTEAAAA="
Pour plus de détails, j'ai trouvé peu de codes sources détaillant la décomposition de la structure, voici un exemple en Python : https://gist.githubusercontent.com/mosajjal/c088d03225287115a2e1fffef82ed25b/raw/fc37b51ac4067975a1c7e70dc0fb61a5781b078b/esni_creator.py
Puisque l’objectif est de cacher le nom du site visité, il est fortement recommandé d’utiliser une clé pour de nombreux services et non une par service. Comme vous pouvez le constater, cette fonctionnalité est particulièrement utile et défendue par les grands hébergeurs et les CDN comme CloudFront. Voici un article de CloudFlare à ce sujet : https://blog.cloudflare.com/esni/
TRR, DoH, ESNI... Tout cela complique énormément la cinématique de connexion à un site Web et repose sur peu d'acteurs, mais heureusement, il est encore possible de travailler avec le modèle ancien 😀.
0-RTT et replay de paquets
Grâce à l’optimisation de l’échange TLS, il est possible de rejouer le premier paquet TLS envoyé, à condition que l'attaquant soit capable d'intercepter le trafic (WiFi...) :
Du côté client, le navigateur signalera une erreur réseau, transparente pour l'utilisateur car elle est gérée par le navigateur, qui rejouera la requête ; Du côté serveur, cette requête spécifique sera vue deux fois. En fait, il est possible de rejouer n’importe quel paquet TLS : https://vnhacker.blogspot.com/2015/12/bad-life-advice-never-give-up-replay.html
Les risques sont limités car les cas d’exploitation sont très rares et la plupart des applications Web ajoutent des identifiants uniques qui ne peuvent pas être rejoués pour des requêtes sensibles telles que des transferts ou des paiements.
Comme le risque n’est pas nul, certains CDN comme CloudFlare ne répondent qu’à certaines requêtes 0-RTT telles que les GET sans paramètres et ajoutent un en-tête HTTP spécifique : "Cf-0rtt-Unique: value-unique-liant-and-session-key-and-nego-Tls". Pour les autres paquets, rien 😱.