目錄遍歷 (Directory Traversal)
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. 路徑規範化與前綴檢查
如果必須使用用戶輸入,請在訪問路徑前使用程式語言原生的路徑規範化功能。
- 解析 完整路徑。
- 檢查 解析後的路徑是否以預期的目錄開頭。
// 安全的 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。
