Date de publication du RFC : Décembre 2021
Auteur(s) du RFC : B. Laurie, A. Langley, E. Kasper, E. Messeri (Google), R. Stradling (Sectigo)
Expérimental
Réalisé dans le cadre du groupe de travail IETF trans
Première rédaction de cet article le 10 décembre 2021
Le système de gestion de certificats PKIX (dérivé des certificats X.509) a une énorme faiblesse. N'importe quelle AC peut émettre un certificat pour n'importe quel nom de domaine. Il ne suffit donc pas de bien choisir son AC, votre sécurité dépend de toutes les AC. Ce RFC propose une approche pour combler cette faille de sécurité : encourager/obliger les AC à publier « au grand jour » les certificats qu'elles émettent. Un titulaire d'un certificat qui craint qu'une AC n'émette un certificat à son nom sans son autorisation n'a alors qu'à surveiller ces publications. (Il peut aussi découvrir à cette occasion que sa propre AC s'est fait pirater ou bien est devenue méchante et émet des certificats qu'on ne lui a pas demandés. L'idée est aussi d'empêcher l'émission « discrète » de vrais/faux certificats qui seraient ensuite utilisés uniquement à certains endroits.) Ce système, dit « Certificate Transparency » (CT) avait initialement été normalisé dans le RFC 6962, que notre RFC remplace, le protocole passant à une nouvelle version, la v2 (toujours considérée comme expérimentale).
Le principe est donc de créer des journaux des certificats émis. Le journal doit être public, pour que n'importe qui puisse l'auditer (section 4 du RFC). Il doit être en mode « ajout seulement » pour éviter qu'on puisse réécrire l'histoire. Les certificats sont déjà signés mais le journal a ses propres signatures, pour prouver son intégrité. Conceptuellement, ce journal est une liste de certificats dans l'ordre de leur création. Toute AC peut y ajouter des certificats (la liste ne peut pas être ouverte en écriture à tous, de crainte qu'elle ne soit remplie rapidement de certificats bidons). En pratique, le RFC estime que la liste des AC autorisées à écrire dans le journal sera l'union des listes des AC acceptées dans les principaux navigateurs Web (voir aussi les sections 4.2 et 5.7, chaque journal est responsable de ce qu'il accepte ou pas comme soumissions).
À chaque insertion, le journal renvoie à l'AC une estampille
temporelle signéee (SCT, pour Signed Certificate
Timestamp), permettant à l'AC de prouver qu'elle a bien
enregistré le certificat. Si on a cette signature mais que le
certificat est absent du journal, l'observateur aura la preuve que
le journal ne marche pas correctement. Le format exact de cette
estampille temporelle est décrit en section 4.8. Idéalement, elle
devra être envoyée au client par les serveurs TLS, dans l'extension
TLS transparency_info
(désormais enregistrée
à l'IANA), comme preuve de la bonne foi de l'AC (cf. section
6 et notamment 6.5, car c'est plus compliqué que cela). Bien sûr,
cette validation de l'insertion dans un journal ne dispense pas de
la validation normale du certificat (un certificat peut être
journalisé et mensonger à la fois). Notez aussi que, si le serveur
TLS n'envoie pas toutes les données au client, celui-ci peut les
demander au journal (opérations /get-proof-by-hash
et
get-all-by-hash
) mais, ce faisant, il informe
le journal des certificats qui l'intéressent et donc, par exemple,
des sites Web qu'il visite.
De même, une extension à OCSP (RFC 6960) peut être utilisée pour appuyer les réponses OCSP. On peut même inclure les preuves d'inclusion dans le journal dans le certificat lui-même, ce qui permet d'utiliser des serveurs TLS non modifiés.
Les titulaires de certificats importants, comme Google, mais aussi des chercheurs, des agences de sécurité, etc, pourront alors suivre l'activité de ces journaux publics (section 8.2 du RFC). Ce qu'ils feront en cas de détection d'un certificat anormal (portant sur leur nom de domaine, mais qu'ils n'ont pas demandé) n'est pas spécifié dans le RFC : cela dépend de la politique de l'organisation concernée. Ce RFC fournit un mécanisme, son usage n'est pas de son ressort. Ce journal n'empêchera donc pas l'émission de vrais/faux certificats, ni leur usage, mais il les rendra visibles plus facilement et sans doute plus vite.
Notons que les certificats client, eux, ne sont typiquement pas journalisés (rappelez-vous que les journaux sont publics et que les certificats client peuvent contenir des données personnelles). Le serveur TLS ne peut donc pas utiliser Certificate Transparency pour vérifier le certificat du client. (Le RFC estime que le principal risque, de toute façon, est celui d'usurpation du serveur, pas du client.)
Pour que cela fonctionne, il faudra que les clients TLS vérifient que le certificat présenté est bien dans le journal (autrement, le méchant n'aurait qu'à ne pas enregistrer son vrai/faux certificat, cf. section 8.3 du RFC).
En pratique, la réalisation de ce journal utilise un arbre de Merkle, une structure de données qui permet de mettre en œuvre un système où l'ajout de certificats est possible, mais pas leur retrait, puisque chaque nœud est un condensat de ses enfants (voir aussi le RFC 8391). La section 2 du RFC détaille l'utilisation de ces arbres et la cryptographie utilisée. (Et les exemples en section 2.1.5 aident bien à comprendre comment ces arbres de Merkle sont utilisés.)
Le protocole utilisé entre les AC et le journal, comme celui
utilisé entre les clients TLS et le journal, est HTTP et le format des
données du JSON (section 5, qui décrit l'API). Ainsi, pour
ajouter un certificat nouvellement émis au journal géré sur
sunlight-log.example.net
, l'AC fera :
POST https://sunlight-log.example.net/ct/v2/submit-entry
et le corps de la requête HTTP sera un tableau JSON de certificats encodés en Base64. La réponse contiendra notamment l'estampille temporelle (SCT pour Signed Certificate Timestamp). S'il y a un problème, le client recevra une des erreurs enregistrées. Pour récupérer des certificats, le programme de surveillance fera par exemple :
GET https://sunlight-log.example.net/ct/v2/get-entries
D'autres URL permettront de récupérer les condensats cryptographiques contenus dans l'arbre de Merkle, pour s'assurer qu'il est cohérent.
Comme il n'existe (en octobre 2021) aucune mise en œuvre de la
version 2 du protocole, voici quelques exemples, utilisant des
journaux réels, et la version 1 du protocole (notez le
v1
dans l'URL). Pour trouver les coordonnées
des journaux, j'ai utilisé la liste
« officielle » du projet. Notez que tous les journaux qui y figurent ne fonctionnent pas
correctement. Notez aussi que, comme pour les AC ou les serveurs de clés PGP, il n'y a
pas de « journal de référence », c'est à chacun de choisir les
journaux où il va écrire, et qu'il va lire. Le script test-ct-logs-v1.py
teste la liste, et trouve :
50 logs are OK, 54 are currently broken
Si vous vous demandez pourquoi un même opérateur a plusieurs
journaux, c'est en partie parce qu'il n'est pas possible de faire
évoluer les algorithmes cryptographiques au sein d'un même journal
(cf. section 9 du RFC) et qu'il faut donc de temps en temps créer un
nouveau journal. Un journal est identifié par son URL, sa clé publique et
(en v2) par son OID. Par exemple, le journal
« Nimbus 2021 » de Cloudflare est en
https://ct.cloudflare.com/logs/nimbus2021/
et a
la clé
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExpon7ipsqehIeU1bmpog9TFo4Pk8+9oN8OYHl1Q2JGVXnkVFnuuvPgSo2Ep+6vLffNLcmEbxOucz03sFiematg==
(je ne donne pas l'OID, il n'existe pas encore de journaux qui
utilisent la version 2 du protocole). Voici un exemple d'utilisation
(le STH est le Signed Tree Head, la valeur de la
racine de l'arbre de Merkle, cf. section 4.2.10) :
% curl -s https://ct.cloudflare.com/logs/nimbus2021/ct/v1/get-sth | jq . { "tree_size": 408013312, "timestamp": 1634739692384, "sha256_root_hash": "7GnGjI7L6O5fn8kQKTdJG2riShNTTbcjRP2WbLoZrvQ=", "tree_head_signature": "BAMARjBEAiAQ0gb6udc9e28ykUGUzl0HV8U5NlJhPVSTUF4JtXGSeQIgcSbZ9kRgttGzpFETFem4eCv7GgUYPUUnl7lTGGFZSHM=" }
Plus de quatre cents millions de certificats, fichtre. Si on veut récupérer les deux premiers certificats journalisés :
% curl -s https://ct.cloudflare.com/logs/nimbus2021/ct/v1/get-entries\?start=0\&end=1 | jq . { "entries": [ { "leaf_input": [L'exemple est fait avec un journal v1, l'objet JSON renvoyé est différent en v2.]
Mais vous pouvez aussi utiliser Certificate
Transparency (CT) sans aller regarder du JSON. Un service en
ligne comme
vous permet de
scruter un journal. Voici par exemple l'actuel certificat de ce
blog, ou bien tous les certificats au
nom de la Banque Postale (CT est
utile pour le renseignement).
https://crt.sh
On a vu que plusieurs acteurs intervenaient, le gérant du
journal, les AC, les gens qui regardent le journal, par exemple pour
l'auditer, etc. Une utilisation courante de CT est pour surveiller
l'émission de certificats au nom de son entreprise ou de son
organisation, pour repérer les AC qui créent des certificats
incorrects. Pour éviter de programmer tout cela de zéro en partant
du RFC, on peut utiliser le service Certstream, qui sert
d'intermédiaire avec plusieurs journaux, et sa bibliothèque
Python. Ainsi, le petit script test-certstream.py
permet de détecter tous les certificats
émis pour les noms de domaine en
.fr
:
% pip3 install certstream % ./test-certstream.py ... [2021-10-23T13:21:46] pimpmydrone.fr (SAN: www.pimpmydrone.fr) [2021-10-23T13:21:51] pascal-goldbach.fr (SAN: www.pascal-goldbach.fr) [2021-10-23T13:21:52] leginkobiloba.fr (SAN: www.leginkobiloba.fr) [2021-10-23T13:21:52] promabat-distribution.fr (SAN: www.promabat-distribution.fr) [2021-10-23T13:21:53] maevakaliciak.fr (SAN: mail.maevakaliciak.fr, www.maevakaliciak.fr) [2021-10-23T13:21:55] pascal-goldbach.fr (SAN: www.pascal-goldbach.fr) [2021-10-23T13:21:56] maevakaliciak.fr (SAN: mail.maevakaliciak.fr, www.maevakaliciak.fr) [2021-10-23T13:21:57] blog.nicolas-buffart.itval.fr (SAN: euromillions-generator.itval.fr, itval.fr, loto-generator.itval.fr, password-generator.itval.fr, www.blog.nicolas-buffart.itval.fr, www.euromillions-generator.itval.fr, www.itval.fr, www.loto-generator.itval.fr, www.password-generator.itval.fr) ...
Bien sûr, cela fait beaucoup (regardez les intervalles entre deux messages). En pratique, on modifierait sans doute ce script pour ne regarder que les noms de son organisation. Ainsi, vous pouvez détecter les certificats et chercher ensuite s'ils sont légitimes (ce qui, dans certaines organisations très cloisonnées n'ira pas de soi…).
À part Certstream, Samuel Bizien Filippi me suggère CertSpotter mais qui me semble uniquement payant. Il a une API. Elle peut être utilisée par le programme check_ct_logs, qui peut être utilisé comme script de test pour les programmes de supervision comme Icinga.
Le projet « Certificate Transparency » (largement impulsé par Google) a un site officiel (lecture recommandée) et, une liste de diffusion (sans compter le groupe de travail IETF TRANS, mais qui se limitait à la normalisation, il ne parle pas des aspects opérationnels, et il a de toute façon été clos en août 2021). Questions logiciels, si vous voulez créer votre propre journal, il y a le programme de Google.
Aujourd'hui, on peut dire que « Certificate Transparency » est un grand succès. La plupart (voire toutes ?) des AC y participent, il existe de nombreux journaux publics, et ils sont fréquemment utilisés pour l'investigation numérique (voire pour le renseignement, puisqu'on peut savoir, via les journaux, les noms de domaine pas encore annoncés, ce qui a parfois été cité comme une objection contre CT). Un bon exemple est celui de l'attaque « moyen-orientale » de 2018 (mais il y a aussi l'affaire du certificat révoqué de la Poste). Par contre, un client TLS ne peut pas encore être certain que tous les certificats seront dans ces journaux, et ne peut donc pas encore refuser les serveurs qui ne signalent pas la journalisation du certificat. Et le navigateur Firefox ne teste pas encore la présence des certificats dans le sjournaux.
Un point amusant : le concept de « Certificate Transparency » montre qu'il est parfaitement possible d'avoir un livre des opérations publiquement vérifiable sans chaine de blocs. La chaine de blocs reste nécessaire quand on veut autoriser l'écriture (et pas juste la lecture) au public.
La section 1.3 du RFC résume les principaux changements entre les versions 1 (RFC 6962) et 2 du protocole :
get-all-by-hash
dans
l'API,signed_certificate_timestamp
(valeur 18) par
transparency_info
(valeur 52, et voir aussi le nouvel
en-tête HTTP
Expect-CT:
du RFC 9163,CT ne change pas de statut avec la version 2 : il est toujours classé par l'IETF comme « Expérimental » (bien que largement déployé). La sortie de cette v2 n'est pas allée sans mal (le premier document étant sorti en février 2014), avec par exemple aucune activité du groupe pendant la deuxième moitié de 2020.
Une des plus chaudes discussions pour cette v2 avait été la
proposition de changer l'API pour que les requêtes, au lieu d'aller
à <BASE-URL>/ct/v2/
partent du chemin
/.well-known/
du RFC 8615. Cette idée a finalement été rejetée, malgré le RFC 8820, qui s'oppose à cette idée de chemins
d'URL en dur.
Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)
Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)