Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

目錄遍歷 (Directory Traversal)

| , 2 minutes reading.

1. 定義

目錄遍歷 (Directory Traversal)(又稱路徑遍歷)旨在訪問存儲在 Web 根資料夾之外的檔案和目錄。

通過操縱帶有「點-點-斜線 (../)」序列及其變體的檔案引用變數,攻擊者可以訪問存儲在檔案系統上的任意檔案和目錄,包括應用程式原始碼、配置檔案以及關鍵系統檔案。

2. 技術原理

如果應用程式接受檔案名稱並將其拼接至路徑中而未經過濾:

// 易受攻擊的 Node.js 程式碼
app.get('/download', (req, res) => {
  const filePath = path.join(__dirname, 'public', req.query.file);
  res.sendFile(filePath);
});

正常請求:?file=report.pdf -> /app/public/report.pdf

攻擊請求:?file=../../../../etc/passwd 檔案系統會將 .. 解析為父目錄。 結果:/app/public/../../../../etc/passwd -> /etc/passwd

3. 攻擊流程

sequenceDiagram
    participant Attacker as 攻擊者
    participant App as 應用程式
    participant FS as 檔案系統

    Attacker->>App: GET /image?filename=../../../etc/shadow
    
    Note over App: 應用程式拼接路徑:<br/>"/var/www/html/images/" + "../../../etc/shadow"
    
    App->>FS: 讀取檔案
    Note over FS: 路徑被解析為 /etc/shadow
    
    FS-->>App: 返回檔案內容 (包含密碼雜湊)
    App-->>Attacker: 200 OK (敏感數據洩漏)

4. 真實案例:Grafana (2021)

目標: Grafana (視覺化儀表板)。 漏洞類別: 目錄遍歷 (CVE-2021-43798)。

漏洞描述: Grafana 的一個插件資產載入器存在缺陷,它接受插件 ID 和檔案路徑,但未能正確清洗檔案路徑。

攻擊過程: 攻擊者可以發送類似如下的請求: /public/plugins/alertlist/../../../../../../../../etc/passwd

由於應用程式盲目信任插件名稱後的路徑段,它會讀取並返回宿主機伺服器上的任何檔案。 這是一個在野外被利用的 零日 (Zero-Day) 漏洞,在許多管理員還沒來得及修補之前,攻擊者就利用它竊取了包含資料庫密碼的配置檔案。

5. 深度防禦策略

A. 避免在檔案路徑中使用用戶輸入

最安全的方法是不讓用戶直接提供檔案名稱。

  • 間接引用: 在資料庫中使用 ID (1, 2, 3) 映射到具體的檔案名稱,用戶僅通過 ID 進行訪問。

B. 路徑規範化與前綴檢查

如果必須使用用戶輸入,請在訪問路徑前使用程式語言原生的路徑規範化功能。

  1. 解析 完整路徑。
  2. 檢查 解析後的路徑是否以預期的目錄開頭。
// 安全的 Node.js 程式碼
const safeDir = path.resolve(__dirname, 'public');
const userPath = path.resolve(safeDir, req.query.file);

if (!userPath.startsWith(safeDir)) {
  throw new Error('拒絕訪問!');
}
res.sendFile(userPath);

C. Chroot 監獄

在「監獄 (Jail)」或容器 (Docker) 中運行 Web 伺服器進程。即使遍歷攻擊成功,攻擊者也只能看到容器內部隔離的檔案,而無法看到宿主機的 /etc/passwd

6. 參考資料