- En 2008, un travail visant à corriger le goulot d’étranglement des connexions SSH de GitHub a mis en lumière des collisions anormales où des utilisateurs différents avaient la même empreinte de clé SSH
- Pour éviter le problème de recherche linéaire dans un fichier
authorized_keysdevenu énorme, GitHub a patché OpenSSH afin de rechercher les empreintes de clés dans MySQL - Après le déploiement du patch, des accès en SSH aux dépôts d’autres utilisateurs sont apparus, mais la répétition des collisions d’empreintes rendait peu probable un simple bug du patch
- Le 13 mai 2008, la publication de DSA-1571-1 a confirmé que l’OpenSSL de Debian avait généré pendant environ 18 mois des clés privées prévisibles, réduisant le nombre de clés possibles à un peu plus de 32 000 par utilisateur
- Les grands incidents de sécurité commencent souvent par un petit signal disant « c’est étrange », et la vraie différence vient du temps et des compétences permettant de suivre cette piste jusqu’au bout
Un incident parti d’un goulot d’étranglement sur les connexions SSH de GitHub
- En mars 2008, l’auteur, alors chez Engine Yard, a été amené à aider GitHub, client de cette société d’hébergement centrée sur Rails, sur un problème de performance des connexions SSH
- GitHub fournissait l’accès aux dépôts Git via une connexion SSH à
git@github.com, suivie d’une authentification par clé publique - À l’époque, la gestion des clés reposait sur la méthode classique via le fichier
~/.ssh/authorized_keys- Quand SSH reçoit une demande d’authentification par clé publique, il ouvre le fichier
authorized_keyset effectue une recherche linéaire pour trouver une entrée correspondant à la clé soumise - Pour un compte classique avec seulement quelques clés, ce n’est pas un gros problème, mais chez GitHub, en pleine croissance, toutes les clés SSH s’accumulaient dans un seul gros fichier et le temps de connexion ralentissait visiblement
- Quand SSH reçoit une demande d’authentification par clé publique, il ouvre le fichier
Patch OpenSSH et recherche des clés dans MySQL
- Après avoir étudié plusieurs solutions, l’équipe GitHub et l’auteur ont choisi de patcher OpenSSH pour rechercher les clés dans une base de données MySQL à partir de leur empreinte
- Ce n’était pas une modification à prendre à la légère
- Modifier OpenSSH pouvait avoir des conséquences de sécurité critiques en cas d’erreur
- Les autres options étaient encore pires, donc cela a été jugé comme la solution « la moins mauvaise »
- Une grande partie du travail a consisté à vérifier que la modification ne compromettait pas la sécurité
- Après le déploiement au début d’avril 2008, les connexions SSH sont devenues plus rapides et le problème semblait réglé pour un bon moment
Un symptôme apparemment impossible : des empreintes de clés dupliquées
- Début mai 2008, l’équipe GitHub a signalé que certains utilisateurs pouvaient accéder en SSH aux dépôts d’autres utilisateurs
- Comme le problème touchait directement à l’authentification par clé SSH et qu’un patch OpenSSH venait juste d’être déployé, le code écrit par l’auteur est devenu le principal suspect
- Le débogage a fini par montrer que deux utilisateurs différents avaient la même empreinte de clé
- C’était pratiquement impossible à moins que les utilisateurs ne partagent volontairement la même clé
- Les utilisateurs concernés ne se connaissaient pas et affirmaient n’avoir jamais rendu leur clé publique
- Peu après, la même empreinte de clé a été observée chez une autre paire d’utilisateurs, avec cette fois une valeur différente de la première
- Il devenait difficile d’expliquer cela par un simple hasard ou par un bug de l’application web
- Une fois suffisamment établi que le patch OpenSSH n’était pas en cause, l’auteur s’est moins impliqué directement
- Il n’était pas employé par GitHub et devait aussi s’occuper d’autres clients d’Engine Yard
- L’équipe GitHub a continué à interroger les utilisateurs et a découvert un point commun : les clés SSH avaient été générées sur des systèmes Debian ou Ubuntu
La divulgation de la vulnérabilité Debian OpenSSL révèle la cause
- Le 13 mai 2008, la publication de DSA-1571-1 a clarifié la situation
- Le paquet OpenSSL de Debian générait depuis environ 18 mois des clés privées prévisibles
- La cause venait d’un nettoyage du code de génération aléatoire d’OpenSSL au cours duquel un mainteneur Debian avait involontairement fortement réduit l’espace de clés possible
- Le nombre de clés possibles qu’un utilisateur donné pouvait générer est passé d’un nombre « astronomique » à un peu plus de 32 000
- Comme de nombreux utilisateurs rejoignaient GitHub, certains ont pu générer une nouvelle clé séparée, comme le recommandaient les bonnes pratiques, et cela pouvait produire des collisions
- Cette divulgation a apporté la preuve décisive que le patch OpenSSH de l’auteur n’était pas responsable
Les travaux ultérieurs autour des weak keys de Debian
- L’auteur a ensuite eu d’autres occasions de travailler sur les weak keys de Debian
- Il exploite pwnedkeys.com, qui gère un vaste dépôt de clés compromises connues
- Il a aussi utilisé ces clés pour identifier une autorité de certification défaillante
Le temps de suivre jusqu’au bout ce qui « semble étrange »
- L’auteur n’a pas réussi à déterminer exactement quand et comment Luciano Bello a découvert la vulnérabilité devenue CVE-2008-0166
- Comme la version stable de Debian contenant le code vulnérable était sortie un an avant la divulgation, il est possible qu’il y ait eu du temps pour voir des collisions de clés, se dire « c’est étrange », puis creuser davantage
- Le backdoor XZ récent est lui aussi présenté comme un cas révélé à partir d’une observation disant « c’est étrange », suivie d’une enquête approfondie
- Le point crucial est d’avoir réellement la capacité et le temps de mener ce type d’enquête poussée
- L’auteur n’a pas pu mener lui-même cette investigation en profondeur à l’époque
- L’équipe GitHub était occupée par le développement produit et la gestion des incidents sur un service en forte croissance
- Lui-même traitait aussi des tickets de support chez Engine Yard
- Une vraie différence se produit quand, au bon moment, quelqu’un ayant les compétences, le temps et l’énergie peut suivre une piste jusqu’au bout
1 commentaires
Avis de Hacker News
À propos du passage « on n’a pas trouvé exactement quand ni comment Luciano Bello a découvert la vulnérabilité qui deviendrait plus tard CVE-2008-0166 », les logs IRC de l’époque indiquent ceci
17:23 < luciano> has really an accident. I was needing many primes numbers... 0:-)17:23 < Sesse> and you got the same numbers every time?17:25 < luciano> Sesse, not every time :PLa phrase selon laquelle « le secteur a eu de la chance qu’une personne avec les bonnes compétences, le temps et l’énergie soit là au bon moment » rend très concrètes les statistiques derrière les nombreux regards et l’idée que « la lumière du soleil est le meilleur désinfectant »
Aussi improbable que puisse paraître le fait que quelqu’un tombe par hasard sur un bug, cela peut arriver, donc cela arrive réellement
Dans du code propriétaire/fermé, cette probabilité est proche de zéro
Quelqu’un a remarqué quelque chose d’anormal et, avec le code source, a pu vérifier la situation réelle et constater qu’il s’était passé quelque chose de suspect
Les experts sécurité des principales distributions ont été contactés pour un examen plus poussé, et eux aussi ont confirmé le problème de sécurité puis ont pu réagir immédiatement
Après la divulgation publique, des personnes expertes dans divers domaines du logiciel et de la sécurité ont pu décortiquer ce qui avait été fait, comment, et quels étaient les risques
Des commits suspects laissés par le même développeur dans d’autres logiciels ont aussi été retrouvés et vérifiés, et l’analyse de leur impact se poursuit
Chaque distribution est devenue plus attentive aux détails de la façon dont une compromission peut se produire autour des archives de build, et a commencé à chercher comment détecter et empêcher des cas similaires à l’avenir
Par rapport au closed source, il est très probable que des signalements du type « le logiciel est un peu lent » auraient reçu peu d’attention avant une exploitation réelle
Même si l’entreprise finissait par comprendre, elle ne publierait sans doute qu’une explication très prudente, ne révélant qu’un minimum d’informations, ce qui nuirait fortement à la capacité de tout le secteur à éviter que cela se reproduise
Le problème, c’est qu’il est plus probable qu’on ne puisse pas les corriger, ou qu’aucune mesure ne soit prise
La plupart des gens ne savent pas quoi faire lorsqu’ils découvrent un bug. C’était aussi mon cas il y a très longtemps, et ce n’est que plus tard que j’ai compris que ce que j’avais vu était des bugs
Les détails sont flous, car cela remonte à presque 30 ans, mais je me souviens qu’en bricolant Microsoft NetMeeting sous Windows, je pouvais le faire planter avec une erreur de dépassement de tampon
À l’époque, j’étais débutant en informatique et je ne comprenais pas qu’un buffer overflow dans une application réseau était une très mauvaise chose. Beaucoup de personnes présentes depuis longtemps dans le secteur semblaient être dans le même cas
Signaler un problème de sécurité était aussi beaucoup plus difficile à l’époque, et parfois même risqué
Au final, plusieurs choses sont nécessaires : tomber sur le problème, comprendre suffisamment l’informatique en profondeur pour reconnaître qu’il est grave, disposer d’un moyen de signaler le bug à un endroit où des gens le regarderont, et avoir une culture de la sécurité qui sait quand et comment traiter ces signalements
Mais en lisant cette même phrase, je me demandais combien de bugs de sécurité critiques comme Heartbleed, CVE-2008-0166 ou l’affaire xz se produisent sans être découverts ni rendus publics
Un fait important que je n’ai appris que récemment à propos de cette vulnérabilité, c’est que ce changement n’a pas été fait dans la précipitation
Le mainteneur a publié sur la liste de diffusion OpenSSL le problème qu’il observait, a demandé des retours en proposant un correctif, et a reçu quelques réponses, y compris de l’upstream
Le résultat a été une vulnérabilité terrible, mais cela ressemble davantage à une malchance extraordinairement mauvaise, où tout le monde est passé à côté du problème
En plus, le code upstream d’OpenSSL invoquait un comportement indéfini. Un compilateur aurait donc pu légitimement effectuer exactement la même transformation que celle faite par le mainteneur Debian
À ce moment-là, cela me semblait très théorique. Je me disais qu’un compilateur ne serait sûrement pas aussi malveillant
Depuis, on comprend mieux qu’il faut éviter purement et simplement le comportement indéfini
Puis, 8 ans plus tard, Heartbleed a été découvert, et tout le monde a soudain compris à quel point OpenSSL était mal maintenu
Pour sa défense, c’était quasiment du bénévolat, et heureusement, le financement arrivé ensuite a amélioré la situation
Pour du code de génération aléatoire critique pour la sécurité, il me semble vraiment nécessaire d’avoir un test qui génère une énorme quantité de nombres aléatoires puis vérifie qu’ils sont tous uniques
Quand je lis ce genre de chose, je me demande quelle est la probabilité que ce soit déjà arrivé, ou que cela arrive un jour, dans la fonction de génération de seed de l’un des wallets matériels Bitcoin populaires
Et je me demande aussi quelles en seraient les conséquences
Au cours des 22 derniers mois, Unciphered a travaillé sur une vulnérabilité affectant BitcoinJS, largement utilisé pour générer des wallets crypto dans le navigateur, ainsi que les produits et projets créés avec ce logiciel
Au fil des années, cette vulnérabilité a entraîné la création d’un nombre considérable de wallets crypto vulnérables
Dans le cas de la vulnérabilité SSH, il faut vérifier activement si le serveur auquel on tente d’accéder possède l’une des mauvaises empreintes, alors que côté wallet cela permettrait automatiquement, depuis le réseau, d’accéder aux fonds d’autres personnes
Cela dit, dans ce cas, il est peu probable que cela ait été introduit intentionnellement
Avec la technologie actuelle, il faudrait des millions d’années de calcul, mais pour un acteur étatique capable de dépenser des sommes quasi illimitées afin de faire tourner autant de calculs en quelques semaines, ce n’est peut-être pas hors de portée
Il pourrait finir par arriver un moment où toute personne connaissant une adresse pourra accéder à n’importe quel wallet
Si quelqu’un doté d’intelligence et d’argent peut vous prendre pour cible, Bitcoin n’est pas vraiment un endroit sûr pour stocker de la valeur
La phrase « Ezra Zygmuntowitz m’a mis en relation avec GitHub, et m’a permis de prendre le temps de creuser le problème avec l’équipe GitHub » m’a fait rire
Comme je ne suis pas locuteur natif, je l’ai aussi lue comme si elle voulait dire qu’il y avait un gros problème avec l’équipe GitHub elle-même, et je m’attendais à ce que les phrases suivantes creusent ce point
Le passage « je me demande combien de temps il aurait fallu pour que quelqu’un le découvre si Luciano ne l’avait pas trouvé » me fait penser que seuls GitHub ou peut-être un gros fournisseur cloud seraient tombés dessus par hasard
Parce qu’il n’y a pas beaucoup d’endroits qui stockent des milliers ou dizaines de milliers de clés utilisateur
La question est de savoir s’il faut lire la phrase comme
(creuser le problème) (avec l’équipe GitHub), ou commecreuser (le problème concernant l’équipe GitHub)Le traiter correctement est réputé être assez difficile
Si j’ai bien compris, le générateur de nombres aléatoires d’OpenSSL était seedé avec de la mémoire de pile non initialisée et le PID, et Debian l’a fait seeder uniquement avec le PID
Mais même sans le patch Debian, ce n’était pas déjà assez dangereux ?
Dans le code d’OpenSSL, il y avait deux endroits où des blocs d’octets étaient copiés, et l’un d’eux pouvait copier des valeurs indéfinies non initialisées. C’était bien une erreur
Quelqu’un a écrit un patch pour corriger cela, puis, sans l’aide d’un LLM et uniquement par pure incompétence humaine, quelqu’un a dit : « il y a une autre copie similaire juste à côté, il faut aussi la supprimer »
Debian a intégré un patch appliquant les deux changements
Résultat : OpenSSL ne copiait désormais plus aucun octet
Ne pas copier de données non initialisées, c’est bien, mais il ne copiait plus non plus de vraie entropie aléatoire dans le pool. Oups
Dans le passage « après avoir examiné plusieurs solutions possibles, nous avons conclu que l’option la moins mauvaise était de patcher OpenSSH pour qu’il recherche les clés dans une base MySQL indexée par empreinte de clé », pourquoi MySQL et pas sqlite ?
Il s’agissait d’accélérer l’accès à ~/.ssh/authorized_keys, et c’est précisément le genre de cas pour lequel MySQL est censé briller
Il me semble qu’il aurait demandé moins de travail de patcher OpenSSH pour qu’il consulte ~/.ssh/authorized_keys.db plutôt que de le patcher pour utiliser MySQL
Il est aussi très probable que MySQL était déjà en production. Dans ce cas, il n’y aurait même pas eu de coût initial pour y stocker les données
De toute façon, la base de données des utilisateurs devait déjà exister quelque part
Indépendamment de la découverte d’un petit nombre de clés faibles, il est intéressant que des temps de connexion SSH lents soient un indice qui mérite d’être tiré pour plusieurs raisons
Un autre épisode intéressant est celui où l’on a détecté des clés RSA partageant un facteur
pouqcommun à l’aide du plus grand commun diviseur : https://factorable.net/weakkeys12.extended.pdfJe me demande si GitHub exécute encore un openssh patché
Il suffit d’acheter une copie de GitHub Enterprise, de désobfusquer les fichiers et de fouiller. La désobfuscation est un défi amusant, et pas si difficile
Malheureusement, ce n’est pas open source, donc on ne peut pas partager le code, en parler, ni mettre de lien vers GitHub
Mais si GitHub Enterprise utilise encore ce patch, il y a de fortes chances que le GitHub en production l’utilise aussi
~/.ssh/authorized_keysSi l’on se connecte en telnet au port 22 de
github.com, la chaîne de version s’affiche immédiatementCorrection : j’avais d’abord dit golang, mais après vérification, c’était Bitbucket qui utilisait golang