La distribution de système d'exploitation open source OpenBSD est bien connue des administrateurs système, en particulier de ceux qui gèrent des serveurs, pour son accent mis sur la sécurité plutôt que sur la vitesse, les fonctionnalités et les frontaux sophistiqués.
À juste titre, peut-être, son logo est un poisson-globe – gonflé, avec ses pointes prêtes à repousser tous les pirates rusés qui pourraient se présenter.
Mais l'équipe OpenBSD n'est probablement pas connue pour l'ensemble de sa distribution, mais pour la boîte à outils d'accès à distance OpenSSH qui a été écrit à la fin des années 1990 pour être inclus dans le système d'exploitation lui-même.
SSH, abréviation de Enveloppe de protection, a été créé à l'origine par un informaticien finlandais Tatu Ylonen au milieu des années 1990 dans l'espoir de sevrer les administrateurs système de l'habitude risquée d'utiliser le protocole Telnet.
Le problème avec Telnet
Telnet était remarquablement simple et efficace : au lieu de connecter des câbles physiques (ou d'utiliser un modem sur une ligne téléphonique) pour établir une connexion par téléscripteur avec des serveurs distants, vous utilisiez à la place une connexion TELetype NETwork.
Fondamentalement, les données qui circulaient habituellement dans les deux sens sur une connexion série dédiée ou une ligne téléphonique commutée étaient envoyées et reçues sur Internet, en utilisant une connexion réseau TCP à commutation de paquets au lieu d'une liaison point à point à commutation de circuits. .
Même système de connexion familier, connexions moins chères, pas besoin de lignes de données dédiées !
La faille géante de Telnet, bien sûr, était son manque total de cryptage, de sorte que détecter votre session de terminal exacte était trivial, permettant aux crackers de voir chaque commande que vous avez tapée (même les erreurs que vous avez commises et toutes les fois que vous appuyez sur [Backspace]
), et chaque octet de sortie produit…
…et, bien sûr, votre nom d'utilisateur et votre mot de passe au début de la session.
N'importe qui sur votre chemin réseau pourrait non seulement reconstruire facilement vos sessions d'administration système en temps réel sur son propre écran, mais aussi probablement altérer votre session en modifiant les commandes que vous avez envoyées au serveur distant et en simulant les réponses pour que vous ne le remarquiez pas. le subterfuge.
Ils pourraient même mettre en place un serveur imposteur, vous y attirer et rendre étonnamment difficile la détection de la tromperie.
Cryptage fort FTW
Le SSH d'Ylönen visait à ajouter une couche de cryptage et d'authentification solides à chaque extrémité d'une session de type Telnet, créant un Enveloppe de protection (c'est ce que signifie le nom, si vous vous êtes déjà demandé, bien que presque tout le monde l'appelle simplement ess-ess-aitch ces jours).
Ce fut un succès instantané et le protocole fut rapidement adopté par les administrateurs système du monde entier.
OpenSSH a rapidement suivi, comme nous l'avons mentionné ci-dessus, apparaissant pour la première fois à la fin de 1999 dans le cadre du OpenBSD 2.6 libérer.
L'équipe OpenBSD souhaitait créer une implémentation libre, fiable et open source du protocole qu'eux-mêmes et quelqu'un d'autre pourrait utiliser, sans aucune des complications de licence ou commerciales qui avaient entravé la mise en œuvre originale d'Ylönen dans les années qui ont immédiatement suivi sa sortie.
En effet, si vous exécutez le serveur Windows SSH et que vous vous y connectez à partir d'un ordinateur Linux en ce moment, vous comptez presque certainement sur l'implémentation OpenSSH aux deux extrémités.
Le protocole SSH est également utilisé dans d'autres services client-serveur populaires, notamment SCP et SFTP, abréviation de copie sécurisée et FTP sécurisé respectivement. SSH signifie vaguement "connectez-vous en toute sécurité et exécutez un shell de commande à l'autre extrémité", généralement pour les connexions interactives, car le programme Unix pour un shell de commande est généralement /bin/sh
. SCP est similaire, mais pour les fichiers CoPying, car la commande Unix file-copy est généralement appelée /bin/cp
, et SFTP porte le même nom.
OpenSSH n'est pas la seule boîte à outils SSH en ville.
D'autres implémentations bien connues incluent: libssh2, pour les développeurs qui souhaitent intégrer le support SSH directement dans leurs propres applications ; dropbear, un serveur SSH simplifié du codeur australien Matt Johnson que l'on trouve largement sur les appareils dits IoT (Internet des objets) tels que les routeurs et les imprimantes domestiques ; et PuTTY, une collection populaire et gratuite d'outils liés à SSH pour Windows par un développeur open source indépendant Simon Tatham En Angleterre.
Mais si vous êtes un utilisateur régulier de SSH, vous vous êtes presque certainement connecté à au moins un serveur OpenSSH aujourd'hui, notamment parce que la plupart des distributions Linux contemporaines l'incluent comme outil d'accès à distance standard, et Microsoft propose à la fois un client OpenSSH et un OpenSSH. serveur en tant que composants Windows officiels de nos jours.
Correction de bogue sans double
OpenSSH version 9.2 vient de sortir, et le notes de version rapport comme suit :
Cette version contient des correctifs pour […] un problème de sécurité de la mémoire. [Ce bogue] n'est pas considéré comme exploitable, mais nous signalons la plupart des défauts de mémoire accessibles par le réseau comme des bogues de sécurité.
Le bogue affecte sshd
, le serveur OpenSSH (le -d
suffixe signifie démon, le nom Unix du type de processus d'arrière-plan que Windows appelle un service):
sshd(8) : corrige un défaut de mémoire double libre de pré-authentification introduit dans OpenSSH 9.1. On pense que cela n'est pas exploitable, et cela se produit dans le processus de pré-autorisation non privilégié qui est soumis à chroot(2) et qui est en outre mis en bac à sable sur la plupart des principales plates-formes.
Un bug double-free signifie qu'un bloc mémoire que vous avez déjà renvoyé au système d'exploitation pour être réutilisé dans d'autres parties de votre programme...
… sera plus tard restitué par une partie du programme qui ne "possède" plus réellement cette mémoire, mais ne sait pas que ce n'est pas le cas.
(Ou rendu délibérément à l'invite du code qui essaie de provoquer le bogue exprès afin de transformer un vulnérabilité dans un exploiter.)
Cela peut entraîner des bogues subtils et difficiles à démêler, en particulier si le système marque le bloc libéré comme disponible lors de la première free()
se produit, l'alloue plus tard à une autre partie de votre code lorsqu'il demande de la mémoire via malloc(
), puis marque à nouveau le bloc libre lorsque l'appel superflu à free()
apparaît.
Cela vous laisse dans le genre de situation que vous rencontrez lorsque vous vous enregistrez dans un hôtel qui dit : « Oh, bonne nouvelle ! Nous pensions que nous étions complets, mais un autre client a juste décidé de partir tôt, afin que vous puissiez avoir sa chambre.
Même si la chambre est soigneusement nettoyée et préparée pour les nouveaux occupants lorsque vous entrez, et qu'elle semble donc avoir été correctement attribuée à votre usage exclusif, vous devez toujours être sûr que la carte-clé de l'invité précédent a effectivement été correctement annulée et que leur " départ anticipé » n'était pas une ruse astucieuse pour revenir plus tard le même jour et voler votre ordinateur portable.
Correction de bogue pour correction de bogue
Ironiquement, si vous regardez l'historique récent du code OpenSSH, vous verrez qu'OpenSSH avait un bogue modeste dans une fonction appelée compat_kex_proposal()
, utilisé pour vérifier le type d'algorithme d'échange de clés à utiliser lors de la configuration d'une connexion.
Mais la correction de ce bogue modeste a introduit une vulnérabilité plus grave à la place.
Soit dit en passant, la présence du bogue dans une partie du logiciel utilisée lors de la configuration d'une connexion est ce qui en fait un soi-disant pré-authentification accessible par le réseau vulnérabilité (ou bogue de pré-autorisation pour faire court).
Le bogue de double libération se produit dans le code qui doit s'exécuter après un client a lancé une session à distance, mais before tout accord de clé ou authentification a eu lieu, de sorte que la vulnérabilité peut, en théorie, être déclenchée avant que les mots de passe ou les clés cryptographiques n'aient été présentés pour validation.
Dans OpenSSH 9.0, compat_kex_proposal
ressemblait à ceci (très simplifié ici):
char* compat_kex_proposal(char* suggestion) { if (condition1) { return suggestion; } if (condition2) { suggestion = allocatenewstring1(); } if (condition3) { suggestion = allocatenewstring2(); } if (isblank(suggestion)) { error(); } return suggestion; }
L'idée est que l'appelant passe dans son propre bloc de mémoire contenant une chaîne de texte suggérant un paramètre d'échange de clé, et récupère soit une approbation pour utiliser la suggestion même qu'il a envoyée, soit une chaîne de texte nouvellement allouée avec une suggestion mise à jour .
Le bogue est que si la condition 1 est fausse mais que les conditions 2 et 3 sont toutes les deux vraies, le code alloue deux nouvelles chaînes de texte, mais ne renvoie que UN.
Le bloc mémoire alloué par allocatenewstring1()
n'est jamais libéré, et lorsque la fonction revient, son adresse mémoire est perdue à jamais, il n'y a donc aucun moyen pour un code de free()
cela à l'avenir.
Ce bloc est essentiellement abandonné, provoquant ce qu'on appelle un fuite de mémoire.
Au fil du temps, cela pourrait causer des problèmes, voire obliger le serveur à s'arrêter pour récupérer d'une surcharge de mémoire.
Dans OpenSSH 9.1, le code a été mis à jour pour tenter d'éviter d'allouer deux chaînes mais d'en abandonner une :
/* Always returns pointer to allocated memory, caller must free. */ char* compat_kex_proposal(char* suggestion){ char* previousone = NULL; if (condition1) { return newcopyof(suggestion); } if (condition2) { suggestion = allocatenewstring1(); } if (condition3) { previousone = suggestion; suggestion = allocatenewstring2(); } free(previousone); } if (isblank(suggestion()) { error(); } return suggestion; }
Cela a le bug double-free, car si la condition 1 et la condition 2 sont toutes les deux fausses, mais que la condition 3 est vraie, alors le code alloue une nouvelle chaîne à renvoyer comme réponse…
… mais libère de manière incorrecte la chaîne que l'appelant a transmise à l'origine, car la fonction allocatenewstring1()
n'est jamais appelé pour mettre à jour la variable suggestion
.
La chaîne de suggestion transmise est la mémoire qui appartient à l'appelant, et que l'appelant se libérera donc plus tard, entraînant le danger du double-gratuit.
Dans OpenSSH 9.2, le code est devenu plus prudent, gardant une trace des trois blocs de mémoire possibles utilisés : l'original suggestion
(mémoire appartenant à quelqu'un d'autre), et deux nouvelles chaînes possibles qui pourraient être allouées en cours de route :
/* Always returns pointer to allocated memory, caller must free. */ char* compat_kex_proposal(char* suggestion) { char* newone = NULL; char* newtwo = NULL; if (condition1) { return newcopyof(suggestion); } if (condition2) { newone = allocatenewstring1(); } if (condition3) { newtwo = allocatenewstring2(); } free(newone); newone = newtwo; } if (isblank(newone)) { error(); } return newone; }
Si la condition 1 est vraie, une nouvelle copie de la chaîne transmise est utilisée, afin que l'appelant puisse ultérieurement free()
la mémoire de leur chaîne transmise quand ils le souhaitent.
Si nous dépassons la condition 1 et que la condition 2 est vraie mais que la condition 3 est fausse, alors la suggestion alternative créée par allocatenewstring1()
est retourné, et le passé suggestion
la chaîne est laissée seule.
Si la condition 2 est fausse et la condition 3 est vraie, alors une nouvelle chaîne est générée et renvoyée, et la valeur transmise suggestion
la chaîne est laissée seule.
Si les deux conditions 2 et 3 sont vraies, alors deux nouvelles chaînes sont allouées en cours de route ; le premier est libéré parce qu'il n'est pas nécessaire ; le second est retourné; et le passé suggestion
la chaîne est laissée seule.
Vous pouvez RTxM pour confirmer que si vous appelez free(newone)
quand newone
is NULL
, alors "aucune opération n'est effectuée", car il est toujours sûr de free(NULL)
. Néanmoins, de nombreux programmeurs s'en prémunissent toujours avec du code tel que if (ptr != NULL) { free(ptr); }
.
Que faire?
Comme le suggère l'équipe OpenSSH, exploiter ce bogue sera difficile, notamment en raison des privilèges limités que le sshd
programme pendant qu'il configure la connexion à utiliser.
Néanmoins, ils l'ont signalé comme un trou de sécurité parce que c'est ce que c'est, alors assurez-vous d'avoir mis à jour OpenSSH 9.2.
Et si vous écrivez du code en C, rappelez-vous que peu importe votre expérience, la gestion de la mémoire est facile à se tromper…
… alors faites attention là-bas.
(Oui, Rust et ses amis modernes vont vous aider à écrire le code correct, mais parfois vous aurez toujours besoin d'utiliser C, et même Rust ne peut pas garantir vous empêcher d'écrire un code incorrect si vous programmez mal !)
- Contenu propulsé par le référencement et distribution de relations publiques. Soyez amplifié aujourd'hui.
- Platoblockchain. Intelligence métaverse Web3. Connaissance Amplifiée. Accéder ici.
- La source: https://nakedsecurity.sophos.com/2023/02/03/openssh-fixes-double-free-memory-bug-thats-pokable-over-the-network/