
PRNG prévisible d'OpenSSL Debian (CVE-2008-0166)
URL d'origine : http://metasploit.com/users/hdm/tools/debian-openssl/ (Miroir)
Exploit :
Outil recommandé : Crowbar (capable de forcer les clés SSH par force brute)
Méthode de test : ssh-vulnkey & dowkd.pl
CVE (CVE-2008-0166) :
Le 13 mai 2008, le projet Debian a annoncé que Luciano Bello avait trouvé une vulnérabilité intéressante dans le paquet OpenSSL qu'ils distribuaient. Le bug en question a été provoqué par la suppression de la ligne de code suivante de md_rand.c
MD_Update(&m,buf,j);
[ .. ]
MD_Update(&m,buf,j); /* purify complains */
Ces lignes ont été supprimées car elles provoquaient des avertissements des outils Valgrind et Purify concernant l'utilisation de données non initialisées dans tout code lié à OpenSSL. Vous pouvez voir un tel rapport adressé à l'équipe OpenSSL ici. La suppression de ce code a pour effet secondaire de paralyser le processus d'ensemencement du PRNG d'OpenSSL. Au lieu de mélanger des données aléatoires pour la graine initiale, la seule valeur « aléatoire » utilisée était l'identifiant du processus en cours. Sur la plateforme Linux, l'identifiant de processus maximal par défaut est de 32 768, ce qui donne un très petit nombre de valeurs de graines utilisées pour toutes les opérations du PRNG.
Toutes les clés SSL et SSH générées sur les systèmes basés sur Debian (Ubuntu, Kubuntu, etc.) entre septembre 2006 et le 13 mai 2008 peuvent être affectées. Dans le cas des clés SSL, tous les certificats générés devront être recréés et envoyés à l'autorité de certification pour signature. Toutes les clés d'autorité de certification générées sur un système basé sur Debian devront être régénérées et révoquées. Tous les administrateurs système qui permettent aux utilisateurs d'accéder à leurs serveurs via SSH et l'authentification par clé publique doivent auditer ces clés pour déterminer si l'une d'entre elles a été créée sur un système vulnérable. Tout outil qui s'appuyait sur le PRNG d'OpenSSL pour sécuriser les données transférées peut être vulnérable à une attaque hors ligne. Tout serveur SSH qui utilise une clé d'hôte générée par un système défectueux est sujet au déchiffrement du trafic, et une attaque de l'homme du milieu serait invisible pour les utilisateurs. Cette faille est problématique car même les systèmes qui n'utilisent pas le logiciel Debian doivent être audités au cas où une clé créée sur un système Debian serait utilisée. Les projets Debian et Ubuntu ont publié un ensemble d'outils pour identifier les clés vulnérables. Vous trouverez ces outils dans la section des références ci-dessous.
Les listes noires publiées par Debian et Ubuntu montrent à quel point l'espace des clés est réduit. Lors de la création d'une nouvelle clé OpenSSH, il n'existe que 32 767 résultats possibles pour une architecture, une taille de clé et un type de clé donnés. La raison est que la seule donnée « aléatoire » utilisée par le PRNG est l'identifiant du processus. Afin de générer les clés réelles correspondant à ces listes noires, nous avons besoin d'un système contenant les bons binaires pour la plateforme cible et d'un moyen de générer des clés avec un identifiant de processus spécifique. Pour résoudre le problème de l'identifiant de processus, j'ai écrit une bibliothèque partagée qui peut être préchargée et qui retourne une valeur spécifiée par l'utilisateur pour l'appel getpid() de libc.
L'étape suivante consistait à construire un environnement chroot contenant les binaires et bibliothèques réels d'un système vulnérable. J'ai pris un instantané d'un système Ubuntu sur le réseau local. Vous pouvez trouver l'environnement chroot complet ici. Afin de générer une clé OpenSSH avec un type, une taille en bits et un identifiant de processus spécifiques, j'ai écrit un script shell pouvant être exécuté dans l'environnement chroot. Vous trouverez ce script shell ici. Ce script est placé dans le répertoire racine du système de fichiers Ubuntu extrait. Pour générer une clé, ce script est appelé avec la ligne de commande suivante :
# chroot ubunturoot /dokeygen.sh 1 -t dsa -b 1024 -f /tmp/dsa_1024_1
Cela générera une nouvelle clé DSA OpenSSH de 1024 bits, la valeur de getpid() renvoyant toujours le nombre « 1 ». Nous avons maintenant notre première clé SSH pré-générée. Si nous poursuivons ce processus pour tous les PID jusqu'à 32 767, puis le répétons pour les clés RSA de 2048 bits, nous avons couvert les plages de clés valides pour les systèmes x86 exécutant la version boguée de la bibliothèque OpenSSL. Avec cet ensemble de clés, nous pouvons compromettre tout compte utilisateur disposant d'une clé vulnérable listée dans le fichier authorized_keys. Cet ensemble de clés est également utile pour déchiffrer une session SSH précédemment capturée, si le serveur SSH utilisait une clé d'hôte vulnérable. Des liens vers les ensembles de clés pré-générées pour les clés DSA de 1024 bits et RSA de 2048 bits (x86) sont fournis dans la section de téléchargement ci-dessous.
Ce qui est intéressant avec ces clés, c'est leur lien avec l'identifiant de processus. Étant donné que la plupart des systèmes basés sur Debian utilisent des identifiants de processus séquentiels (qui s'incrémentent depuis le démarrage du système et bouclent si nécessaire), l'identifiant de processus d'une clé donnée peut également indiquer combien de temps après le démarrage du système cette clé a été générée. En regardant l'inverse, nous pouvons déterminer quelles clés utiliser lors d'une attaque par force brute en fonction de la cible attaquée. Lorsqu'on tente de deviner une clé générée au démarrage (comme une clé d'hôte SSH), les clés avec des valeurs de PID inférieures à 200 seraient les meilleurs choix pour une force brute. Lorsqu'on attaque une clé générée par un utilisateur, on peut supposer que la plupart des clés utilisateur valides ont été créées avec un identifiant de processus supérieur à 500 et inférieur à 10 000. Cette optimisation peut accélérer considérablement une attaque par force brute sur un compte utilisateur distant via le protocole SSH.
Dans un avenir proche, ce site sera mis à jour pour inclure un outil de force brute pouvant être utilisé pour accéder rapidement à tout compte SSH qui autorise l'authentification par clé publique à l'aide d'une clé vulnérable. Les clés des fichiers de données ci-dessous utilisent la convention de dénomination suivante :
/ Algorithm / Bits / Fingerprint-ProcessID
and
/ Algorithm / Bits / Fingerprint-ProcessID.pub
Pour obtenir le fichier de clé privée correspondant à une clé publique donnée, vous devez connaître l'empreinte de la clé. Le moyen le plus simple d'obtenir cette empreinte est la commande suivante :
$ ssh-keygen -l -f targetkey.pub
2048 c6:7b:14:fa:ae:b6:89:e6:67:17:ee:04:17:b0:ec:4e targetkey.pub
Si nous ouvrons la clé publique dans un éditeur, nous pouvons également en déduire que le type de clé est RSA. Pour localiser la clé privée correspondant à cette clé publique, nous devons extraire les fichiers de données et rechercher un fichier nommé :
rsa/2048/**c67b14faaeb689e66717ee0417b0ec4e-26670**
Dans l'exemple ci-dessus, l'empreinte est représentée en hexadécimal sans les deux-points, et l'identifiant de processus est indiqué comme « 26670 ». Si nous voulons nous authentifier sur un système vulnérable qui utilise cette clé publique pour l'authentification, nous exécuterions la commande suivante :
$ ssh -i rsa/2048/c67b14faaeb689e66717ee0417b0ec4e-26670 root@targetmachine
Q : Combien de temps a-t-il fallu pour générer ces clés ?
R : J'ai utilisé 31 cœurs Xeon cadencés à 2,33 GHz. Il a fallu deux heures pour générer les clés DSA de 1024 bits et RSA de 2048 bits pour x86. Les clés RSA de 4096 bits ont pris environ 6 heures à générer. La génération des clés RSA de 8192 bits prendrait environ 100 heures à son rythme actuel et sera probablement arrêtée avant son achèvement.
Q : Partagerez-vous votre code pour répartir la génération de clés sur plusieurs processeurs ?
R : Non. Le code est codé en dur pour ce cluster spécifique et est trop mal écrit pour mériter d'être nettoyé.
Q : Combien de temps faut-il pour craquer un compte utilisateur SSH en utilisant ces clés ?
R : Cela dépend de la vitesse du réseau et de la configuration du serveur SSH. Il devrait être possible d'essayer les 32 767 clés de DSA-1024 et RSA-2048 en quelques heures, mais attention aux scripts anti-force brute sur le serveur cible.
Q : J'utilise des clés RSA de 16384 bits, peuvent-elles être cassées ?
R : Oui, ce n'est qu'une question de temps et de puissance de calcul. Le jeu de clés RSA de 8192 bits nécessiterait environ 3100 heures de temps CPU pour générer les 32 767 clés (100 heures sur les 31 cœurs que j'utilise actuellement). J'imagine que le jeu de clés RSA de 16384 bits se rapprocherait plutôt de 100 000 heures de temps CPU. Une chose à garder à l'esprit est que la plupart des clés se situent dans une plage beaucoup plus restreinte, basée sur la graine de l'identifiant de processus, et que l'ensemble complet n'aurait pas besoin d'être généré pour couvrir la majorité des clés utilisateur (la plupart des clés se trouvent dans les 3 000 premiers identifiants de processus).
Copyright © 2008 H D Moore