OpenSSL fait un gros malaise

Sécurité du Cloud
OpenSSL fait un gros malaise

Décidément, les implémentations SSL tombent les unes après les autres. Après le goto fail d'Apple et son quasi homonyme dans GNULTS, c'est au tour d'OpenSSL de chuter. Une faille très sérieuse vient en effet d'être corrigée. Son matricule ? CVE-2014-0160. Son petit nom ? Heartbleed. C'est grave docteur ? Oui, très.

Une fuite de mémoire qu'on n'oubliera pas

Contrairement au bug d'Apple, le problème identifié dans OpenSSL n'est pas trivial à comprendre. On n'entendra donc probablement pas autant de railleries, mais cela n'enlève rien au fond du problème. Les chercheurs ayant identifié le bug ont vraisemblablement fait le même constat, et ils ont donc monté un site inhabituellement élégant pour parler du problème de façon pédagogique et éviter qu'on n'oublie ce bug trop rapidement.

Sur ce site, ils expliquent qu'en exploitant cette nouvelle faille, il est possible d'accéder à des mots de passe, des clés de chiffrement, des emails, des documents confidentiels, ... la liste est assez effrayante. La vulnérabilité permet en effet d'abuser d'une fuite de mémoire pour accéder à des choses qui auraient dû rester secrètes. Penchons-nous donc un peu sur les détails pour essayer d'y voir plus clair.

De battre son coeur s'est arrêté

Le code incriminé gère une extension de TLS appelée heartbeet (battement de coeur). Pour simplifier, lorsqu'un message de ce type est envoyé à un processus utilisant OpenSSL, il est renvoyé tel quel, indiquant à la source que la destination est bien présente et qu'elle reçoit bien ses messages. Jusqu'ici, on voit mal ce qui pourrait poser problème.

Et pourtant il y en a un gros. Une fois n'est pas coutume, je vais encore vous faire lire du code C : si vraiment vous n'aimez pas ça, rassurez-vous ça sera bref :

Code C1

Code C2

Quelques explications :

  • payload est la taille de la requête, que l'on a extraite et convertie en valeur entière non signée. Elle ne peut pas excéder la valeur maximale représentée avec 16 bits (65535 donc).
  • pl désigne le message d'origine, que l'on veut copier.
  • bp est la mémoire dans laquelle on va stocker la réponse.

L'appel à la function memcpy ci-dessus effectue l'opération suivante : payload octets sont copiés de la requête vers la réponse. Mais que se passe-t-il si quelqu'un fait une requête dont la taille déclarée est de 65535 mais dont la taille réelle est d'un seul octet ? Ca plante ? Pas du tout.

Plutôt que de planter, le code fait ce qui lui est demandé : lire 65535 octets en mémoire. Et si la requête d'origine fait 1 octet, les 65534 octets suivants seront... intéressants.

64k should be enough for everybody

Résumons : il est possible d'envoyer de petits messages ("battements de coeur") à n'importe quelle application utilisant l'implémentation TLS d'OpenSSL pour chiffrer les communications et d'obtenir en retour de moins petits messages contenant une partie de la mémoire du processus OpenSSL.

Que peut-on trouver dans la mémoire du processus OpenSSL ? Beaucoup de choses. Et des choses qui doivent rester secrètes à priori. On appelle ce processus pour chiffrer les données de l'application, ou pour les déchiffrer. Ces données sont temporairement stockées en mémoire, avant d'être traitées, puis envoyées. Il y a donc des chances que dans les 64 kilos-octets de données retournés dans la réponse du "battement de coeur", on trouve des données confidentielles. Et bien entendu, rien n'empêche de bombarder continuellement un serveur de "battements de coeur" pour récupérer bien plus que 64ko de mémoire. Du reste, personne ne s'en apercevra - aucune trace n'étant générée.

Et d'un coup, on comprend mieux pourquoi cette faille est vraiment très grave. Elle remet en question toutes les garanties de confidentialité du chiffrement TLS effectué par OpenSSL : inutile de d'espionner les communications, il suffit de "prendre le pouls" d'une application utilisant OpenSSL pour lire sa mémoire, bloc par bloc, et y chercher les données croustillantes.

Mon serveur est-il malade ? Y a-t-il un remède efficace ?

Plusieurs sites proposent de tester votre serveur afin de déterminer s'il est vulnérable. Compte tenu de l'impact de la vulnérabilité, cependant, il serait dommage de faire fuir volontairement vos données confidentielles dans le nuage. Les plus paranoïaques préféreront donc utiliser un outil local, comme celui de Filippo Valsorda par exemple, dont vous pouvez vous procurer le code sur github.

Si vous êtes vulnérable, le plus simple des remèdes est aussi le plus courant : mettez à jour OpenSSL. Toutes les versions d'OpenSSL 1.0.1 sont affectées jusqu'à 1.0.1g. Certains cyniques diront qu'on peut également utiliser la vieille version d'OpenSSL (0.9.8y), qui ne dispose pas de la fonctionnalité TLS heartbeat, mais je me garderais bien de vous inviter à utiliser du code qui n'est plus activement développé. D'autant que la version 1.0.1g corrige également une autre vulnérabilité, beaucoup moins simple à exploiter et décrite de façon parfaitement académique par les chercheurs l'ayant découverte. Mais autant éviter de prendre des risques, arrivé à ce stade...

Enfin, il sera peut-être nécessaire de régénérer votre certificat SSL. Dans certaines conditions, il est en effet possible que la clé privée associée à votre certificat ait pu être lue. Si vous décidez de révoquer votre certificat, assurez-vous toutefois que votre autorité de certification a traité le problème en amont; si le certificat racine est compromis, il apparaît bien futile de changer le vôtre...