路徑穿越 (Path Traversal),也稱為目錄穿越 (Directory Traversal) 或「點-點-斜線 (dot-dot-slash)」攻擊,是一種允許攻擊者存取網站伺服器上任意檔案的漏洞。透過操縱檔案路徑,攻擊者可以讀取到網站根目錄之外的敏感檔案,例如設定檔、原始碼,甚至是系統層級的密碼檔案。
什麼是路徑穿越漏洞?
此漏洞的根源在於,應用程式將使用者提供的輸入,未經嚴格的過濾和驗證,就直接用來拼接成一個檔案路徑,並在後續的檔案系統操作(如讀取、寫入檔案)中使用這個路徑。
攻擊者可以利用特殊的目錄序列(如 ../
)來改變檔案路徑,使其「穿越」到預期目錄之外,從而存取到受限制的檔案。
攻擊原理與範例
情境:下載網站上的任意圖片
- 正常功能:一個網站提供圖片顯示功能,URL 看起來像這樣:後端 PHP 程式碼的邏輯可能是:
1
https://example.com/show_image.php?filename=cat.jpg
1
2
3
4$base_path = "/var/www/html/images/";
$filename = $_GET['filename'];
$full_path = $base_path . $filename;
readfile($full_path); - 發現漏洞:後端程式直接將使用者傳入的
filename
拼接到基底路徑/var/www/html/images/
後面。 - 發動攻擊:攻擊者想要讀取伺服器上儲存系統密碼的
/etc/passwd
檔案。他知道../
可以跳轉到上一層目錄,於是他建構了以下的filename
參數:1
../../../../etc/passwd
- 攻擊成功:後端拼接出來的完整路徑變成了:這個路徑經過解析後,最終指向了
1
/var/www/html/images/../../../../etc/passwd
/etc/passwd
。由於程式沒有進行任何過濾,readfile()
函數成功讀取了這個敏感檔案,並將其內容回傳給攻擊者。
常見的繞過技巧
為了防禦這種攻擊,開發者有時會簡單地過濾 ../
字串,但攻擊者仍有多種技巧可以繞過:
- URL 編碼:將
../
進行單次或雙次 URL 編碼,如%2e%2e%2f
或%252e%252e%252f
。 - 使用絕對路徑:直接提供檔案的絕對路徑,如
/etc/passwd
。 - 混合編碼:使用不同的編碼方式混合
.
和/
。
風險與影響
- 敏感資訊洩漏:攻擊者可以讀取到應用程式的原始碼、設定檔、資料庫憑證、作業系統的敏感檔案等。
- 系統資訊探測:了解伺服器的目錄結構和檔案佈局,為進一步的攻擊做準備。
- 檔案竄改或刪除:如果存在漏洞的檔案操作是寫入或刪除,攻擊者甚至可能修改或刪除伺服器上的任意檔案,導致系統癱瘓或被植入後門。
防禦與預防措施
1. 不要將使用者輸入直接用於檔案操作
- 這是最根本的原則。應避免將使用者可控的字串,直接傳遞給任何檔案系統相關的 API。
2. 使用間接對應 (Indirect Reference)
- 如果必須讓使用者選擇檔案,可以在後端建立一個安全的檔案列表或對應表。使用者傳入一個索引值(如
1
,2
)或一個安全的檔案名稱,後端根據這個索引值去查詢預先定義好的、安全的檔案路徑。
3. 建立安全的檔案路徑
- 如果無法避免使用使用者輸入,必須進行嚴格的處理:
- 輸入驗證:使用白名單的方式,只允許輸入包含已知的、安全的字元(例如,只允許字母和數字)。
- 路徑正規化 (Normalization):在使用輸入之前,先將路徑正規化。作業系統和程式語言通常提供函式來解析路徑,消除
../
等序列,並取得其真實的絕對路徑。 - 驗證路徑是否在預期目錄內:在正規化路徑後,必須檢查該路徑是否仍然位於預期的基底目錄之下。
4. 使用沙箱環境 (Chroot Jail)
- 在作業系統層級,將應用程式的執行環境限制在一個特定的目錄(“chroot jail”)中。這樣即使路徑穿越漏洞被利用,攻擊者也無法存取到該目錄之外的任何檔案。
說些什麼吧!