
Reproduktions- und PoC-Skripte für CVE-2026-96512 (SudoTimeWarp), bei dem die TZ des Aufrufers die NOTBEFORE/NOTAFTER-Fenster von sudoers verschiebt, sowie Mitigationsprüfungen.
sudo: die TZ des Aufrufers entscheidet über NOTBEFORE/NOTAFTER
Reproduktionsmaterial für SudoTimeWarp (CVE-2026-96512). Eine sudoers-Regel, deren Date_Spec-Zeitstempel
das abschließende Z weglässt, wird von mktime() umgewandelt, das bei jedem Aufruf getenv("TZ") erneut liest.
Da sudo setuid-root ist und die environ des Aufrufers execve() unverändert überquert, wählt der
unprivilegierte Aufrufer die Zeitzone, in der sein eigener Gültigkeitsbereich ausgewertet wird.
| Name | SudoTimeWarp |
| CVE | CVE-2026-96512 |
| CVSS v3.1 | AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — 7.8 High |
| CWE | CWE-863 (registriert); Mechanismus ist CWE-807 |
| Betroffen | sudo 1.8.20 bis 1.9.17p2, und main vor 1820a349 |
| Behoben in | 1820a349 (2026-08-29) |
| Verschiebung | bis zu 24 h 59 m 59 s pro Richtung; Gesamtintervall 49 h 59 m 58 s |
Das Grundproblem — TZ beeinflusst NOTBEFORE/NOTAFTER — wurde privat gemeldet vom
XlabAI Team of Tencent Xuanwu Lab, der Atuin Automated Vulnerability Discovery
Engine und Guannan Wang, Zhanpeng Liu und Guancheng Li und in Commit
db669167c (2026-03-14) gewürdigt.
SudoTimeWarp (CVE-2026-96512) ist die Erkenntnis, dass db669167c unvollständig ist. Der Schutz, den er
installiert, deckt glibcs Zeitzonen-Cache ab — und damit die Log-Zeitstempel — erreicht aber nicht
das mktime() in gentime.c:156, wo über die Autorisierung entschieden wird. Auf einem Tree, der
diesen Commit bereits enthält, bleibt die Fensterverschiebung vollständig reproduzierbar. Der Maintainer
hält den Punkt in der Nachricht von 1820a349 fest:
die vorherige Änderung „war nicht wirksam, da die mktime()-Funktion die TZ Umgebungsvariable bei jedem Aufruf erneut liest“
Eine sudoers-Regel, die (1) dem Aufrufer einen Befehl gewährt, (2) NOTBEFORE= oder
NOTAFTER= trägt und (3) den Zeitstempel ohne Z-Suffix und ohne expliziten
Offset schreibt.
Punkt (3) ist nicht exotisch: Das sudoers-Handbuch dokumentiert die suffixlose Form als unterstützte
Erweiterung, gibt 20151201235900 als einen seiner vier Beispiel-Zeitstempel an
(docs/sudoers.man.in:1820), und die Form erscheint im eigenen Regression-Korpus des Projekts
(plugins/sudoers/regress/testsudoers/test13.sh).
Immer in einem Wegwerf-Container oder einer VM. Jedes Skript hier schreibt /etc/sudoers um.
Sie sichern sie und stellen sie wieder her, aber ein Fehler dort sperrt Sie aus einer echten Maschine aus — die
Skripte weigern sich, außerhalb eines Containers zu laufen, es sei denn, Sie übergeben --i-know.
docker build -t sudotimewarp .
docker run --rm -it sudotimewarp
Oder ohne ein Image zu bauen:
docker run --rm -it -v "$PWD:/m" debian:trixie bash -c \
'apt-get update >/dev/null && apt-get install -y sudo >/dev/null && bash /m/poc.sh'
Erwartete Ausgabe auf einem betroffenen Build:
=== probes ===
rule valid, no TZ : uid=0(root) gid=0(root) groups=0(root)
rule expired, no TZ : sudo: a password is required
rule expired, TZ=UTC : sudo: a password is required
rule expired, TZ=XXX24 : uid=0(root) gid=0(root) groups=0(root)
expired + 'Z', TZ=XXX24 : sudo: a password is required
XXX ist eine beliebige dreistellige Zeitzonen-Abkürzung und 24 ist ein POSIX-Offset. Es ist keine
Datei beteiligt und keine muss existieren — der ausnutzbare Kanal ist ausschließlich der Inline-POSIX-
String. Die tzfile-Form (TZ=:/tmp/evil.tz und Varianten) wird von glibcs
__libc_enable_secure-Guard unter setuid abgelehnt und misst exakt 0 s Verschiebung, was dies
von CVE-2014-9680 unterscheidet.
Zeilen 1–3 sind Kontrollen, und sie sind wichtig: Ein Parse-Fehler würde dasselbe ALLOW erzeugen wie der Bug.
| Zeile | Prüft |
|---|---|
| 1 | Die Regel funktioniert überhaupt innerhalb ihres Fensters |
| 2 | Die Verweigerung in Zeile 4 kommt wirklich von NOTAFTER |
| 3 | Das Setzen von TZ ist nicht selbst die Ursache — TZ=UTC entscheidet wie kein TZ |
| 4 | Der Bug: die abgelaufene Regel wird als root ausgeführt |
| 5 | Die Grenze: mit dem dokumentierten Z wird der timegm()-Zweig genommen und es stirbt |
poc.sh beendet mit 0, wenn betroffen, 1, wenn nicht, 2, wenn die Kontrollen nicht hielten.
poc.sh verwendet NOPASSWD, damit es nicht-interaktiv laufen kann. Das ist keine Bedingung des
Bugs. Die geteilten Skripte zeigen die Privilegiengrenze explizit — Teil 1 tut nur, was
ein Administrator legitim tut, Teil 2 läuft als unprivilegierter Benutzer und nutzt keinerlei
Privileg:
bash repro-admin.sh escalation # as root: writes the policy
su - poc -c 'bash /poc/repro-attacker.sh'
bash repro-admin.sh --cleanup
repro-admin.sh kennt vier Szenarien:
| Szenario | Policy |
|---|---|
expired (Standard) | eine Regel, NOTAFTER eine Stunde in der Vergangenheit, zonenlos |
valid | dieselbe Regel noch innerhalb ihres Fensters — Kontrolle |
expired-z | dieselbe abgelaufene Regel mit dem dokumentierten Z — Kontrolle, nicht betroffene Form |
escalation | eine enge dauerhafte Gewährung plus eine abgelaufene breite — die Form, die eine Wartungs- oder Break-Glass-Gewährung tatsächlich annimmt |
Bei einer passwortverlangenden Regel authentifiziert sich der Aufrufer weiterhin über PAM, und ein falsches Passwort schlägt weiterhin fehl. Dies ist kein Authentication Bypass — was sich verschiebt, ist die Autorisierungsentscheidung.
PR:L, nicht PR:N.TZ-Werte.C:L/I:N/A:N). Der 7.8-Vektor bewertet den Fall, in dem die datierte Regel
breiter ist als der dauerhafte Zugriff des Aufrufers.Die ~25-h-Grenze gilt für das Zugriffsfenster, nicht für die Dauer der Auswirkung: eine erfolgreiche Nutzung darin genügt, um Persistenz zu etablieren, die das Fenster überlebt.
Hängen Sie Z an jeden NOTBEFORE/NOTAFTER-Zeitstempel an — das erzwingt den timegm()-Zweig.
grep -rE 'NOT(BEFORE|AFTER)=' /etc/sudoers /etc/sudoers.d/
Auditieren Sie nicht mit sudo -l. Es formatiert jedes Date_Spec durch gmtime() und hängt immer
ein Z an (plugins/sudoers/display.c:229), sodass eine als
NOTAFTER=20260827221423 geschriebene Regel als NOTAFTER=20260827221423Z angezeigt wird. Die Ausgabe normalisiert
genau das Detail weg, das entscheidet. cvtsudoers und fmtsudoers verhalten sich gleich.
Lesen Sie /etc/sudoers direkt.
1820a349: https://github.com/sudo-project/sudo/commit/1820a349687522f51023d1ae5925125f59679a8cAm 2026-08-28 an den Maintainer gemeldet, ohne Frist. Noch am selben Tag kam ein Kandidaten-Patch zurück; der öffentliche Fix landete am 2026-08-29. CVE von Red Hat in der Rolle als CNA-LR vergeben und am 2026-09-23 veröffentlicht. Es gibt keine Embargo: alles hier ist seit dem Fix-Commit öffentlich.
SudoTimeWarp / CVE-2026-96512: Ermenson Junior, unabhängige Forschung, von Red Hat als „Independent security research“ erfasst. Der ursprüngliche Bericht des zugrunde liegenden Problems gehört dem XlabAI Team of Tencent Xuanwu Lab, der Atuin Automated Vulnerability Discovery Engine und Guannan Wang, Zhanpeng Liu und Guancheng Li.
Veröffentlicht für defensive Nutzung: um zu prüfen, ob ein Host betroffen ist, und um die Z-
Mitigation zu validieren.