web-dev-qa-db-fra.com

Comment l'exploit Heartbleed est-il même possible?

J'ai lu la vulnérabilité Heartbleed OpenSSL et je comprends le concept. Cependant, ce que je ne comprends pas, c'est la partie où nous passons 64 Ko comme longueur et le serveur renvoie 64 Ko de données aléatoires car il ne vérifie pas si nous avons vraiment passé 64 Ko de message d'écho ou 1 octet.

Mais comment est-il même possible qu'un processus sur un serveur retourne 64 Ko de données aléatoires de la RAM?

Le système d'exploitation n'est-il pas censé empêcher l'accès au vrai RAM et autoriser uniquement l'accès à la mémoire virtuelle lorsqu'un processus ne peut pas accéder au contenu de la mémoire d'autres processus?

OpenSSL fonctionne-t-il en mode noyau et a donc accès à toute la RAM?

Je m'attendrais à une erreur de segmentation si un processus tentait d'accéder à une mémoire qu'il n'avait pas explicitement allouée. Je peux comprendre l'obtention de 64 Ko de données aléatoires à partir du processus qui exécute le programme OpenSSL lui-même, mais je ne vois pas comment il peut même voir l'intégralité du RAM du serveur pour pouvoir l'envoyer). retour au client.

MISE À JOUR: @ commentaire de paj28, oui ce sont précisément les fausses informations qui m'ont amené à m'interroger à ce sujet. Comme vous l'avez dit, même l'avis officiel de heartbleed.com le formule de manière trompeuse (bien que je dirais qu'ils l'ont fait parce qu'il est destiné à un public beaucoup plus large que juste nous, les techniciens et qu'ils voulaient rester simple)

Pour référence, voici comment Heartbleed.com le dit (c'est moi qui souligne):

Le bogue Heartbleed permet à quiconque sur Internet de lire la mémoire des systèmes protégé par les versions vulnérables du logiciel OpenSSL.

Pour toute personne technique qui impliquerait le RAM complet de la machine virtuelle/physique).

126
Talha Sayed

Le commentaire de @ paj28 couvre le point principal. OpenSSL est une bibliothèque partagée, elle s'exécute donc dans le même espace d'adressage en mode utilisateur que le processus qui l'utilise. Il ne peut pas voir la mémoire des autres processus du tout; tout ce qui suggérait le contraire était faux.

Cependant, la mémoire utilisée par OpenSSL - ce qui se trouve probablement près du tampon sur lequel Heartbleed sur-lit - est pleine de données sensibles. Plus précisément, il est susceptible de contenir à la fois le texte chiffré et le texte en clair de toute transmission récente ou à venir. Si vous attaquez un serveur, cela signifie que vous verrez les messages envoyés au serveur par d'autres et les réponses du serveur à ces messages. C'est un bon moyen de voler des jetons de session et des informations privées, et vous attraperez probablement les informations de connexion de quelqu'un aussi. Les autres données stockées par OpenSSL comprennent des clés de chiffrement symétriques (utilisées pour le chiffrement et l'intégrité des données en masse via TLS) et des clés privées (utilisées pour prouver l'identité du serveur). Un attaquant qui vole ceux-ci peut écouter (et même modifier) ​​la communication TLS compromise en temps réel, ou réussir à usurper l'identité du serveur, respectivement (en supposant une position d'homme au milieu sur le réseau).

Maintenant, il y a une chose étrange à propos de Heartbleed qui la rend pire que vous ne le pensez. Normalement, il y a de fortes chances que si vous essayez de lire 64k de données à partir d'une adresse de tas arbitraire dans un processus, vous tombiez sur une adresse mémoire non allouée (la mémoire virtuelle n'est sauvegardée par rien et donc inutilisable). rapidement. Ces trous dans un espace d'adressage de processus sont assez courants, car lorsqu'un processus libère de la mémoire dont il n'a plus besoin, le système d'exploitation récupère cette mémoire afin que d'autres processus puissent l'utiliser. Sauf si votre programme perd de la mémoire comme un tamis, il n'y a généralement pas beaucoup de données en mémoire autres que celles actuellement utilisées. Tenter de lire la mémoire non allouée (par exemple, tenter d'accéder à la mémoire qui a été libérée) provoque une violation d'accès en lecture (sous Windows)/une erreur de segmentation (sur * nix), ce qui entraînera un plantage du programme (et il se bloque avant qu'il ne puisse le faire) quelque chose comme envoyer des données). C'est toujours exploitable (comme une attaque par déni de service), mais ce n'est pas aussi mauvais que de laisser l'attaquant obtenir toutes ces données.

Avec Heartbleed, le processus ne se bloquait presque jamais. Il s'avère qu'OpenSSL, décidant apparemment que les bibliothèques de gestion de la mémoire de la plateforme étaient trop lentes (ou quelque chose; je ne vais pas essayer de justifier cette décision), pré-alloue une grande quantité de mémoire et utilise ensuite ses propres fonctions de gestion de la mémoire à l'intérieur de cela. Cela signifie plusieurs choses:

  • Quand OpenSSL "libère" la mémoire, elle n'est pas réellement libérée en ce qui concerne le système d'exploitation, de sorte que la mémoire reste utilisable par le processus. Le gestionnaire de mémoire interne d'OpenSSL peut penser que la mémoire n'est pas allouée, mais en ce qui concerne le système d'exploitation, le processus utilisant OpenSSL possède toujours cette mémoire.
  • Quand OpenSSL "libère" de la mémoire, à moins qu'il n'efface explicitement les données avant d'appeler sa fonction free, cette mémoire conserve toutes les valeurs qu'elle avait avant d'être "libérée". Cela signifie que de nombreuses données qui ne sont pas encore utilisées peuvent être lues.
  • Le tas de mémoire utilisé par OpenSSL est contigu; il n'y a pas de lacunes en ce qui concerne le système d'exploitation. Il est donc très peu probable que la sur-lecture du tampon se retrouve dans une page non allouée, il est donc peu probable qu'elle se bloque.
  • L'utilisation de la mémoire d'OpenSSL a une localité très élevée - c'est-à-dire qu'elle est concentrée dans une plage d'adresses relativement petite (le bloc pré-alloué) - plutôt que d'être répartie dans l'espace d'adressage au gré de l'allocateur de mémoire du système d'exploitation. En tant que tel, la lecture de 64 Ko de mémoire (ce qui n'est pas beaucoup, même à côté de la plage typique de 2 Go d'un processus 32 bits, et encore moins de l'énorme plage d'un processus 64 bits) est susceptible d'obtenir beaucoup de données qui sont actuellement (ou était récemment) en cours d'utilisation, même si ces données résident dans le résultat d'un ensemble d'allocations soi-disant distinctes.
209
CBHacking

Je m'attendrais à une erreur de segmentation si un processus tentait d'accéder à une mémoire qu'il n'avait pas explicitement allouée

C'est là que réside l'idée fausse.

Tout accès à la mémoire cassé pourrait entraîner une erreur de segmentation, mais en fait si l'adresse mémoire demandée se trouve dans l'espace d'adressage du processus actuel (par exemple, une variable que vous venez de libérer), cela est hautement improbable.

C'est pourquoi vous ne devez pas vous fier aux erreurs de segmentation pour trouver les bogues d'accès à la mémoire!