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
CVE-2026-8933 — Preuve de concept en C pour CVE-2026-8933, une élévation de privilèges locale dans snap-confine exploitant le gel des cgroups, des courses de liens symboliques et l'injection de règles udev pour exécuter des commandes en tant que root. | Kitploit
Outils/GitHubGitHub/yifengchen-cc/cve-2026-8933
Escalade de PrivilègesSécurité des ConteneursAnalyse des VulnérabilitésExploitation
GitHubyifengchen-cc/cve-2026-8933

CVE-2026-8933

Preuve de concept en C pour CVE-2026-8933, une élévation de privilèges locale dans snap-confine exploitant le gel des cgroups, des courses de liens symboliques et l'injection de règles udev pour exécuter des commandes en tant que root.

Voir le dépôt
il y a 14 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 — Élévation de privilèges locale via snap-confine set-capabilities PoC

Reproduire l'avis Qualys « Local Privilege Escalation in set-capabilities versions of snap-confine » (https://cdn2.qualys.com/advisory/2026/07/21/snap-confine-set-capabilities.txt).

Testé sur la machine locale (Ubuntu 25.10 / snapd 2.73+ubuntu25.10.1 / noyau 6.17) : en partant de l'uid 1000, la commande est finalement exécutée en root par systemd-udevd, et /tmp/pwned obtient uid=0(root) gid=0(root) groups=0(root), conformément à l'effet démontré à la fin de l'avis.

Les notes sur les pièges rencontrés lors de la reproduction, ainsi que l'explication de pourquoi la première évaluation a conclu à tort « non exploitable », sont dans NOTES.md.

Fichiers

FichierDescription
poc.cPoC complet (fichier unique)
MakefileCompilation (liaison avec le libfuse3.so.3.17.4 installé sur le système)
include/En-têtes de libfuse3 3.17.4 (correspondant à la bibliothèque d'exécution du système)
NOTES.mdNotes sur les pièges rencontrés + rétrospective sur la méthodologie d'analyse d'accessibilité

Principe de la vulnérabilité

cmd/snap-confine/mount-support.c (snapd 2.73) :

sc_bootstrap_mount_namespace()      // 第 475 行起
  479:  mkdtemp("/tmp/snap.rootfs_XXXXXX")          <- 目录先归调用者所有
  491:  sc_do_mount(scratch, scratch, NULL, MS_BIND)
  498:  sc_do_mount("none", scratch, NULL, MS_UNBINDABLE)
  503:  sc_do_mount("none", scratch, "tmpfs", ...)
  504:  sc_replicate_base_rootfs(scratch, rootfs_dir, mounts)

sc_replicate_base_rootfs()
  330:  chown(scratch, 0, 0)
  418:  fd = open(full_path, O_CREAT | O_TRUNC, 0644)   <- 缺少 O_NOFOLLOW
  422:  fchown(fd, 0, 0)

Les numéros de ligne proviennent du code source de snapd 2.73 de cette machine (cmd/snap-confine/mount-support.c). L'avis Qualys cite sa propre copie du fichier, dont les numéros de ligne correspondants sont 511 / 523 / 530 / 535 / 536 / 362 / 450 / 454 — les instructions correspondent une à une, seuls les numéros de ligne diffèrent.

Sur cette machine, /usr/lib/snapd/snap-confine est en mode=755 + capacités de fichier (et non setuid-root), il s'exécute donc avec l'euid de l'attaquant tout en détenant des capacités proches de root : les répertoires et fichiers qu'il crée appartiennent à l'attaquant pendant un court instant, et l'open() de la ligne 418 suit les liens symboliques.

La désassemblage confirme : sur cette machine, les indicateurs de open@plt sont 0x240 (O_CREAT|O_TRUNC, sans O_NOFOLLOW) ; au même point dans la version corrigée 2.77.1, ils sont 0x20240.

Les six étapes du PoC

  1. Placer snap-confine dans son propre cgroup : systemd-run --user --scope --unit=snap.<snap>.<app>. Ce scope appartient à l'utilisateur courant, cgroup.freeze est accessible en écriture, ce qui permet de laisser passer snap-confine appel système par appel système.
  2. Geler au bon endroit : avec SNAPD_DEBUG=1, snap-confine affiche associated snap application process ... with device cgroup. Cette ligne apparaît après l'attachement du programme BPF du cgroup de périphériques, avant mkdtemp(). Il ne faut pas geler plus tôt : le vérificateur BPF renvoie EAGAIN en présence d'un freeze trap, et snap-confine quitte immédiatement. stderr est connecté à un pty (pas un pipe) : sinon stdio serait en tampon de bloc et le marqueur ne serait souvent vidé qu'après mkdtemp() et le bind mount. De plus, le scope démarre avec CPUQuota=1% : entre le marqueur et mkdtemp(), il n'y a que quelques centaines de microsecondes de temps CPU, du même ordre de grandeur que la latence de réveil du processus de capture ; la limitation étire cette fenêtre en temps réel jusqu'à l'ordre de la milliseconde, et une fois le gel confirmé, cpu.max est immédiatement restauré à 100%.
  3. Remplacer le répertoire scratch par un lien symbolique vers notre propre répertoire : mount(2) suit les liens symboliques dans le chemin cible, de sorte que les bind/unbindable/tmpfs de snap-confine atterrissent tous sur <scratch>.dA, tandis que la boucle de copie utilise toujours la chaîne du répertoire scratch.
  4. Après le montage du tmpfs (ns_mount_count(sc, .dA) >= 2), rediriger le lien symbolique vers <scratch>.dB, et placer dans dB des liens symboliques portant le même nom que les fichiers ordinaires de premier niveau du rootfs de base, pointant vers /run/udev/rules.d/97-cve-2026-8933-<pid>-<rand>.rules. À ce moment, la résolution de chemin de la boucle de copie aboutit à dB — un répertoire ordinaire que nous contrôlons entièrement. Le tmpfs reste sur dA et ne nous gêne plus. Attention : avec un seul montage sur .dA, il s'agit d'un bind mount (/tmp est lui-même un tmpfs, et après bind le fstype reste tmpfs) ; il faut attendre le 2e montage (le vrai tmpfs) pour rediriger, sinon le mount --make-unbindable de snap-confine échouerait avec EINVAL parce que le chemin n'est plus la racine d'un montage.
  5. Gagner la fenêtre entre open()/fchown() : la boucle de copie exécute sur le premier fichier ordinaire open(O_CREAT|O_TRUNC) (suit le lien symbolique, crée le fichier sous /run/udev/rules.d en tant que root), puis fchown(fd,0,0). À cet instant, le fichier nous appartient encore. Le PoC utilise simultanément deux moyens :
    • chemin principal : continuer à utiliser le freezer pour ne laisser passer qu'environ un appel système à la fois ; dès que stat() voit le fichier et que l'uid est encore le nôtre, immédiatement chmod 0666 + écrire la règle udev (snap-confine étant alors gelé, la fenêtre est « élargie ») ;
    • filet de sécurité : plusieurs processus spinner préemptent la même fenêtre par une boucle active de chmod(). Une fois que le spinner l'emporte, le fichier appartient à root mais son mode est 0666 — les bits de mode sont conservés après fchown(0,0), donc le chemin principal peut également finir de l'écrire (le code teste « peut-on écrire », pas « est-on propriétaire »).
  6. Déclencher udev : le profil AppArmor de snap-confine autorise /run/udev/** rw. Monter/démonter un système de fichiers FUSE amène le noyau à émettre un uevent add pour le sous-système bdi, et systemd-udevd exécute alors le PROGRAM= de la règle en tant que root.

Utilisation

make
./poc --diagnose            # 只读自检,不改动任何系统状态
./poc                       #  exploit,默认最多 5 次尝试
./poc --attempts 8          # 增加尝试次数
./poc --file default256.png # 只用 base rootfs 里的这一个普通文件
sudo ./poc --cleanup        # 清理(仅在异常中断留下残留时需要)

Paramètres :

ParamètreDescription
--snap NAMEQuel snap utiliser pour le rootfs (par défaut firefox, également disponible via la variable d'environnement CVE8933_SNAP)
--app NAMEL'app de ce snap (par défaut, le premier sous apps: dans meta/snap.yaml)
--file NAMEN'utiliser que ce fichier ordinaire dans le rootfs de base ; erreur et sortie si aucune correspondance
--attempts NNombre de tentatives (par défaut 5)
--step US / --step2 USTemps CPU par tranche pour les deux phases (microsecondes), pour le débogage
--keepConserver les répertoires <scratch>.dA / .dB et les liens symboliques (pour le débogage)
--diagnoseAuto-vérification en lecture seule
--cleanupNettoyer les résidus historiques (nécessite root)

Les journaux sont écrits dans /tmp/cve8933.log, la sortie de débogage de snap-confine dans /tmp/cve8933-debug.txt.

CVE8933_PAYLOAD_CMD='<commande shell>' permet de remplacer le corps du payload (pour démontrer l'exécution d'autres commandes root), auquel cas le nettoyage automatique n'a pas lieu ; la commande personnalisée doit toujours écrire dans /tmp/pwned, sinon le PoC considérera que cette tentative a échoué.

Résultats des tests

Télécharger l’outil