Une vulnérabilité a été identifiée dans le noyau Linux (CVE-2022-0847), permettant d'écrire le contenu du cache de pages pour n'importe quel fichier, y compris ceux en mode lecture seule, ouverts avec le drapeau O_RDONLY ou situés sur des systèmes de fichiers montés en lecture seule. Sur le plan pratique, cette vulnérabilité peut être utilisée pour injecter du code dans des processus arbitraires ou altérer des données dans des fichiers ouverts. Par exemple, il est possible de modifier le contenu du fichier authorized_keys pour le processus sshd. Un prototype d'exploit est disponible pour le test.
Le problème a été baptisé Dirty Pipe, par analogie avec la vulnérabilité critique Dirty COW découverte en 2016. Il est noté que Dirty Pipe présente un niveau de danger similaire à celui de Dirty COW, mais est beaucoup plus simple à exploiter. La vulnérabilité a été identifiée lors de l'examen de plaintes concernant des fichiers téléchargés via le réseau qui étaient parfois corrompus dans le système, qui charge des archives compressées à partir d'un serveur de logs (37 corruptions en 3 mois sur un système très chargé), lors de la préparation desquelles l'opération splice() et des canaux sans nom ont été utilisés.
La vulnérabilité se manifeste à partir du noyau Linux 5.8, sorti en août 2020, c'est-à-dire qu'elle est présente dans Debian 11, mais n'affecte pas le noyau de base d'Ubuntu 20.04 LTS. Les noyaux RHEL 8.x et openSUSE/SUSE 15 sont initialement basés sur des branches anciennes, mais il se peut que le changement à l'origine du problème ait été rétroporté (aucune donnée précise n'est disponible pour l'instant). Les mises à jour des paquets dans les distributions peuvent être suivies sur ces pages : Debian, SUSE, Ubuntu, RHEL, Fedora, Gentoo, Arch Linux. Un correctif pour la vulnérabilité a été proposé dans les versions 5.16.11, 5.15.25 et 5.10.102. Le correctif est également inclus dans le noyau utilisé sur la plateforme Android.
La vulnérabilité est causée par l'absence d'initialisation de la valeur «buf->flags» dans le code des fonctions copy_page_to_iter_pipe() et push_pipe(), alors que la mémoire allouée pour la structure n'est pas nettoyée. En conséquence, avec certaines manœuvres sur des canaux sans nom, il est possible que la valeur dans «buf->flags» provienne d'une autre opération. En utilisant ce détail, un utilisateur local non privilégié peut faire en sorte que le drapeau contienne la valeur PIPE_BUF_FLAG_CAN_MERGE, ce qui permet d'organiser l'écriture de données dans le cache de pages par une simple écriture de nouvelles données dans un canal sans nom spécialement préparé.
Pour qu'une attaque réussisse, le fichier cible doit être accessible en lecture, et comme lors de l'écriture dans un pipe, les droits d'accès ne sont pas vérifiés, il est possible de remplacer dans le cache de page y compris pour des fichiers situés sur des partitions montées en mode lecture seule (par exemple, pour les fichiers d'un CD-ROM). Après le remplacement des informations dans le cache de page, le processus obtient des données non réelles mais altérées lors de la lecture des données du fichier.
L'exploitation consiste à créer un canal sans nom et à le remplir de données arbitraires afin de déclencher le drapeau PIPE_BUF_FLAG_CAN_MERGE dans toutes les structures en anneau qui lui sont associées. Ensuite, les données sont lues à partir du canal, mais le drapeau reste actif dans toutes les instances de la structure pipe_buffer dans les structures en anneau pipe_inode_info. Ensuite, un appel à splice() est effectué pour lire les données du fichier cible dans le canal sans nom, en commençant à partir du décalage requis. En raison du drapeau PIPE_BUF_FLAG_CAN_MERGE, les données écrites dans ce canal sans nom écraseront les données dans le cache de page, au lieu de créer une nouvelle instance de la structure pipe_buffer.
Source : opennet.ru
