跳轉至內容

Web 應用安全指南/檢查清單

來自華夏公益教科書

雜項要點

  • 不要依賴 Web 應用防火牆來保證安全(但是,可以考慮使用它們來提高安全級別)
  • 如果使用了外部庫(例如,用於資料庫訪問、XML 解析),請始終使用最新版本
  • 如果需要隨機數,請從安全/加密隨機數生成器中獲取
  • 對於每個資料操作或檢索,請始終檢查訪問許可權
  • 在任何情況下都不要嘗試自己實現加密演算法。請使用高階庫進行加密。
  • 確保除錯輸出和錯誤訊息不會洩露敏感資訊
  • 在程式碼中標記有問題的除錯輸出(例如 //TODO DEBUG REMOVE),即使您打算在測試後立即將其刪除
  • 不要使用“eval()”和類似函式
    • 如果可能,請避免使用“system()”和類似函式
  • 確保資料庫伺服器無法從外部直接訪問
  • 考慮阻止舊版瀏覽器使用您的應用程式

檔案包含與洩露

  • 不要從使用者輸入中獲取包含檔案的名稱,只能從受信任的列表或常量中獲取。
    • 如果要使用使用者輸入,請根據白名單進行驗證。檢查檔案是否存在或輸入是否匹配特定格式是不夠的。
  • 如果可能,請避免讓指令碼讀取和傳遞檔案。
  • 如果您使用使用者提供的檔名讀取和傳遞檔案,請徹底驗證檔名以避免目錄遍歷和類似攻擊,並確保使用者有權讀取該檔案。
  • 確保應用程式執行時沒有超過所需的許可權。

檔案上傳漏洞

  • 避免不必要的檔案上傳
  • 確保使用者上傳的檔案不會被 Web 伺服器解釋為指令碼檔案,例如,透過檢查副檔名(或 Web 伺服器用於識別指令碼檔案的任何方法)
  • 確保檔案無法上傳到意外的目錄(目錄遍歷)
  • 嘗試停用上傳目錄中的指令碼執行
  • 確保副檔名與檔案內容的實際型別匹配
  • 如果只需要上傳影像,請考慮使用安全庫重新壓縮它們以確保它們有效
  • 確保上傳的檔案在傳遞給使用者時使用正確的 Content-type 指定
  • 使用允許的檔案型別白名單,防止使用者上傳有問題的檔案型別,例如 HTML、CSS、JavaScript、XML、SVG 和可執行檔案
  • 防止使用者上傳特殊檔案(例如 .htaccess、web.config、robots.txt、crossdomain.xml、clientaccesspolicy.xml)
  • 防止使用者覆蓋應用程式檔案
  • 考慮使用“Content-disposition: attachment”標頭傳遞上傳的檔案

SQL 注入

  • 使用預處理語句訪問資料庫 – 或 –
  • 使用儲存過程,並使用適當的語言/庫方法或預處理語句進行訪問
  • 始終確保應用程式使用的資料庫登入名僅具有所需的許可權

跨站指令碼 (XSS)

  • 在將任何非常量內容包含在響應中之前,儘可能靠近輸出位置進行轉義(即,在包含“echo”或“print”呼叫的行中)
  • 如果不可能(例如,在構建較大的 HTML 塊時),請在構建時進行轉義,並指示變數內容已預先轉義以及名稱中的預期上下文。
  • 在轉義時考慮上下文:轉義 HTML 內部的文字與轉義 HTML 屬性值不同,並且與轉義 CSS 或 JavaScript 內部的值或 HTTP 標頭內的值非常不同。
    • 這可能意味著您需要針對多個上下文和/或多次進行轉義。例如,當將 HTML 片段作為 JS 常量傳遞以供稍後包含在文件中時,在將常量寫入 JavaScript 原始碼時,需要針對 HTML 中的 JS 字串進行轉義,然後在指令碼將片段寫入文件時,再次針對 HTML 進行轉義。(請參閱基本原理以獲取示例)
    • 攻擊者絕不能將任何內容放在不應放置的位置,即使您認為它不可利用(例如,因為嘗試利用它會導致 JavaScript 損壞)。
  • 在文件開頭(即,儘早)和/或標頭中顯式設定正確的字元集。
  • 確保使用者提供的 URL 以允許的方案開頭(白名單),以避免危險的方案(例如 javascript:-URL)
  • 不要忘記重定向指令碼中的 URL
  • 可以將內容安全策略用作額外的安全措施,但它本身不足以防止攻擊。

XML 和內部資料轉義

  • 如果可能,請避免使用 XML。
  • 對於 XML,請使用經過良好測試的高質量庫,並密切關注文件。瞭解您的庫 - 一些庫具有允許您在不知情的情況下繞過轉義的函式。
  • 如果您解析(讀取)XML,請確保您的解析器不嘗試載入外部引用(例如實體和 DTD)。
  • 對於資料的其他內部表示形式,請確保應用了正確的轉義或過濾。即使看起來更困難,也嘗試使用經過良好測試的高質量庫(如果可用)。
  • 如果手動進行轉義,請確保它能夠以安全的方式處理空位元組、意外字元集、無效的 UTF-8 字元等。

XML、JSON 和通用 API 安全

  • 確保對 API 進行適當的訪問控制
  • 不要忘記您需要正確轉義所有輸出以防止 XSS 攻擊,資料格式(如 XML)需要特別考慮,並且在許多情況下都需要防止跨站請求偽造 (CSRF)
  • 使用具有成熟庫的標準資料格式(如 JSON),並正確使用它們。這可能會處理您所有的轉義需求。
  • 確保瀏覽器不會誤解您的文件或允許跨站點載入
    • 確保您的文件格式正確
    • 傳送正確的 content type
    • 使用 X-Content-Type-Options: nosniff 標頭
    • 對於 XML,請提供字元集並確保攻擊者無法插入任意標籤
    • 對於 JSON,請確保頂級資料結構是物件,並且 HTML 中所有具有特殊含義的字元都已轉義

(不)受信任的輸入

  • 徹底過濾/轉義任何不受信任的內容
  • 如果某些輸入欄位的允許字元集受到限制,請在使用它之前檢查輸入是否有效
  • 如果您對某種資料(例如伺服器變數)有疑問,請將其視為不受信任的
  • 如果您確定,但沒有真正需要將其視為受信任的,請將其視為不受信任的
  • 請求 URL(例如,在環境變數中)不受信任
  • 來自 HTTP 標頭的資料不受信任
    • Referer
    • X-Forwarded-For
    • Cookie
    • 伺服器名稱(!)
  • 所有 POST 和 GET 資料都不受信任
    • 包括不可修改的使用者輸入欄位,例如 select
  • 所有內容驗證都必須在伺服器端完成

跨站請求偽造 (CSRF)

  • 包含一個隱藏的表單欄位,其中包含與使用者會話(最好是執行的操作)繫結的隨機令牌,並在響應中檢查此令牌
  • 確保令牌不可預測,攻擊者無法獲取
    • 不要將其包含在攻擊者可以使用 <script> 標籤載入到其站點中的檔案中
  • Referer 檢查不安全,但可以用作附加措施

點選劫持

  • 透過包含 HTTP 響應標頭“來防止在當前瀏覽器中對您的應用程式進行 (i)framingX-Frame-Options: deny
  • 透過包含一個 JavaScript 框架破壞程式來防止在過時的瀏覽器中進行 (i)framing,該程式檢查 (i)framing,如果檢測到則拒絕顯示頁面
  • 對於安全要求高的應用程式,您希望使用者使用 JavaScript 停用的過時瀏覽器,請考慮要求使用舊版瀏覽器的使用者啟用 JavaScript

不安全的資料傳輸

  • 對任何和所有資料傳輸使用 SSL/TLS (https)
  • 不要以 http 方式開始通訊,只有在“需要”時才重定向到 https
  • 使用“secure”屬性標記 Cookie
  • 在可能的情況下使用 Strict-Transport-Security 標頭
  • 教育使用者直接訪問https://URL
  • 如果您的 Web 應用程式執行 HTTPS 請求,請確保它驗證證書和主機名
    • 如果連線到內部伺服器,請考慮限制受信任的 CA

會話固定

  • 在使用者登入後立即重新生成(更改)會話 ID(銷燬舊會話)

  • 防止攻擊者透過使用者會話來利用使用者,僅從cookie中獲取會話ID,而不是從GET或POST引數中獲取(PHP:php.ini設定“session.use_only_cookies”)

會話劫持

  • 為會話cookie設定“HttpOnly”屬性
  • 使用安全的隨機性和足夠的長度生成隨機會話ID
  • 不要洩露會話ID

截斷攻擊,修剪攻擊

  • 避免截斷輸入。將過長的輸入視為錯誤。
  • 如果需要截斷,請確保在截斷後檢查值,並且僅使用截斷後的值
  • 確保不會發生修剪或一致地進行檢查
  • 引入長度檢查
    • 注意由於編碼導致的不同長度
  • 透過設定適當的SQL模式,確保SQL將截斷的查詢視為錯誤SQL模式

密碼安全

  • 不要儲存明文密碼,只儲存雜湊值
  • 使用Argon2、scrypt、bcrypt或其他專為安全密碼儲存而設計的安全雜湊演算法。[1][2]
  • 使用每個使用者的鹽值
  • 使用增強(例如多迭代雜湊來減緩暴力破解嘗試)
  • 限制每個IP的登入嘗試次數(而不是每個使用者帳戶)
  • 實施合理但不要過於嚴格的密碼策略
  • 如果實施了密碼重置流程,請確保其具有足夠的安全性。“母親的孃家姓”之類的問題通常可以被攻擊者猜測,並且不夠安全。

比較問題

  • 瞭解程式語言中的比較型別並使用正確的型別
  • 如有疑問(尤其是使用PHP時),請使用嚴格比較(PHP:“===”)
  • 當比較字串是否相等時,請確保您實際上是在檢查字串是否相等,而不是一個字串是否包含另一個字串

PHP特定問題

  • 不要使用簡寫形式“<?”,始終使用完整形式“<?php
  • 當使用nginx web伺服器時,請確保正確遵循**官方**安裝說明並注意“陷阱”頁面。注意一些教程中經常包含有效的但不安全的配置示例。
  • 在某些情況下,preg_replace可以充當eval()。避免將使用者輸入傳遞給它。如果必須這樣做,請正確過濾和轉義它。
  • 使用Suhosin(如果可能,包括補丁)並使用嚴格規則進行配置
    • 啟用suhosin.executor.disable_emodifier
    • 如果可能,啟用suhosin.executor.disable_eval
    • 如果可能,將suhosin.mail.protect設定為2
  • 從舊版本更新PHP到PHP 5.4時,請確保舊版應用程式不依賴於magic quotes來保證安全。

預取和蜘蛛

  • 對於觸發任何操作的任何內容,請使用POST請求而不是GET請求

特殊檔案

  • 瞭解這些檔案的含義
  • 確保robots.txt不洩露“秘密”路徑
  • 除非需要,否則確保crossdomain.xml和clientaccesspolicy.xml不存在
  • 如果使用,請確保crossdomain.xml和clientaccesspolicy.xml僅允許來自受信任域的訪問
  • 防止使用者上傳/更改特殊檔案(請參閱檔案上傳漏洞部分

SSL、TLS和HTTPS基礎

  • 遵循SSLLabs最佳實踐,包括
    • 確保停用SSLv2
    • 自己生成證書的私鑰,不要讓您的CA來做
    • 使用合適的金鑰長度(通常在2013年為2048位)
    • 如果可能,停用客戶端發起的重新協商
    • 考慮手動限制/設定密碼套件
  1. Patrick Mylund Nielsen。“安全儲存密碼”
  2. Wikibook密碼學/安全密碼描述了為密碼儲存設計雜湊演算法的歷史和理論。
華夏公益教科書