Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2022-0185-Case-Study — Étude de cas pédagogique et parcours de développement d'exploit pour CVE-2022-0185, un dépassement de tampon basé sur le tas du noyau Linux permettant une escalade de privilèges locale. Inclut un POC, un débogage QEMU et un exploit Ubuntu avec une analyse technique détaillée. | Kitploit
Outils/GitHubGitHub/dcheng69/cve-2022-0185-case-study
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationCTFApprentissage et ÉducationExploitation de BinairesLabs et Pratique
GitHubdcheng69/cve-2022-0185-case-study

CVE-2022-0185-Case-Study

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Étude de cas pédagogique et parcours de développement d'exploit pour CVE-2022-0185, un dépassement de tampon basé sur le tas du noyau Linux permettant une escalade de privilèges locale. Inclut un POC, un débogage QEMU et un exploit Ubuntu avec une analyse technique détaillée.

Voir le dépôt
31il y a 2 ansPas encore vérifié

CVE-2022-0185-Case-Study

Cette étude de cas est le résultat d'un travail dans le cadre du cours ECE 9069: Introduction to Hacking : https://whisperlab.org/introduction-to-hacking/

Présentation de CVE-2022-0185

CVE-2022-0185 est un défaut de dépassement de tampon basé sur le tas (heap-based buffer overflow) découvert dans la manière dont la fonction legacy_parse_param de la fonctionnalité Filesystem Context du noyau Linux vérifiait la longueur des paramètres fournis. Un utilisateur local non privilégié (dans le cas où les espaces de noms non privilégiés sont activés, sinon nécessite le privilège CAP_SYS_ADMIN dans l'espace de noms) capable d'ouvrir un système de fichiers qui ne prend pas en charge l'API Filesystem Context (et qui retombe donc sur la gestion héritée) pourrait exploiter ce défaut pour élever ses privilèges sur le système. [1]

Après la divulgation de cette vulnérabilité, un correctif a été publié pour résoudre ce bogue :

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=722d94847de2

https://ubuntu.com/security/CVE-2022-0185#impact-score

Il existe un article détaillé de l'explorateur : https://www.hackthebox.com/blog/CVE-2022-0185:_A_case_study

Dans ce dépôt, j'expliquerai les étapes de base et les informations contextuelles associées pour reproduire cette vulnérabilité. De plus, si quelque chose vous semble flou, vous pouvez m'envoyer un courriel à [email protected], je serai ravi de répondre à vos questions.

1. Introduction

La vulnérabilité CVE-2022-0185 a été publiée le 11/02/2022, avec un score de base CVSS 3.x de 8,4 (Élevé). [1] Cette vulnérabilité est un dépassement de tampon basé sur le tas, causé par un dépassement négatif d'entier non signé (unsigned integer underflow).

La vulnérabilité a été introduite dans le noyau Linux v5.1, affectant toutes les distributions Linux avec des versions de noyau supérieures à 5.1. Par exemple, Ubuntu 20.04 LTS (focal) était vulnérable à ce bogue. Cependant, un correctif a été publié et est disponible depuis la version 5.4.0-96.109. [3]

L'exploitation de cette vulnérabilité permet à un utilisateur local non privilégié d'élever ses privilèges sur le système, compromettant potentiellement l'ensemble du système. [1] [2] Voici une analyse détaillée du score CVSS : Score de base : 8,4, indiquant un risque de sécurité significatif nécessitant une attention immédiate. Score d'impact : 5,9, suggérant des dégâts potentiels substantiels en cas d'exploitation. Les valeurs élevées de confidentialité, d'intégrité et de disponibilité contribuent à ce score. Score d'exploitabilité : 2,5, suggérant une exploitabilité relativement élevée. Le vecteur d'attaque local, ainsi que les valeurs élevées d'intégrité et de disponibilité, contribuent à ce score.

Les tableaux 1.1 et 1.2 fournissent plus d'informations sur ces scores et leurs composants.

Gravité CVSS v3.1Valeur
Score de base8,4 ÉLEVÉ
Score d'impact5,9
Score d'exploitabilité2,5

Tableau 1.1 Scores de gravité CVSS[1]

Tableau 1.2 Vecteur CVSS[1]

2. Contexte et concepts associés

2.1 Dépassement négatif d'entier non signé

2.1.1 Complément à deux

Il existe deux types d'entiers dans les ordinateurs modernes : signés et non signés. La représentation des nombres signés implique généralement une opération appelée complément à deux. [4] "Le complément à deux utilise le chiffre binaire ayant la plus grande valeur de position comme signe pour indiquer si le nombre binaire est positif ou négatif" [4]

L'introduction du complément à deux permet de convertir le calcul de la soustraction en addition, simplifiant ainsi la conception et l'implémentation du CPU. La génération du complément à deux d'un entier implique trois étapes : [4]

  • Étape 1 : "Commencer par la représentation binaire du nombre, le bit de tête étant un bit de signe" ;
  • Étape 2 : "Inverser tous les bits" ;
  • Étape 3 : "Ajouter 1 au nombre inversé complet, ignorer les éventuels débordements"

La figure 2.1.1.1 montre le processus de conversion dans un schéma avec un exemple concret de conversion de "-6" au format complément à deux.

twos_complement.drawio

Fig 2.1.1.2 Addition à l'aide du complément à deux

La figure 2.1.1.2 montre le processus d'ajout du complément à deux de '-6' à '+6'. Cela démontre comment l'utilisation du complément à deux permet d'utiliser l'addition comme substitut de la soustraction.

twos_complement-Page-2.drawio

Fig 2.1.1.2 Addition à l'aide du complément à deux

2.1.2 Représentation des nombres dans la RAM

À partir de la section 2.1.1, nous comprenons déjà ce qu'est le complément à deux. Examinons maintenant le scénario du dépassement négatif d'un entier non signé dans les ordinateurs. Dans les ordinateurs modernes, lors de l'utilisation de nombres non signés, le bit le plus significatif n'est pas traité comme un bit de signe ; il fait plutôt partie du nombre non signé lui-même. Cette situation signifie que lors de l'exécution d'une soustraction avec un nombre non signé, nous devons être prudents, car cela peut conduire à une condition connue sous le nom de dépassement négatif d'entier non signé. [5]

La figure 2.1.2.1 illustre la situation de soustraction de 6 à 5 pour un nombre non signé de 8 bits. Le résultat final est 255 en raison du bouclage du nombre non signé. Lorsque ce dépassement négatif se produit dans une instruction conditionnelle, il peut potentiellement perturber le fonctionnement de cette instruction.

twos_complement-Page-3.drawio

Fig 2.1.2.1 Dépassement négatif d'entier non signé

2.2 Mémoire du noyau Linux

2.2.1 Slabs dans la mémoire tas

Dans le noyau Linux, l'allocateur de Slabs est un mécanisme de gestion de la mémoire utilisé pour l'allocation et la désallocation efficaces de petits blocs de mémoire. Il offre des performances en maintenant plusieurs caches de Slabs, chacun contenant des blocs de mémoire de taille fixe. Typiquement, kmalloc-32 alloue 32 octets de mémoire, c'est un slab kmalloc-32, tandis que kmalloc-4k alloue 4096 octets de mémoire, c'est un slab kmalloc-4k. [6]

De plus, l'allocation par slabs dans le noyau Linux implique généralement l'allocation de mémoire à partir d'un espace d'adressage contigu au sein de la région de mémoire tas du noyau. Cette adresse contiguë est gérée par le noyau et est utilisée pour allouer de la mémoire à divers objets et structures de données du noyau. La figure 2.2.1.1 montre la disposition des slabs dans la mémoire du noyau Linux.

img

Fig 2.2.1.1 Allocateur de Slabs dans Linux [7] (L'auteur de cette figure est https://leviathan.vip/)

3 Analyse technique de la vulnérabilité

3.1 Preuve de concept

Si vous souhaitez reproduire le processus avec un noyau Linux compilé vous-même, veuillez lire les fichiers markdown suivants pour obtenir les informations contextuelles :

  1. Lisez d'abord le markdown sur la façon de compiler un noyau Linux : https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/compile_linux/compile.md
  2. Lisez ensuite le markdown sur la façon de préparer un système de fichiers ram pour effectuer le POC : https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/ramfs/ramfs.md
  3. Suivez enfin le markdown du POC : https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/Poc/poc.md

Remarque :

Tous les fichiers markdown ainsi que le code et les scripts se trouvent dans différents dossiers de ce dépôt ; chaque dossier possède son propre fichier markdown, lisez-le avant d'essayer de faire quoi que ce soit !

3.1.1 Dépassement négatif non signé dans le noyau

Dans la section 2.1, nous avons expliqué comment fonctionne le dépassement négatif non signé. Maintenant, nous allons examiner la fonction du noyau qui contient cette vulnérabilité.

L'utilisateur "clubby789" a découvert une vulnérabilité dans la fonction du noyau legacy_parse_param. Cette fonction est principalement responsable de l'analyse des paramètres passés au noyau. Dans CVE-2022-0185, elle était invoquée après avoir utilisé fsopen pour ouvrir un descripteur de fichier, suivi de l'utilisation de la fonction fsconfig pour passer les paires clé-valeur de configuration au noyau. Une version simplifiée de legacy_parse_param est présentée dans le code suivant. [2]```c static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param) { struct legacy_fs_context *ctx = fc->fs_private; // [1] unsigned int size = ctx->data_size; // [2] size_t len = 0; int ret; [ ... ] switch (param->type) { case fs_value_is_string: len = 1 + param->size; // [3] case fs_value_is_flag: len += strlen(param->key); break; default: return invalf(fc, "VFS: Legacy: Parameter type for '%s' not supported", param->key); } if (len > PAGE_SIZE-2-size) return invalf(fc, "VFS: Legacy: Cumulative options too large"); // [4] [ ... ] if (!ctx->legacy_data) { ctx->legacy_data = kmalloc(PAGE_SIZE, GFP_KERNEL); // [5] if (!ctx->legacy_data) return -ENOMEM; } ctx->legacy_data[size++] = ','; // [6] len = strlen(param->key); memcpy(ctx->legacy_data + size, param->key, len); size += len; if (param->type == fs_value_is_string) { ctx->legacy_data[size++] = '='; memcpy(ctx->legacy_data + size, param->string, param->size); size += param->size; } ctx->legacy_data[size] = '\0'; ctx->data_size = size; ctx->param_type = LEGACY_FS_INDIVIDUAL_PARAMS; return 0; }

root@kitploit:~
From above code snippet, we can see that lines [1] and [2] set up the context of the code, while line [4] contains the statement where unsigned underflow occurs. Line [5] handles heap slab allocation, and lines [6] and [7] are responsible for populating data into the allocated slab. Notably, line [6] adds a comma (',') as a separate delimiter, and an equals sign ('=') is also added, resulting in two extra bytes beyond the actual data size.

In line [4], the variables inside the if statement contain PAGE_SIZE (a macro set to 4096) and size (an unsigned 64-bit number). When an unsigned number accumulates to 4095, underflow occurs, causing the if statement to always evaluate to false. This allows for an out-of-bounds write to the neighboring slab. The underflow is caused by subtracting an unsigned number, resulting in 4096 - 4095, which yields an unsigned number of 18446744073709551615.[2]

The result of `18446744073709551615` is explained in the following text:```c
if (len > PAGE_SIZE-2-size) return invalf(fc, "VFS: Legacy: Cumulative options too large");

Remarquez qu'ici, PAGE_SIZE est égal à 4096 octets, et le 2 correspond aux caractères , et = ajoutés pour séparer chaque paire clé-valeur. Le problème est que size est une valeur non signée, donc lorsque size atteint 4095, l'expression PAGE_SIZE-2-size sera égale à valeur signée : -1, mais pour valeur non signée : 18446744073709551615 à cause du complément à 2 comme le montre le diagramme suivant ! [3]

poc.drawio

Par conséquent, l'instruction if ci-dessus sera toujours fausse, ce qui signifie que le reste des données sera copié sur le tas au-delà de la slab que nous avons allouée !

3.1.2 Analyse du code du POC

Après avoir compris comment ce dépassement de capacité d'entier non signé peut se produire, nous pouvons procéder à la construction d'un code de preuve de concept (POC) pour démontrer la vulnérabilité.

L'utilisateur « clubby789 » nous fournit un code POC détaillé, illustré dans l'extrait de code suivant. Le code est concis ; il ouvre d'abord un descripteur de fichier appelé ext4, puis utilise fsconfig à plusieurs reprises pour alimenter des données dans le noyau.

Deux choses à noter ici :

  • L'appel à fsopen pour ouvrir ext4 nécessite les privilèges CAP_SYS_ADMIN. Par conséquent, dans une exploitation ultérieure, nous utiliserons unshare pour obtenir ces privilèges. Cependant, pour cette preuve de concept (POC), nous exécuterons simplement le programme avec les privilèges root.
  • Chaque paire clé-valeur que nous insérons dans le noyau a une longueur de 33. Cependant, la fonction legacy_parse_param insère une virgule (',') au début et un signe égal ('=') entre la clé et la valeur. En conséquence, la taille réelle occupée pour chaque cycle est de 35.```c #define _GNU_SOURCE #include <sys/syscall.h> #include <stdio.h> #include <stdlib.h> #ifndef __NR_fsconfig #define __NR_fsconfig 431 #endif #ifndef __NR_fsopen #define __NR_fsopen 430 #endif #define FSCONFIG_SET_STRING 1 #define fsopen(name, flags) syscall(__NR_fsopen, name, flags) #define fsconfig(fd, cmd, key, value, aux) syscall(__NR_fsconfig, fd, cmd, key, value, aux) int main(void) { char* key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; // 33 characters [1] int fd = 0; fd = fsopen("ext4", 0); // [2] if (fd < 0) { puts("Open failed!\n"); exit(-1); } for (int i = 0; i < 130; i++) { fsconfig(fd, FSCONFIG_SET_STRING, "\x00", key, 0); //[3] } return 0; }
root@kitploit:~
Dans la section 3.1.1, nous avons mentionné que 4095 octets de données doivent être peuplés avant d'observer l'écriture hors limites. Étant donné que chaque cycle ne peuple que 35 octets, nous devons effectuer l'opération 117 fois (4095 / 35) avant d'observer la mémoire du tas pour terminer la preuve de concept.

### 3.1.3 POC avec QEMU

Dans ce dépôt : GitHub - dcheng69/CVE-2022-0185-Case-Study, nous avons fourni un script shell appelé poc.sh pour faciliter le processus de débogage. Veuillez lire le fichier markdown dans le dossier Poc avant de commencer la configuration.

Puisque legacy_parse_param est une fonction du noyau, vous devrez déboguer une fonction du noyau. Pour ce faire, vous devez compiler les sources du noyau pour obtenir les symboles et le code source nécessaires. Nous avons également fourni un fichier markdown détaillé pour vous guider dans ce processus. Veuillez vous référer au dossier Compile_linux pour plus de détails.

Dans la Fig. 3.1.3.1, nous avons démontré qu'après avoir peuplé 4095 octets de données dans le tas du noyau, nous avons réussi à déclencher une écriture hors limites en exploitant un dépassement négatif non signé (unsigned underflow). De plus, nous avons peuplé un total de 4130 octets de données dans un slab kmalloc-4k, corrompant avec succès le slab voisin. Bien que dans cet exemple le slab voisin ne contienne aucune information (tous des zéros), nous pouvons construire soigneusement notre code pour tirer parti de cette fonctionnalité afin d'écrire des données malveillantes. Nous montrerons comment y parvenir dans la section 3.2 Exploit.

![image-20240417133914423](https://assets.kitploit.com/production/public/readmes/24547/2a679fe489b44c6f1f46040bf6c74c7481d6bd4eaf70a594830cc4c0afc2ffc4.png)

**Fig 3.1.3.1 POC avec QEMU**

Pour plus de détails, veuillez consulter https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/Poc/poc.md dans le dossier `Poc` de ce dépôt !

## 3.2 Exploit

Après avoir pris connaissance de cette vulnérabilité, nous pouvons passer à son exploitation. Les détails sont documentés dans le dossier `exploit-ubuntu` et également dans ce fichier markdown : https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/explot-ubuntu/exploit.md

En résumé, nous avons compilé le code source d'Ubuntu, obtenu le fichier deb, puis testé sur une machine virtuelle pour obtenir une version spécifique du noyau. Ensuite, nous avons modifié le décalage (offset) du code d'exploitation pour cibler la version du noyau à l'aide des informations trouvées dans le fichier `System.map`. Enfin, nous avons mis à jour grub et redémarré pour exploiter !

### 3.2.1 Aperçu de l'exploit

L'utilisateur 'clubby789' nous fournit un code d'exploitation détaillé. Nous commencerons par un aperçu, suivi d'explications de plusieurs concepts clés à l'aide de diagrammes. Enfin, nous présenterons les résultats de l'exploitation sur Ubuntu fonctionnant dans une machine virtuelle (VirtualBox).

Après avoir démontré la preuve de concept de cette vulnérabilité, nous pouvons maintenant procéder à son exploitation. Dans la Fig. 3.2.1.1, un aperçu de la manière d'exploiter cette vulnérabilité est illustré :

- La partie gauche se concentre sur l'obtention de l'adresse de base du noyau Linux. Ceci est réalisé en exploitant le dépassement négatif non signé pour écraser le champ m_ts de la structure msg_msg, ce qui permet une lecture hors limites et l'accès à des structures du noyau précédemment placées (sprayed).
- La partie droite vise à obtenir les privilèges root. Ceci est accompli en utilisant le dépassement négatif non signé pour écraser le pointeur next de la structure msg_msg, en le pointant vers modprobe_path. Nous déclenchons ensuite un défaut de page qui invoque notre code fuse construit, permettant des écritures arbitraires dans l'espace noyau.

![Exploit.drawio](https://assets.kitploit.com/production/public/readmes/24547/a8f37de0aa45a0f1bc442bc2bb485402558656b76f3dab668d878132e67c0656.png)

**Fig 3.2.1.1 Aperçu de l'exploit**

### 3.2.2 Obtenir l'adresse de base du noyau Linux

Comme analysé précédemment, nous allons exploiter le dépassement négatif non signé dans cette partie pour écraser le champ m_ts de la structure msg_msg, permettant une lecture hors limites. En plaçant (spraying) le tas avec des structures contenant des pointeurs du noyau, nous espérons obtenir une fuite mémoire.

La structure msg_msg est une structure de données dans le noyau Linux utilisée pour implémenter les files de messages System V. Dans cette section, nous nous concentrons sur la structure interne de struct msg_msg et la logique des fonctions liées à l'envoi, la réception et l'allocation des messages. Comme le montre la Fig. 3.2.2.1, voici les fonctions que nous devons comprendre.

L'implémentation de l'envoi de messages se trouve dans le fichier msg.c, qui définit la longueur maximale d'un message à 8192 octets. Dans la fonction alloc_msg, les messages sont divisés en segments en fonction de leur longueur. Si la longueur du message, ainsi que l'en-tête du message, dépasse une page (4096 octets), le message sera stocké dans plusieurs segments reliés entre eux par des pointeurs.

![img](https://assets.kitploit.com/production/public/readmes/24547/f8e7cad3bbc5f2de8854df978f329a67645fb1e36e824e81785a15fee4f24221.png)

**Fig 3.2.2.1 struct msg_msg envoi et réception**

Dans la Fig. 3.2.2.2, nous pouvons voir que struct msg_msg sert d'en-tête de message, occupant 0x30 octets de mémoire. S'il reste des données dans le message, elles seront stockées dans des segments de message et liées à struct msg_msgseg. Par conséquent, si le noyau permet des messages jusqu'à un maximum de 8192 octets, les données seront stockées dans un maximum de trois segments de message.

![img](https://assets.kitploit.com/production/public/readmes/24547/d5d17b09317a77e03559d587bde7c9a5eb8e9a446f3833d47ce6f57219c9c37b.png)

**Fig 3.2.2.2 struct msg_msg**

Dans la Fig. 3.2.2.3, nous illustrons la structure de struct msg_msg. D'après le code, nous savons que le champ m_ts est celui que nous devons écraser pour lire hors limites. (Vous pouvez trouver le fichier source draw.io dans le dossier `res` si besoin !)

![img](https://assets.kitploit.com/production/public/readmes/24547/8b1a61a5a135f83757eb965ea221a92026f913ec590756f6fde7ce970e1a2f34.png)

**Fig 3.2.2.2 Structure de struct msg_msg**

Maintenant que nous comprenons la structure de struct msg_msg, nous devons apprendre comment obtenir une fuite du noyau. Le noyau Linux dispose d'une fonctionnalité de randomisation de l'espace d'adressage du noyau (KASLR), ce qui signifie que le code du noyau est chargé à une adresse aléatoire décidée lors de la phase de démarrage. Cependant, le décalage entre le point de départ du noyau et toute adresse de fonction reste constant, ce qui nous permet d'effectuer des opérations spécifiques pour remplir l'espace du tas avec des structures contenant des fonctions particulières du noyau. En diminuant le décalage, nous pouvons trouver l'adresse de démarrage du noyau.

Heureusement, nous pouvons facilement placer (spray) le tas avec des structures seq_operations en ouvrant /proc/self/stat, qui réside dans des slabs kmalloc-32. La définition de seq_operations est montrée dans la Fig. 3.2.2.3.

![img](https://assets.kitploit.com/production/public/readmes/24547/8612e158d1534e21c1f56210aeaad89b83f4663bea3838b5874dcb613cec3f7a.png)

**Fig 3.2.2.3 Structures pour la fuite du noyau**

Enfin, le processus global est décrit dans la Fig. 3.2.2.4. Nous commençons par peupler legacy_data avec 4095 octets de données pour préparer l'écrasement. Ensuite, nous construisons des messages en utilisant struct msg_msg. Parce que la mémoire du tas est allouée de manière continue, les messages construits seront probablement adjacents au slab kmalloc-4k voisin. Nous écrasons le champ m_ts en contrôlant les données que nous écrivons dans legacy_data.

Ensuite, nous plaçons (spray) le tas avec plusieurs structures seq_operations de taille kmalloc-32. Nous recevons ensuite des données de la file de messages, ce qui déclenche une lecture hors limites. En ajustant le décalage par rapport à la fonction du noyau, nous pouvons obtenir l'adresse de base du noyau.

![img](https://assets.kitploit.com/production/public/readmes/24547/c4e1e439085cb22305cae68e7b2edff599a51211c159f3682f4f3085d85198c1.png)

**Fig 3.2.2.3 Aperçu de la lecture hors limites**

### 3.2.3 Obtenir les privilèges root

Similaire à notre analyse précédente, dans cette partie, nous devons mettre en place un système de fichiers FUSE, qui permet à notre code en espace utilisateur de gérer les défauts de page provenant de l'espace noyau. En même temps, nous allons écraser le pointeur msg_msgseg *next pour qu'il pointe vers modprobe_path, permettant des écritures arbitraires dans l'espace noyau.

Examinons d'abord la pile d'appels FUSE illustrée dans la Fig. 3.2.3.1. En général, FUSE nous permet d'implémenter un système de fichiers dans l'espace utilisateur. Lorsqu'une nouvelle opération se produit, le système invoquera le code que nous avons défini pour FUSE !

![img](https://assets.kitploit.com/production/public/readmes/24547/304bbdfc643bea5b104119270549179c725ef45c12a166527a06e7097c748ccb.png)

**Fig 3.2.3.1 Aperçu de FUSE**

Analysons comment utiliser FUSE pour réaliser des écritures arbitraires dans l'espace noyau. Tout d'abord, considérons l'opération d'envoi de message pour struct msg_msg. Cette opération implique l'écriture de données dans l'espace noyau. Si nous construisons le message pour qu'il ait deux segments, nous pouvons écraser le pointeur et écrire à n'importe quelle adresse du noyau. Ce concept est illustré dans la Fig. 3.2.3.2.

De plus, après avoir examiné la logique d'envoi de messages à la file, nous savons que le processus implique la copie d'un tampon de l'espace utilisateur vers l'espace noyau. Si les messages sont suffisamment longs, ils seront copiés segment par segment. Si nous pouvons déclencher un défaut de page pendant ce processus, nous pouvons réaliser le scénario montré dans la Fig. 3.2.3.2.

Heureusement, FUSE fournit la fonctionnalité nécessaire. Nous pouvons mapper une page à FUSE, et lorsqu'un défaut de page est déclenché, le système appellera notre fonction de lecture FUSE pour gérer le défaut. En mettant en pause le processus de lecture jusqu'à ce que le dépassement négatif non signé écrase le pointeur msg_msg_seg *next, puis en reprenant le processus d'envoi de message, nous pouvons réaliser des écritures arbitraires. L'ensemble du processus est démontré dans la Fig. 3.2.3.3.

![img](https://assets.kitploit.com/production/public/readmes/24547/8880a54e3e6935fe02652f53e91d8135878cf10b0d45f83aeae10b9777e8d11e.png)

**Fig 3.2.3.2 Utilisation de l'envoi de message**

![img](https://assets.kitploit.com/production/public/readmes/24547/84c63673478a7d9646c8cdcf0c6e4efbdfab431d36d825f28822208c2df08f7e.png)

**Fig 3.2.3.3 FUSE et envoi de message**

### 3.2.4 Exploitation avec VirtualBox

Suivez le fichier markdown à l'adresse : https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/explot-ubuntu/exploit.md

Une fois la compilation terminée, vous pouvez observer les résultats de l'exploitation dans la Fig. 3.2.4.1.

![img](https://assets.kitploit.com/production/public/readmes/24547/16e9a8827c11c7f44d7e37cf5e97a9b47a8b5c14e408c2fe3c1622da7d8ecb30.png)

**Fig 3.2.4.1 Exploitation dans VirtualBox**

# 4. Atténuation de la vulnérabilité

## 4.1 Correctifs officiels

Après que cette vulnérabilité a été signalée, Linux et ses nombreuses distributions ont fusionné des correctifs pour corriger ce bogue.[9] [10] [11]

Dans la capture d'écran suivante, nous montrons le correctif fusionné par Linus Torvalds. L'atténuation de ce problème de dépassement négatif consiste simplement à convertir l'opération de soustraction en addition.

![img](https://assets.kitploit.com/production/public/readmes/24547/f3303a9112d28a5ef779f3e248e2bef28f9793355d55e59ad8509c7d1b72141e.png)

# 5. Impact dans le monde réel

Dans ce rapport, nous démontrons comment cette vulnérabilité peut être exploitée pour compromettre un système Ubuntu. De plus, elle peut potentiellement cibler des systèmes plus anciens qui ne bénéficient pas de mises à jour de sécurité régulières.

Concernant Kubernetes, cette vulnérabilité pourrait entraîner une élévation de privilèges, une évasion de conteneur ou des attaques par déni de service.

Bien qu'aucune perte causée par cette vulnérabilité n'ait été rapportée dans les actualités, cela souligne l'importance d'appliquer systématiquement les mises à jour de sécurité critiques. Le chercheur qui a signalé cette vulnérabilité illustre les pratiques de piratage éthique que nous devrions tous nous efforcer de respecter.[12]

# Références

[1] https://nvd.nist.gov/vuln/detail/CVE-2022-0185

[2] https://www.hackthebox.com/blog/CVE-2022-0185:_A_case_study

[3] https://ubuntu.com/security/CVE-2022-0185#impact-score

[4] [https://en.wikipedia.org/wiki/Two%27s_complement](https://en.wikipedia.org/wiki/Two's_complement)

[5]https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Unsigned-Overflow.html

[6] https://www.kernel.org/doc/gorman/html/understand/understand011.html

[7] https://leviathan.vip/

[8] https://www.willsroot.io/2021/08/corctf-2021-fire-of-salvation-writeup.html

[9] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=722d94847de2

[10] https://ubuntu.com/security/CVE-2022-0185

[11] https://access.redhat.com/security/cve/CVE-2022-0185

[12]https://jfrog.com/blog/the-impact-of-cve-2022-0185-linux-kernel-vulnerability-on-popular-kubernetes-engines/

[14] https://github.com/chenaotian/CVE-2022-0185?tab=readme-ov-file

[15] https://www.tutorialspoint.com/two-s-complement
Télécharger l’outil
Métriques CVSS v3.1Valeur
Vecteur d'attaque (AV)Local
Privilèges requis (PR)Aucun
Interaction utilisateur (UI)Aucune
Confidentialité (C)Élevée
Intégrité (I)Élevée
Disponibilité (A)Élevée