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