檔案上傳漏洞
1. 定義
檔案上傳漏洞 發生在 Web 伺服器允許用戶在未經充分驗證(如檔案名稱、類型、內容或大小)的情況下,將檔案上傳至其檔案系統時。
最嚴重的後果是 遠端程式碼執行 (Remote Code Execution, RCE):攻擊者上傳一個腳本(如 shell.php),然後該腳本在伺服器上被執行。
2. 技術原理
伺服器通常根據檔案副檔名或 MIME 類型來決定如何處理檔案。
- 副檔名繞過: 攻擊者將
shell.php重命名為shell.php.jpg或利用零字元截斷shell.php%00.jpg。 - MIME 偽造: 在發送 PHP 腳本時,將 HTTP 標頭中的
Content-Type修改為image/jpeg。 - 多語言型檔案 (Polyglots): 創建一個合法的圖像檔案,但在其元數據 (EXIF) 中包含有效的 PHP 程式碼。
如果伺服器將此類檔案保存到公開目錄(如 /uploads),且伺服器配置允許在該目錄下執行 PHP/ASP 檔案,那麼訪問 site.com/uploads/shell.php 就會觸發惡意程式的執行。
3. 攻擊流程 (Web Shell)
sequenceDiagram
participant Attacker as 攻擊者
participant Server as 伺服器
participant FS as 檔案系統
Attacker->>Server: POST /upload (將 shell.php 重命名為 shell.jpg 上傳)
Note right of Attacker: 內容: <?php system($_GET['cmd']); ?>
Server->>Server: 檢查副檔名 (.jpg)? 通過。
Server->>FS: 保存至 /var/www/uploads/shell.jpg
Attacker->>Server: GET /uploads/shell.jpg
Note right of Attacker: 伺服器執行了 PHP,因為<br/>配置允許 .jpg 以腳本方式運行<br/>或檔案被重命名回了 .php
Server-->>Attacker: 返回命令執行結果4. 真實案例:ImageTragick (2016)
目標: 使用 ImageMagick 的數千個網站。 漏洞類別: 檔案處理 / 命令注入 (CVE-2016-3714)。
漏洞背景: ImageMagick 是一個被廣泛使用的圖像處理庫(當時包括 Facebook 和 Yahoo 在內的許多網站都在使用它來縮放用戶上傳的照片)。 它在處理 SVG (向量圖) 檔案時存在缺陷:支持通過「委託 (delegates)」執行 Shell 命令。
攻擊過程: 攻擊者上傳了一個精心構造的圖像檔案(看起來是 .jpg 或 .mvg),內容如下:
fill 'url(https://example.com/image.jpg"|ls "-la)'當伺服器嘗試「縮放」這張圖片時,ImageMagick 執行了 ls -la 命令。這意味著攻擊者只需上傳一張頭像就能實現完全的遠端程式碼執行。
5. 深度防禦策略
A. 副檔名白名單 (Allowlist)
絕不使用黑名單(如禁止 .php, .exe)。攻擊者總能找到繞過方法,如 .php5, .phtml 等。
- 白名單機制: 僅接受特定的安全副檔名:
.jpg,.png,.pdf。
B. 內容校驗 (魔數 Magic Bytes)
不要相信檔案副檔名或 Content-Type 標頭(這些都是用戶可控的)。
- 機制: 讀取檔案的前幾個位元組(魔數)來驗證其真實類型。
- JPEG =
FF D8 FF - PNG =
89 50 4E 47
- JPEG =
- 如果魔數與副檔名不匹配,則拒絕檔案。
C. 檔案名稱隨機化
不要使用用戶提供的原始檔案名稱(如 my_vacation.jpg)。
- 防禦措施: 在存儲時將檔案重命名為 UUID (如
f47ac10b...jpg)。這可以防止覆蓋關鍵系統檔案,並能防禦部分路徑遍歷嘗試。
D. 存儲於 Web 根目錄之外
將上傳的檔案存儲在 Web 伺服器無法直接存取的目錄中(例如 S3 桶或私有資料夾)。通過一個讀取檔案流的控制器來間接提供檔案內容。這能從根源上防止伺服器直接「執行」上傳的檔案。
