名詞解釋

什麼是 TOCTOU:檢查與使用之間狀態改變

TOCTOU(time-of-check to time-of-use)是指檢查之後狀態又發生改變的競爭條件。說明其運作方式與防禦方法:把檢查與使用合併成一個步驟。

發布於 2026-11-15 更新於 2026-11-15 閱讀時間 2 分鐘
本頁內容

TOCTOU(time-of-check to time-of-use)是指某個事物的狀態在被檢查的時刻與被使用的時刻之間發生改變的問題。本頁說明其運作方式與預防方法(不含攻擊步驟)。

什麼是 TOCTOU

程式常以「先檢查,若看起來沒問題再使用」的方式運作,例如「檢查此檔案可否寫入,再開啟並寫入」。但檢查與使用之間存在一段很短的時間差。若在這段時間內,其他程式或請求改變了目標,檢查結果便不再成立。

MITRE 的 CWE-367 將其描述為:產品在使用資源前檢查其狀態,但狀態可能在檢查與使用之間改變,使檢查結果失效。CWE(Common Weakness Enumeration,通用弱點列舉)是漏洞背後弱點的共通目錄。TOCTOU 是競爭條件的一種,其結果取決於同時執行之事件的時序。

為何會發生

1. 檢查:此檔案可否寫入?→ 可以
2. 空隙:另一個程序取代了該名稱所指向的內容
↓ 檢查結果已與實際情況不符
3. 使用:程式寫入了它從未檢查過的目標
當檢查與使用是獨立步驟時,目標可能在中間被替換,使檢查結果過時。

根據 CWE-367,其後果可能包括:存取本應禁止存取的資源、資源被以非預期方式改變,以及缺少日誌紀錄。空隙可能很短,但在同時執行大量工作的系統中,它會被反覆觸及,而非僅是偶然發生。

常見出現的位置

位置檢查使用出錯的情況
檔案處理存在或權限檢查開啟或寫入檢查後檔案被替換
網頁應用程式的庫存或餘額SELECT 剩餘數量UPDATE 扣減數量兩個並行請求都通過檢查而超出上限
付款與註冊是否仍未處理?執行動作重複送出導致執行兩次
檔案上傳檢查內容儲存或發佈檢查後內容被改變

關於上傳檢查,另請參閱 檔案上傳漏洞。

防禦:不要將檢查與使用分開

1

不要在使用前進行檢查

CWE-367 最基本的建議是不要在使用之前進行檢查。直接使用資源,若失敗則處理錯誤。這樣便能消除空隙本身。

2

使用檔案描述子,而非路徑

先開啟檔案,然後檢查狀態並透過已開啟的檔案描述子寫入。重複查詢同一路徑名稱,每次都可能指向不同的目標。O_NOFOLLOW(不跟隨符號連結)等旗標,以及 openat(相對於目錄開啟)等呼叫也有幫助;可用的選項取決於作業系統。

3

資料庫使用條件式更新與交易

不要採用「SELECT 檢查,再 UPDATE」,而是使用包含條件的單一 UPDATE(例如僅在數量為 1 或以上時才遞減)。若涉及多個陳述式,請使用具適當隔離層級與資料列鎖定的交易。

4

在檢查之前鎖定

若使用鎖定,請如 CWE-367 所述,在檢查之前取得鎖。在檢查之後才鎖定,無法保證你檢查的目標就是你使用的目標。

5

以冪等性金鑰防止重複執行

對於付款與註冊,為每個請求指定唯一金鑰(冪等性金鑰),並確保每個金鑰只執行一次該動作。

如何檢查自己的程式碼

請在你自行開發或管理的程式碼中進行。

  1. 找出檢查程式碼與使用程式碼是獨立呼叫的地方(先檢查存在再開啟;先 SELECT 再 UPDATE)
  2. 對每一處,評估能否取消檢查,並將該步驟合併為單一操作
  3. 撰寫測試,同時對同一請求送出數次,確認只有一次生效
  4. 切勿對他人的服務進行此類測試;請使用你自己的環境

本站觀點:將檢查置於與使用相同的操作之中

TOCTOU 並非「有人忘了檢查」。檢查其實存在,只是與使用分開了。增加更多檢查程式碼無法解決問題。正確的修正是將檢查置於與使用相同的原子操作之中,而不是將其當作額外步驟加入。在審查程式碼時,若同時學習 IDOR 會有幫助:兩者都是「檢查存在,卻未發揮作用」的缺陷。

主要來源

  • MITRE CWE-367:Time-of-check Time-of-use (TOCTOU) Race Condition — cwe.mitre.org(定義、後果、緩解措施)
  • 具體技術(O_NOFOLLOW、openat、冪等性金鑰、交易)係以一般實作做法說明;可用性因作業系統與資料庫而異,請查閱各產品的官方文件

延伸閱讀

分類編號

CWE 對造成漏洞的弱點類型進行分類,MITRE ATT&CK 對攻擊者的技術進行分類。兩者皆由 MITRE 維護,廣泛用於標註漏洞資訊與偵測規則。

CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use

FAQ

QTOCTOU 是什麼意思?
A

它代表 time-of-check to time-of-use,指資源的狀態在被檢查的時刻與被使用的時刻之間發生改變。MITRE 的 CWE-367 將其描述為:產品在使用資源前檢查其狀態,但狀態可能在檢查與使用之間改變,使檢查結果失效。它屬於競爭條件的一種。

QTOCTOU 常發生在哪裡?
A

典型的地方是檔案處理:程式先檢查檔案是否存在或是否可寫入,之後才在另一個呼叫中開啟它,而檔案可能在這段時間被替換。它也會出現在網頁應用程式與資料庫中,例如「檢查庫存後確認訂單」或「檢查餘額後扣款」,只要檢查與更新是分開的步驟就可能發生。

Q主要的防禦方法是什麼?
A

將檢查與使用合併為一個原子操作。CWE-367 指出最基本的建議是不要在使用之前進行檢查。對於檔案,先開啟,再透過已開啟的檔案描述子進行檢查或操作。對於資料庫,使用條件式更新,或搭配鎖定的交易。

Q加上鎖定就一定安全嗎?
A

鎖定必須在檢查之前取得,而不是之後。CWE-367 指出應確保鎖定發生在檢查之前,而非之後。在檢查之後才鎖定,無法保證你檢查的對象就是你使用的對象。若鎖定的範圍太小,或其他程式忽略該鎖,鎖定也不會有任何作用。

QTOCTOU 會影響網頁應用程式嗎?
A

會。例如:檢查上傳的檔案後才儲存、讀取優惠券或庫存數量後再遞減,以及不應重複執行的付款處理程序。若同一個請求同時到達兩次,兩者都可能通過檢查。請讓更新成為一個條件式操作,並使用冪等性金鑰來防止重複執行。

Q如何在自己的程式碼中找出 TOCTOU?
A

找出檢查程式碼與使用程式碼是獨立的行或呼叫之處。在檔案相關程式碼中,即是先檢查存在或權限、再依路徑開啟。在資料庫程式碼中,即是先 SELECT 檢查、再 UPDATE。接著評估能否取消檢查,改為單一操作,並加入並行請求的測試。