翻譯自
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/File_Upload_Cheat_Sheet.md
檔案上傳小抄
簡介
檔案上傳正逐漸成為任何應用程式中更為重要的一部分,使用者可以上傳他們的照片、履歷,或是展示他們正在進行的專案的影片。應用程式應該能夠防範虛假和惡意檔案,以保護應用程式和使用者的安全。
簡而言之,應遵循以下原則以實現安全的檔案上傳實作:
- 列出允許的副檔名。僅允許安全和關鍵的副檔名以供業務功能使用
- 確保在驗證副檔名之前應用 輸入驗證
- 驗證檔案類型,不要信任 Content-Type 標頭,因為它可能被偽造
- 將檔案名稱更改為應用程式生成的內容
- 設定檔案名稱長度限制。如有可能,限制允許的字元
- 設定檔案大小限制
- 僅允許授權使用者上傳檔案
- 將檔案存儲在不同的伺服器上。如果不可能,則將它們存儲在網站根目錄之外
- 在檔案公開存取的情況下,使用一個映射到應用程式內部檔案名稱的處理程序(someid -> file.ext)
- 將檔案通過防毒軟體或沙箱過濾以驗證其不包含惡意資料
- 如果適用,將檔案通過 CDR(Content Disarm & Reconstruct)過濾(如 PDF、DOCX 等)
- 確保任何使用的函式庫都被安全配置並保持最新
- 保護檔案上傳免受 CSRF 攻擊
內容
上傳檔案的危險
要保護好系統,知道自己面對什麼樣的問題是非常重要的。這樣才知道具體上要做什麼保護措施。
以下章節展示上傳檔案時隨之而來的風險。
惡意檔案
攻擊者可能會上傳惡意檔案,比方說:
- 針對檔案分析器或處理模組的弱點攻擊(比方說 ImageTrick Exploit 和 XXE)
- 上傳釣魚檔案(比方說企業簡歷)
- 上傳 ZIP bombs 或 XML bombs(也被稱為 billion laughs attack)。或者上傳一個超大的檔案,讓系統容量爆滿,破壞主機的可用性。
- 嘗試覆寫系統內已存的檔案
- 攻擊客戶端的檔案(XSS、CSRF⋯⋯等)。當其他用戶存取到這些檔案時,會對用戶產生危害。
公開檔案檢索
如果上傳的檔案之後會公開,那麼會有其他的風險:
- 導致其他文件公開泄露
- 通過請求大量檔案來發起 DoS 攻擊。請求很小,但回應卻要大得多
- 檔案內容可能被視為非法、冒犯性或危險(例如個人資料、受版權保護的資料等),這將使您成為這些惡意檔案的主機。
上傳檔案防護
在驗證使用者內容方面並無萬無一失的方法。實施深度防禦方法是使上傳過程更加困難並更加符合服務的需求和要求的關鍵。實施多種技術是關鍵且建議的,因為沒有一種技術足以保護服務。
副檔名驗證
確保驗證發生在解碼檔案名之後,並設置適當的過濾器,以避免某些已知的繞過方式,例如:
- 雙重副檔名,例如
.jpg.php
,其中它很容易繞過正則表達式\.jpg
- 空字節,例如
.php%00.jpg
,其中.jpg
被截斷,而.php
成為新的副檔名 - 通用的不良正則表達式,未經適當測試和審查。除非您對此主題有足夠的了解,否則請避免構建自己的邏輯。
請參考 輸入驗證 CS 以正確解析和處理副檔名。
副檔名白名單
只允許使用 商業邏輯上極重要的 檔案格式,不允許任何類型的 非必要 擴充功能。例如,如果系統需要:
- 上傳圖片,允許商務需求上一致認同的一種型態
- 上傳履歷,允許
docx
和pdf
格式
根據應用本身的需求,確保使用傷害最小和風險最低的檔案型態。
副檔名黑名單
只使用副檔名黑名單是非常危險的,除非沒有其他辦法,不然別這樣做。
In order to perform this validation, specifying and identifying which patterns that could should be rejected are used in order to protect the service.
內容類型驗證
用戶提供上傳檔案的內容類型,因此不能信任,因為很容易進行欺騙。儘管不應依賴它來進行安全性,但它提供了一個快速檢查,以防止用戶意外上傳具有不正確類型的檔案。
除了定義上傳檔案的擴充功能外,可以檢查其 MIME 類型,以快速保護免受簡單檔案上傳攻擊。
最好以白名單的方式進行;否則,可以以黑名單的方式進行。
檔案簽名驗證
與 內容類型驗證 一起,可以檢查並驗證檔案的簽名,以確認是否符合應收到的預期檔案。
這不應單獨使用,因為繞過它非常常見且容易。
檔名過濾
檔名可能以多種方式危害系統,可以使用不可接受的字元,或使用特殊和受限制的檔名。對於 Windows,請參考以下 MSDN 指南。有關不同檔案系統及其處理檔案方式的更廣泛概述,請參考 維基百科的檔名頁面。
為了避免上述威脅,創建一個隨機字串作為檔案名稱是必要的,例如生成 UUID/GUID。如果業務需求需要檔案名稱,應對客戶端進行適當的輸入驗證(例如 導致 XSS 和 CSRF 攻擊的主動內容)和後端(例如 特殊檔案覆寫或創建)攻擊向量。應根據存儲檔案的系統,考慮檔案名稱長度限制,因為每個系統都有自己的檔案名稱長度限制。如果需要使用使用者檔案名稱,請考慮實施以下措施:
- 實施最大長度
- 限制字符為特定允許的子集,例如字母數字字符、連字符、空格和句號
- 如果不可能,則封鎖可能危及存儲和使用檔案的框架和系統的危險字符。
檔案內容驗證
如在公共檔案檢索部分所述,檔案內容可能包含惡意、不當或非法數據。
根據預期類型,可以應用特殊的檔案內容驗證:
- 對於圖像,應用圖像重寫技術可以消除圖像中注入的任何類型的惡意內容;這可以通過隨機化來完成。
- 對於Microsoft 文件,使用Apache POI有助於驗證上傳的文件。
- ZIP 檔案不建議使用,因為它們可能包含各種類型的檔案,與之相關的攻擊向量很多。
檔案上傳服務應允許用戶舉報非法內容,並允許版權所有者舉報濫用。
如果有足夠的資源,應在釋放檔案到公眾之前在受控環境中進行手動檔案審查。
將一些自動化添加到審查中可能會有所幫助,這是一個嚴格的過程,在使用之前應該進行充分研究。一些服務(例如 病毒總)提供 API 來掃描文件以對抗眾所周知的惡意文件哈希。一些框架可以檢查和驗證原始內容類型,並將其與預定義的文件類型進行驗證,例如在ASP.NET 繪圖庫中。請注意公共服務可能導致數據洩露威脅和信息收集。
檔案儲存位置
應根據安全性和業務需求來選擇應存儲檔案的位置。以下點由安全性優先順序設定,並包括:
- 將檔案存儲在不同的主機上,這樣可以完全區分用戶端應用程式和處理檔案上傳及存儲的主機之間的職責。
- 將檔案存儲在網站根目錄之外,僅允許管理訪問。
- 將檔案存儲在網站根目錄內,並僅設置寫入權限。
- 如果需要讀取訪問權限,設置適當的控制是必要的(例如 內部 IP、授權使用者等)。
以研究方式將檔案存儲在資料庫中是一種額外的技術。這有時用於自動備份過程、非檔案系統攻擊和權限問題。然而,這也會帶來性能問題(在某些情況下)、資料庫及其備份的存儲考量,以及可能引發 SQLi 攻擊的風險。建議僅在團隊中有資料庫管理員(DBA)並且此過程證明是將其存儲在檔案系統上的改進時才使用。
有些檔案在上傳後會通過電子郵件發送或處理,並不會存儲在伺服器上。在對其進行任何操作之前,必須在此表中討論的安全措施。
使用者權限
在訪問任何檔案上傳服務之前,應對上傳檔案的使用者進行兩個層面的適當驗證:
- 認證層級
- 使用者應為註冊使用者或可識別使用者,以便為其上傳功能設置限制和限制
- 授權層級
- 使用者應具有適當的權限以訪問或修改檔案
檔案系統權限
根據最低權限原則設置檔案權限。
應以確保以下方式存儲檔案:
- 允許的系統使用者是唯一能夠讀取檔案的使用者
- 檔案僅設置所需的模式
- 如果需要執行,則在運行之前掃描檔案是一種安全最佳實踐,以確保沒有可用的巨集或隱藏腳本。
上傳下載限制
應用程式應該為上傳服務設定適當的大小限制,以保護檔案儲存容量。如果系統將要提取檔案或處理它們,則在進行檔案解壓縮後應考慮檔案大小限制,並使用安全方法來計算 zip 檔案大小。有關詳細資訊,請參閱如何從ZipInputStream安全提取檔案,Java的輸入串流來處理 ZIP 檔案。
應用程式還應為下載服務設定適當的請求限制,以保護伺服器免受 DoS 攻擊。
Java程式碼節錄
Dominique 所撰寫的 Document Upload Protection ,用於Java中的某些文件類型。