在多執行緒與並發環境中,time of check to time of use(TOCTOU)是最容易被忽視卻危害深遠的漏洞類型。攻擊者只需掌握那一瞬間的時間差,就能讓系統執行完全非預期的操作。
什麼是 TOCTOU 競態條件?
TOCTOU 的核心在於「檢查(Check)」與「使用(Use)」兩個動作之間存在時間窗口。程式先確認某資源的狀態是否符合條件,隨後才對其進行操作;而攻擊者正是在這段窗口期內,悄悄置換或竄改該資源。最典型的案例是檔案系統攻擊:程式用 access() 確認檔案權限後,攻擊者迅速以 符號連結(Symlink)替換目標路徑,使後續的 open() 實際操作到不同的敏感檔案。此漏洞同樣廣泛出現於身份驗證流程與資料庫事務中。
防禦策略:縮短或消除時間窗口
防禦 TOCTOU 的核心思路是將「檢查」與「使用」合併為不可分割的原子操作。在檔案系統層面,應使用 O_NOFOLLOW 旗標避免跟隨符號連結,或改以 檔案描述符(File Descriptor)取代路徑名稱進行後續操作,確保檢查對象與操作對象為同一實體。在並發程式設計中,應透過互斥鎖(Mutex)或資料庫的 SELECT FOR UPDATE 鎖定機制,保障檢查至使用期間資源不被他方修改。從根本上消除窗口,遠比縮短窗口更為可靠。
// ❌ 易受 TOCTOU 攻擊的寫法
if (access("target.txt", W_OK) == 0) { // 檢查
fd = open("target.txt", O_WRONLY); // 使用(窗口在此)
}
// ✅ 安全寫法:直接開啟並檢查結果
fd = open("target.txt", O_WRONLY | O_NOFOLLOW);
if (fd < 0) { /* 處理錯誤 */ }
💡 重點整理
- 核心成因:檢查與使用之間的非原子性時間窗口是漏洞根源。
- 常見場景:檔案權限驗證、登入流程、並發資料庫讀寫皆為高風險區域。
- 最佳防禦:使用原子操作或鎖定機制,讓檢查與使用不可被中斷。
- 避免路徑操作:優先使用檔案描述符而非路徑字串,防止 Symlink 攻擊。
TOCTOU 漏洞的危險在於其隱蔽性——邏輯看似正確,卻在並發場景下完全失效。將原子性設計納入開發思維,才是從根本上杜絕此類競態條件的唯一解法。
留言
張貼留言