
CVE-2026-96512 (SudoTimeWarp) के लिए पुनरुत्पादन और PoC स्क्रिप्ट, जिसमें कॉलर का TZ sudoers NOTBEFORE/NOTAFTER विंडो को शिफ्ट कर देता है, साथ ही शमन जाँचें।
sudo: कॉलर का TZ NOTBEFORE/NOTAFTER तय करता है
SudoTimeWarp (CVE-2026-96512) के लिए पुनरुत्पादन सामग्री। एक sudoers नियम जिसका Date_Spec टाइमस्टैम्प
अंत में Z छोड़ देता है, उसे mktime() द्वारा परिवर्तित किया जाता है, जो हर कॉल पर getenv("TZ") को फिर से पढ़ता है।
चूँकि sudo setuid-root है और कॉलर का environ execve() को सुरक्षित रूप से पार करता है,
अनप्रिविलेज्ड कॉलर उस समय क्षेत्र को चुनता है जिसमें उसकी स्वयं की वैधता विंडो का मूल्यांकन किया जाता है।
मूल समस्या — TZ का NOTBEFORE/NOTAFTER पर प्रभाव — की सूचना निजी तौर पर
XlabAI Team of Tencent Xuanwu Lab, Atuin Automated Vulnerability Discovery
Engine, और Guannan Wang, Zhanpeng Liu तथा Guancheng Li द्वारा दी गई थी, और इसे commit
db669167c (2026-03-14) में श्रेय दिया गया।
SudoTimeWarp (CVE-2026-96512) यह खोज है कि db669167c अपूर्ण है। इसके द्वारा स्थापित सुरक्षा
glibc के टाइमज़ोन कैश को कवर करती है — और उसके साथ लॉग टाइमस्टैम्प को भी — लेकिन
gentime.c:156 पर मौजूद mktime() तक नहीं पहुँचती, जहाँ प्राधिकरण तय होता है। उस ट्री पर जिसमें
वह commit पहले से मौजूद है, विंडो शिफ्ट पूरी तरह पुनरुत्पादनीय बनी रहती है। मेंटेनर ने
1820a349 के संदेश में यह बात दर्ज की है:
पिछला परिवर्तन "प्रभावी नहीं था क्योंकि mktime() फ़ंक्शन हर बार कॉल किए जाने पर TZ पर्यावरण चर को फिर से पढ़ता है"
एक sudoers नियम जो (1) कॉलर को कोई कमांड प्रदान करता है, (2) NOTBEFORE= या
NOTAFTER= रखता है, और (3) टाइमस्टैम्प को बिना Z प्रत्यय और बिना स्पष्ट
ऑफ़सेट के लिखता है।
मद (3) कोई असामान्य बात नहीं है: sudoers मैनुअल प्रत्यय-रहित रूप को एक समर्थित
एक्सटेंशन के रूप में प्रलेखित करता है, अपने चार उदाहरण टाइमस्टैम्प में से एक के रूप में 20151201235900 दिखाता है
(docs/sudoers.man.in:1820), और यह रूप परियोजना के स्वयं के रिग्रेशन कॉर्पस
(plugins/sudoers/regress/testsudoers/test13.sh) में मौजूद है।
हमेशा एक डिस्पोज़ेबल कंटेनर या VM में। यहाँ की हर स्क्रिप्ट /etc/sudoers को फिर से लिखती है।
वे इसका बैकअप लेती हैं और इसे पुनर्स्थापित करती हैं, लेकिन वहाँ एक गलती आपको असली मशीन से बाहर कर देगी — ये
स्क्रिप्ट कंटेनर के बाहर चलने से मना कर देती हैं जब तक आप --i-know पास न करें।
docker build -t sudotimewarp .
docker run --rm -it sudotimewarp
या बिना इमेज बनाए:
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'
प्रभावित बिल्ड पर अपेक्षित आउटपुट:
=== 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 एक मनमाना तीन-अक्षर का टाइमज़ोन संक्षेप है और 24 एक POSIX ऑफ़सेट है। इसमें कोई
फ़ाइल शामिल नहीं है और किसी के मौजूद होने की आवश्यकता नहीं है — शोषण योग्य चैनल केवल इनलाइन POSIX
स्ट्रिंग है। tzfile रूप (TZ=:/tmp/evil.tz और इसके प्रकार) को setuid के अंतर्गत glibc के
__libc_enable_secure गार्ड द्वारा अस्वीकार कर दिया जाता है और यह ठीक 0 s शिफ्ट देता है, यही इसे
CVE-2014-9680 से अलग करता है।
पंक्तियाँ 1–3 नियंत्रण हैं, और वे महत्वपूर्ण हैं: एक पार्स त्रुटि भी वही ALLOW उत्पन्न करेगी जो बग करता है।
poc.sh प्रभावित होने पर 0 लौटाता है, न होने पर 1, और जब नियंत्रण विफल हों तो 2।
poc.sh NOPASSWD का उपयोग करता है ताकि यह गैर-इंटरैक्टिव रूप से चल सके। यह बग की
शर्त नहीं है। विभाजित स्क्रिप्ट विशेषाधिकार सीमा को स्पष्ट रूप से दिखाती हैं — भाग 1 केवल वही करता है जो
एक प्रशासक वैध रूप से करता है, भाग 2 अनप्रिविलेज्ड उपयोगकर्ता के रूप में चलता है और किसी भी प्रकार के
विशेषाधिकार का उपयोग नहीं करता:
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 चार परिदृश्य लेता है:
पासवर्ड-आवश्यक नियम के साथ कॉलर अभी भी PAM के माध्यम से प्रमाणित होता है, और गलत पासवर्ड अभी भी विफल होता है। यह प्रमाणीकरण बायपास नहीं है — जो बदलता है वह प्राधिकरण निर्णय है।
PR:L, PR:N नहीं।TZ मान इनकार करते हैं।C:L/I:N/A:N)। 7.8 वेक्टर उस मामले को स्कोर करता है जहाँ दिनांकित नियम
कॉलर की स्थायी पहुँच से व्यापक है।~25 h की सीमा पहुँच विंडो पर लागू होती है, प्रभाव की अवधि पर नहीं: इसके भीतर एक सफल उपयोग उस विंडो से अधिक जीवित रहने वाली दृढ़ता स्थापित करने के लिए पर्याप्त है।
हर NOTBEFORE/NOTAFTER टाइमस्टैम्प में Z जोड़ें — यह timegm() शाखा को बाध्य करता है।
grep -rE 'NOT(BEFORE|AFTER)=' /etc/sudoers /etc/sudoers.d/
sudo -l से ऑडिट न करें। यह हर Date_Spec को gmtime() के माध्यम से प्रारूपित करता है और हमेशा
एक Z जोड़ता है (plugins/sudoers/display.c:229), इसलिए
NOTAFTER=20260827221423 के रूप में लिखा नियम NOTAFTER=20260827221423Z के रूप में प्रदर्शित होता है। आउटपुट ठीक उसी
विवरण को सामान्यीकृत कर देता है जो इसे तय करता है। cvtsudoers और fmtsudoers भी वैसा ही व्यवहार करते हैं।
/etc/sudoers को सीधे पढ़ें।
1820a349: https://github.com/sudo-project/sudo/commit/1820a349687522f51023d1ae5925125f59679a8cमेंटेनर को 2026-08-28 को सूचित किया गया, बिना किसी समय-सीमा के। उसी दिन एक संभावित पैच वापस आया; सार्वजनिक फ़िक्स 2026-08-29 को आया। CVE, Red Hat द्वारा CNA-LR के रूप में कार्य करते हुए सौंपा गया, और 2026-09-23 को प्रकाशित हुआ। कोई एम्बार्गो नहीं है: यहाँ सब कुछ फ़िक्स commit के बाद से सार्वजनिक है।
SudoTimeWarp / CVE-2026-96512: Ermenson Junior, स्वतंत्र शोध, Red Hat द्वारा "Independent security research" के रूप में दर्ज। अंतर्निहित समस्या की मूल रिपोर्ट XlabAI Team of Tencent Xuanwu Lab, Atuin Automated Vulnerability Discovery Engine, और Guannan Wang, Zhanpeng Liu तथा Guancheng Li की है।
रक्षात्मक उपयोग के लिए प्रकाशित: यह सत्यापित करना कि कोई होस्ट प्रभावित है या नहीं, और Z
शमन को मान्य करना।
| नाम | 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 (पंजीकृत); तंत्र CWE-807 है |
| प्रभावित | sudo 1.8.20 से 1.9.17p2 तक, और main में 1820a349 से पहले |
| में ठीक किया गया | 1820a349 (2026-08-29) |
| शिफ्ट | प्रति दिशा 24 h 59 m 59 s तक; कुल अंतराल 49 h 59 m 58 s |
| पंक्ति | जाँच करती है |
|---|
| 1 | नियम अपनी विंडो के भीतर बिल्कुल काम करता है |
| 2 | पंक्ति 4 के अभाव में इनकार वास्तव में NOTAFTER से आता है |
| 3 | TZ सेट करना स्वयं कारण नहीं है — TZ=UTC वैसे ही निर्णय देता है जैसे कोई TZ न हो |
| 4 | बग: समाप्त नियम root के रूप में निष्पादित होता है |
| 5 | सीमा: प्रलेखित Z के साथ, timegm() शाखा ली जाती है और यह मर जाता है |
| परिदृश्य | नीति |
|---|
expired (डिफ़ॉल्ट) | एक नियम, NOTAFTER एक घंटा पहले, ज़ोन-रहित |
valid | वही नियम अभी भी अपनी विंडो के भीतर — नियंत्रण |
expired-z | वही समाप्त नियम प्रलेखित Z के साथ — नियंत्रण, अप्रभावित रूप |
escalation | एक संकीर्ण स्थायी अनुदान और एक समाप्त व्यापक अनुदान — वह आकार जो रखरखाव या break-glass अनुदान वास्तव में लेता है |