文件上載功能怎麼安全實現提示詞(類型校驗、大小限制、存儲與訪問控制、防路徑穿越,防禦向自查)

要實現頭像上載、附件上載、批量導入這類功能,或者審查現有上載接口是否安全時用:AI 按防禦清單逐項檢查和實現:只信任服務端識別的文件類型、限制大小與數量、重命名並存到不可執行的位置、下載時校驗權限,給出完整的接口代碼。

NNathaniel bigo··原創首發·AI 輔助撰寫
通用大模型 對話模型通用
你是一名注重安全的後端工程師。請幫我實現(或審查)一個文件上載功能,目標是防禦常見的上載風險。本任務只用於加固自己的系統。

- 上載場景:[上載場景](例:用戶上載頭像、工單附件、Excel 批量導入)
- 允許的文件類型與大小:[類型與大小](例:jpg、png,最大 5MB)
- 技術棧:[技術棧](例:Node.js + Express)
- 存儲位置:[存儲位置](例:本地磁盤、對象存儲)
- 誰能訪問上載後的文件:[訪問範圍](例:僅上載者本人和管理員)
- 現有代碼(審查時填寫):
  [粘貼代碼]

逐項實現或檢查:
1. 大小與數量:在網關和應用兩層限制請求體大小;限制單次上載的文件數;流式處理,避免把整個大文件讀進內存。
2. 類型校驗:
   - 用白名單而不是黑名單;
   - 不信任客戶端聲明的類型和文件擴展名,根據文件內容的特徵識別真實類型;
   - 圖片可以重新解碼並重新編碼,去除附帶的元數據和隱藏內容;
   - 壓縮包、表格、文檔類文件的額外風險(如解壓炸彈、宏、公式注入),以及對應的處理方式。
3. 文件名與路徑:服務端生成隨機文件名,不使用用戶提供的文件名拼接路徑;原始文件名只作為元數據儲存,顯示時轉義;防止路徑穿越。
4. 存儲:存放在不會被當作腳本執行的位置,最好與應用代碼分離(對象存儲或獨立目錄);不要放在網站根目錄下可以直接執行的位置。
5. 訪問控制:下載時校驗當前用戶是否有權訪問;私有文件使用短期有效的簽名連結;響應時設定正確的內容類型和「作為附件下載」的頭,防止在瀏覽器中被當作網頁執行。
6. 其他:需要時對文件做病毒掃描(如 ClamAV);記錄上載日誌;限制上載頻率;定期清理未被引用的文件。

輸出:風險檢查表(項目 | 當前是否滿足 | 風險 | 建議)、完整的上載與下載接口代碼(中文註釋)、測試用例清單(例如偽造擴展名的文件、超大文件、含路徑字符的文件名、越權下載)。
另外說明:前端預檢查只為體驗,服務端校驗才算數;對象存儲的桶預設設為私有,禁止列出目錄。

高亮處換成你自己的內容:[上載場景]、[類型與大小]、[技術棧]、[存儲位置]、[訪問範圍]、[粘貼代碼]

ChatGPT Plus 充值

已被複製 0 次

使用說明

怎麼填變量:[允許的文件類型與大小] 越嚴格越安全,只開放業務真正需要的類型。[誰能訪問上載後的文件] 決定了是否需要簽名連結和下載權限校驗,用戶私人附件絕不能用可以被猜到的公開地址。

常見坑:

  • 只檢查文件擴展名或瀏覽器傳來的類型字段,攻擊者改個名字就能繞過。要根據文件內容識別類型。
  • 直接用用戶上載的文件名儲存,文件名裏帶上級目錄符號,就可能寫到預期目錄之外。
  • 上載的文件可以通過固定規律的地址直接訪問,任何人都能遍歷下載別人的附件。

追問技巧:追問「Excel 批量導入時,如何防止單元格中的公式在別人打開導出文件時被執行」,或「改為前端直傳對象存儲時,服務端還需要做哪些校驗」。

示例輸出

示例,僅供參考(Node.js,節選)
項目當前風險建議
類型校驗只檢查擴展名偽造擴展名上載任意文件讀取文件頭識別真實類型,只允許 jpg、png
文件名使用原始文件名路徑穿越、覆蓋其他文件服務端生成隨機文件名
訪問控制公開固定地址越權下載下載接口校驗歸屬,或使用短期簽名連結
js
const ALLOWED = new Map([['image/jpeg', 'jpg'], ['image/png', 'png']])

async function saveUpload(buffer, userId) {
  const type = await fileTypeFromBuffer(buffer)             // 根據文件內容識別類型
  if (!type || !ALLOWED.has(type.mime)) throw new BadRequest('只支持 JPG、PNG 圖片')
  const name = `${crypto.randomUUID()}.${ALLOWED.get(type.mime)}`   // 不使用用戶提供的文件名
  const clean = await sharp(buffer).rotate().toBuffer()     // 重新編碼,去除附帶的元數據
  await storage.put(`avatars/${userId}/${name}`, clean, { contentType: type.mime })
  return name
}

同款作品

用這條提示詞做出來的作品;原作者會因此獲得積分

做同款

還沒有同款,來做第一個。

Nathaniel 的更多內容

同主題

同模型

0 條評論

登入 後參與評論

還沒有評論,來搶沙發~