sudo TZ 操弄繞過時間限制規則
oss-security(Ermenson Junior) · 2026-09-24
sudo 的時間限制規則出現一個藏在時區換算裡的破口:只要調整呼叫端的 TZ 環境變數,sudoers 裡的 NOTBEFORE/NOTAFTER 時間限制就可能被繞過,讓已過期的授權規則繼續可用,或讓還沒生效的規則提前生效。此漏洞編號 CVE-2026-96512,CVSS 評分 7.8,由 Ermenson Junior 於 2026 年 9 月 24 日在 oss-security 郵件論壇揭露,sudo 主要維護者 Todd Miller 已在主線修補。
漏洞機制
NOTBEFORE 與 NOTAFTER 是 sudoers 規則裡的時間限制欄位,讓管理者可以指定一條授權規則只在某個時間區間內生效,常見用法是「維護窗口才准重啟服務」或「外包人員只在合約期間內有存取權」。這類規則本來就是設計來限制存取時窗,一旦時窗判斷本身能被使用者操弄,等於整個限時授權機制形同虛設。問題出在 sudoers 剖析時間戳記的 parse_gentime() 函式。當規則裡的時間字串沒有結尾 Z(代表 UTC)時,這個函式會改用 mktime() 把字串轉成本地時區的時間值,而 mktime() 每次呼叫都會重新讀取行程環境裡的 TZ 變數。呼叫 sudo 的使用者只要先在自己的 shell 設定一個偏移量極端的 TZ,就能讓 sudo 用錯誤的時區解讀 NOTBEFORE/NOTAFTER 的時間戳記,效果是把有效時間窗位移將近 25 小時。身分驗證本身沒有被繞過,被打穿的只是時間限制這一層,屬於 CWE-863(不當授權判斷)。
這不是全新問題。較早的修補 commit db669167c 已經處理過 localtime_r() 那條路徑,但當時漏掉了 mktime() 這條路徑——只要規則裡的時間戳記缺少 Z 後綴,剖析就會落回沒修好的那條路。舊的修補只堵住一半的門,這也是這次漏洞能存在的根本原因。
受影響版本
受影響版本涵蓋 sudo 1.8.20 到 1.9.17p2,以及修補前的未發布主線程式碼。CVSS 向量為 AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H——攻擊者只需要本機低權限帳號、不需要與人互動,就能讓機密性、完整性、可用性同時受到高度影響。漏洞在 2026 年 8 月 28 日回報後,Todd Miller 當天就完成修補,但對應的 CVE 編號一直到 9 月 23 日才正式公開,隔天才由 Ermenson Junior 在 oss-security 貼出完整分析。這中間的時間差意味著多數發行版目前拿到的只是主線修補,還沒有對應的套件更新可以直接安裝,維運者暫時得靠設定層面的緩解措施頂著。
有用 NOTBEFORE/NOTAFTER 做限時授權的環境都在受影響範圍內,例如稽核要求的維護窗口、外包工程師的臨時存取權限。這類環境應該先盤點自己的 sudoers 規則是否用了不帶 Z 的時間格式,再追蹤所屬發行版何時把修補收進正式套件。Red Hat 已經在自家的追蹤系統 Bugzilla #2539327 建了對應項目,用 Red Hat 系發行版的維運者可以先從那裡確認自己套件的修補排程。
修補與緩解
修補 commit 1820a349687522f51023d1ae5925125f59679a8c 改寫了 src/sudo.c 裡的 set_time_zone()。原本的做法是暫時把行程的 environ 換成空陣列,藉此讓 TZ「消失」;但因為 mktime() 每次呼叫都會重新讀環境變數,換空陣列這招對它沒有效果。新版直接呼叫 unsetenv("TZ") 再呼叫 tzset(),並在 os_init_common() 裡另外複製一份環境陣列,讓 sudo 拿掉自己要用的 TZ,同時把原始 envp 留給後續的 plugin 使用。
/* 修補前:換空 environ,mktime() 仍會重讀 TZ */
environ = empty_environ;
t = mktime(&tm);
environ = saved_environ;
/* 修補後:轉換前先 unsetenv */
unsetenv("TZ");
tzset();
t = mktime(&tm);在各發行版把修補收進正式套件之前,可行的緩解是把 sudoers 裡的時間戳記一律寫成帶 Z 尾碼的 UTC 格式,例如把 NOTBEFORE=20261001000000 改成 NOTBEFORE=20261001000000Z,這樣剖析就會走沒有問題的路徑,不會呼叫到會被 TZ 影響的 mktime()。
原始來源:oss-security:CVE-2026-96512 sudo TZ vulnerability、sudo-project/sudo commit 1820a34