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位)
- 如果可能,停用客戶端發起的重新協商
- 考慮手動限制/設定密碼套件