?
This document uses PHP Chinese website manual Release
永遠不要信任外部輸入。請在使用外部輸入前進行過濾和驗證。filter_var()和 filter_input() 函數(shù)可以過濾文本并對格式進行校驗(例如 email 地址)。
外部輸入可以是任何東西:$_GET 和 $_POST 等表單輸入數(shù)據(jù),$_SERVER 超全局變量中的某些值,還有通過 fopen('php://input', 'r') 得到的 HTTP 請求體。記住,外部輸入的定義并不局限于用戶通過表單提交的數(shù)據(jù)。上傳和下載的文檔,session 值,cookie 數(shù)據(jù),還有來自第三方 web 服務(wù)的數(shù)據(jù),這些都是外服輸入。
雖然外部輸入可以被存儲、組合并在以后繼續(xù)使用,但它依舊是外部輸入。每次你處理、輸出、連結(jié)或在代碼中包含時,請?zhí)嵝炎约簷z查數(shù)據(jù)是否已經(jīng)安全地完成了過濾。
數(shù)據(jù)可以根據(jù)不同的目的進行不同的 過濾 。比如,當原始的外部輸入被傳入到了 HTML 頁面的輸出當中,它可以在你的站點上執(zhí)行 HTML 和 JavaScript 腳本!這屬于跨站腳本攻擊(XSS),是一種很有殺傷力的攻擊方式。一種避免 XSS 攻擊的方法是在輸出到頁面前對所有用戶生成的數(shù)據(jù)進行清理,使用 strip_tags() 函數(shù)來去除 HTML 標簽或者使用 htmlentities() 或是 htmlspecialchars() 函數(shù)來對特殊字符分別進行轉(zhuǎn)義從而得到各自的 HTML 實體。
另一個例子是傳入能夠在命令行中執(zhí)行的選項。這是非常危險的(同時也是一個不好的做法),但是你可以使用自帶的 escapeshellarg() 函數(shù)來過濾執(zhí)行命令的參數(shù)。
最后的一個例子是接受外部輸入來從文件系統(tǒng)中加載文件。這可以通過將文件名修改為文件路徑來進行利用。你需要過濾掉"/", "../", null 字符或者其他文件路徑的字符來確保不會去加載隱藏、私有或者敏感的文件。
數(shù)據(jù)清理
數(shù)據(jù)清理是指刪除(或轉(zhuǎn)義)外部輸入中的非法和不安全的字符。
例如,你需要在將外部輸入包含在 HTML 中或者插入到原始的 SQL 請求之前對它進行過濾。當你使用 PDO 中的限制參數(shù)功能時,它會自動為你完成過濾的工作。
有些時候你可能需要允許一些安全的 HTML 標簽輸入進來并被包含在輸出的 HTML 頁面中,但這實現(xiàn)起來并不容易。盡管有一些像 HTML Purifier 的白名單類庫為了這個原因而出現(xiàn),實際上更多的人通過使用其他更加嚴格的格式限制方式例如使用 Markdown 或 BBCode 來避免出現(xiàn)問題。
查看 Sanitization Filters
反序列化
將來自用戶或非信任源的數(shù)據(jù)通過 unserialize() 進行反序列化是非常危險的。這樣做將導致惡意用戶的的對象被實例化(帶有用戶自定義屬性),即便此對象本身并未被使用過在被銷毀時析構(gòu)函數(shù)(destructor)仍會被執(zhí)行。因此,切記避免對不被信任的數(shù)據(jù)執(zhí)行反序列化。
如果你確實需要反序列化不被信任的數(shù)據(jù),請設(shè)置 PHP 7 的 allowed_classes配置項以限制能夠被反序列化的對象類型。
有效性驗證
驗證是來確保外部輸入的是你所想要的內(nèi)容。比如,你也許需要在處理注冊申請時驗證 email 地址、手機號碼或者年齡等信息的有效性。