上傳功能看起來只是讓使用者附上一張圖片或 PDF,實際上卻可能成為網站被植入程式、讀取伺服器檔案的入口。以 PHP 回饋系統為例,使用者可能上傳工單附件;即使檔案名稱是 photo.jpg,也不能因此認定它安全。副檔名、瀏覽器傳來的 MIME 類型都能偽造,防護必須從接收、儲存到下載整條流程一起考慮。
不要只檢查副檔名
建議採用明確白名單,只允許業務真正需要的格式,例如 JPG、PNG、PDF 與純文字,並拒絕 PHP、HTML、SVG 等可能帶有腳本或主動內容的檔案。檢查時至少比對副檔名與伺服器端判定的 MIME 類型;圖片還可用 getimagesize() 檢查是否為有效影像。這些檢查不是萬無一失,但比只看檔名可靠得多。
原系統規格提到附件採「副檔名+MIME+圖片檢查」雙重白名單,並禁用 SVG,方向是正確的。若網站只需要展示圖片,還可以考慮用影像函式重新解碼、轉存成標準格式,降低夾帶異常內容的風險。
隔離儲存,下載也要驗證
上傳檔案最好放在網站公開目錄之外,透過 PHP 控制下載;若部署環境無法如此安排,就必須確認上傳目錄禁止執行 PHP 等腳本。檔案應使用隨機名稱儲存,不沿用使用者提供的檔名,並限制單檔大小、數量與總容量。回饋系統設定單檔不超過 10MB、每次最多 5 個附件,能降低濫用與磁碟耗盡的風險。
下載時不可直接拼接網址或路徑。應以資料庫中的附件 ID 查詢實際檔案,檢查登入者是否有權查看該工單,再安全地輸出檔案。否則,即使上傳流程安全,猜測其他附件路徑仍可能造成資料外洩。
留意路徑與部署設定
儲存檔案前要清理檔名、拒絕 ../ 等路徑穿越字串,並確認最終路徑仍位於預定目錄內。PHP 端可設定合理的 upload_max_filesize、post_max_size,伺服器也應限制請求大小;上傳操作則需搭配登入授權、CSRF 防護與速率限制。
最後,別只在上線前測一次。可定期檢查上傳目錄權限、失敗紀錄與異常檔案,並以偽造 MIME、超大檔案及未授權下載情境做測試。上傳漏洞常不是單一檢查失效,而是幾道防線同時缺席;把儲存隔離和下載授權做好,往往比再多寫一條副檔名判斷更關鍵。

評論(10)
以前真的以為檢查副檔名就夠了,這點很容易忽略。
把附件放在公開目錄外,感覺是最值得先做的一步。
下載還要核對工單權限,這個細節常常被漏掉。
圖片重新解碼再存,對只需要展示圖片的網站很實用。
SVG 也要列入限制,很多人可能沒想到它不只是圖片。
每次最多五個附件的限制,是依照使用情境設定比較好嗎?
隨機命名很重要,不然使用者檔名裡有特殊路徑字元就麻煩了。
10MB 的限制對回饋附件應該夠用,也能少些容量管理壓力。
想請教一下,MIME 類型在伺服器端通常用什麼方式判定比較妥當?
偽造 MIME 和未授權下載都納入測試,這樣檢查才比較貼近實際風險。