php代碼審計應(yīng)從配置安全、輸入驗證、輸出編碼等10個方面入手。①檢查php.ini關(guān)閉register_globals和display_Errors;②所有用戶輸入需嚴(yán)格過濾;③輸出到html或數(shù)據(jù)庫時分別進(jìn)行html編碼和sql轉(zhuǎn)義;④記錄錯誤日志但不暴露敏感信息;⑤設(shè)置https及安全Cookie選項;⑥限制上傳文件類型并重命名;⑦避免使用eval等危險函數(shù);⑧使用預(yù)處理語句防止sql注入;⑨對輸出數(shù)據(jù)進(jìn)行上下文編碼;⑩利用靜態(tài)分析工具提高效率,同時人工復(fù)核確保準(zhǔn)確性。
PHP代碼審計,簡單來說,就是檢查你的PHP代碼,看看有沒有安全漏洞。這事兒很重要,不然你的網(wǎng)站可能就被黑了,數(shù)據(jù)被盜,甚至直接癱瘓。
代碼審計也不是說非得是安全專家才能做,了解一些常見的漏洞類型,再配合一些工具,你自己也能發(fā)現(xiàn)不少問題。
PHP代碼審計:常見漏洞檢測
立即學(xué)習(xí)“PHP免費學(xué)習(xí)筆記(深入)”;
如何開始PHP代碼審計?從哪里入手?
開始代碼審計,我覺得最重要的是先了解你的項目。項目的架構(gòu)、功能模塊、使用的框架和第三方庫,都要心里有數(shù)。然后,你可以從以下幾個方面入手:
-
配置安全: 檢查php.ini,看看有沒有開啟register_globals,這個必須關(guān)掉,不然太危險了。還有display_errors,生產(chǎn)環(huán)境一定要關(guān)掉,不然會泄露服務(wù)器信息。safe_mode和open_basedir也可以考慮配置,增加安全性。
-
輸入驗證: 這是重中之重!所有來自用戶的輸入,都要經(jīng)過嚴(yán)格的驗證和過濾。包括GET、POST、COOKIE、REQUEST等等。不要相信任何用戶的輸入!
-
輸出編碼: 輸出到HTML頁面時,要進(jìn)行HTML編碼,防止xss攻擊。輸出到數(shù)據(jù)庫時,要進(jìn)行SQL轉(zhuǎn)義,防止SQL注入。
-
錯誤處理: 錯誤處理要做好,但不要泄露敏感信息。可以記錄錯誤日志,方便調(diào)試和排查問題。
-
會話管理: 會話管理要安全,使用https,設(shè)置Session.cookie_secure和session.cookie_httponly,防止會話劫持。
-
文件上傳: 文件上傳要嚴(yán)格限制文件類型,不要允許上傳可執(zhí)行文件。上傳后的文件要重命名,防止覆蓋已有文件。
-
代碼執(zhí)行: 避免使用eval()、system()、exec()等危險函數(shù),如果必須使用,要進(jìn)行嚴(yán)格的參數(shù)控制。
當(dāng)然,這只是一個大致的框架,具體還要根據(jù)你的項目情況來調(diào)整。
PHP代碼審計中,SQL注入漏洞如何高效檢測?
SQL注入,絕對是PHP代碼審計的重點。很多網(wǎng)站被黑,都是因為SQL注入。
檢測SQL注入,可以從以下幾個方面入手:
-
查找所有SQL查詢: 使用代碼搜索工具,查找所有的SQL查詢語句,包括mysql_query()、mysqli_query()、pdo的query()、prepare()等等。
-
檢查參數(shù)來源: 檢查SQL查詢語句中的參數(shù),看它們是否來自用戶的輸入。如果是,就要特別小心。
-
檢查過濾: 檢查是否對參數(shù)進(jìn)行了過濾。常用的過濾函數(shù)有mysql_real_escape_string()、mysqli_real_escape_string()、PDO的quote()等等。但是,僅僅使用這些函數(shù)是不夠的,還需要根據(jù)具體的數(shù)據(jù)庫類型和字符集進(jìn)行調(diào)整。
-
使用預(yù)處理語句: 強(qiáng)烈建議使用預(yù)處理語句(Prepared Statements),這是防止SQL注入的最有效方法。預(yù)處理語句可以將sql語句和參數(shù)分開處理,避免參數(shù)被解析成SQL代碼。
// 使用PDO預(yù)處理語句 $stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password"); $stmt->bindParam(':username', $username); $stmt->bindParam(':password', $password); $stmt->execute();
-
模糊測試: 使用SQL注入的payload進(jìn)行模糊測試,看看是否能繞過過濾。常用的payload可以從網(wǎng)上找,也可以自己構(gòu)造。
例如,可以嘗試以下payload:
' OR '1'='1 " OR "1"="1 ; DROP TABLE users;
-
靜態(tài)分析工具: 使用靜態(tài)分析工具,如RIPS、PHPStan等,可以自動檢測SQL注入漏洞。這些工具可以分析代碼的結(jié)構(gòu)和數(shù)據(jù)流,找出潛在的安全問題。
# 使用RIPS進(jìn)行靜態(tài)分析 rips --scan /path/to/your/code
記住,SQL注入的檢測是一個持續(xù)的過程,需要不斷學(xué)習(xí)新的攻擊技術(shù)和防御方法。
XSS跨站腳本漏洞在PHP代碼審計中如何發(fā)現(xiàn)和修復(fù)?
XSS(Cross-Site Scripting)跨站腳本漏洞也是PHP代碼審計中需要重點關(guān)注的。XSS攻擊者可以在你的網(wǎng)站上注入惡意腳本,盜取用戶cookie,甚至控制用戶的瀏覽器。
發(fā)現(xiàn)XSS漏洞,主要看輸出。
-
查找所有輸出點: 查找所有將數(shù)據(jù)輸出到HTML頁面的地方,包括echo、print、printf、= ?>等等。
-
檢查數(shù)據(jù)來源: 檢查輸出的數(shù)據(jù)是否來自用戶的輸入。如果是,就要特別小心。
-
檢查編碼: 檢查是否對輸出的數(shù)據(jù)進(jìn)行了HTML編碼。常用的編碼函數(shù)有htmlspecialchars()、htmlentities()等等。
// 使用htmlspecialchars()進(jìn)行HTML編碼 echo htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
-
上下文編碼: 根據(jù)輸出的上下文,選擇合適的編碼方式。例如,在HTML標(biāo)簽內(nèi)部,可以使用HTML編碼;在JavaScript代碼中,可以使用JavaScript編碼;在URL中,可以使用URL編碼。
-
內(nèi)容安全策略(CSP): 使用CSP可以限制瀏覽器加載外部資源,防止XSS攻擊。CSP需要在HTTP響應(yīng)頭中設(shè)置。
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
-
過濾特殊字符: 除了編碼,還可以過濾一些特殊字符,如、”、’等等。
-
使用模板引擎: 一些模板引擎,如Twig、Smarty等,會自動進(jìn)行HTML編碼,可以減少XSS漏洞的風(fēng)險。
修復(fù)XSS漏洞,最重要的是對所有用戶輸入進(jìn)行嚴(yán)格的驗證和過濾,并對所有輸出進(jìn)行合適的編碼。
文件上傳漏洞:PHP代碼審計的常見陷阱
文件上傳漏洞,也是PHP代碼審計中一個常見的陷阱。如果允許用戶上傳任意文件,攻擊者可以上傳惡意腳本,甚至控制服務(wù)器。
檢測和修復(fù)文件上傳漏洞,可以從以下幾個方面入手:
-
限制文件類型: 嚴(yán)格限制允許上傳的文件類型,只允許上傳必要的文件類型。可以使用白名單機(jī)制,只允許上傳指定的文件類型。
$allowed_types = array('jpg', 'jpeg', 'png', 'gif'); $file_ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)); if (!in_array($file_ext, $allowed_types)) { die('Invalid file type'); }
-
驗證文件類型: 除了檢查文件擴(kuò)展名,還要驗證文件的MIME類型。可以使用mime_content_type()函數(shù)或exif_imagetype()函數(shù)來驗證文件類型。
$mime_type = mime_content_type($_FILES['file']['tmp_name']); if ($mime_type != 'image/jpeg' && $mime_type != 'image/png') { die('Invalid file type'); }
-
重命名文件: 上傳后的文件要重命名,可以使用隨機(jī)字符串或哈希值作為文件名,防止覆蓋已有文件。
$new_file_name = md5(uniqid(rand(), true)) . '.' . $file_ext;
-
保存目錄: 上傳的文件要保存到獨立的目錄,不要保存到Web根目錄或可執(zhí)行目錄。
-
禁用執(zhí)行權(quán)限: 上傳的文件要禁用執(zhí)行權(quán)限,可以使用.htaccess文件或服務(wù)器配置來禁用執(zhí)行權(quán)限。
# .htAccess <Files *> deny from all </Files>
-
文件大小限制: 限制上傳的文件大小,防止上傳過大的文件。
if ($_FILES['file']['size'] > 1024 * 1024) { // 1MB die('File size too large'); }
-
檢查上傳錯誤: 檢查$_FILES[‘file’][‘error’],處理上傳錯誤。
if ($_FILES['file']['error'] != UPLOAD_ERR_OK) { die('Upload error: ' . $_FILES['file']['error']); }
總之,文件上傳漏洞的防御需要多方面的措施,不能只依賴于單一的防御手段。
如何利用工具輔助PHP代碼審計?
人工審計很耗時,而且容易遺漏。所以,利用工具輔助審計,可以大大提高效率和準(zhǔn)確性。
-
靜態(tài)分析工具:
- RIPS: 專門用于PHP代碼審計的靜態(tài)分析工具,可以自動檢測SQL注入、XSS、代碼執(zhí)行等漏洞。
- PHPStan: PHP靜態(tài)分析工具,可以檢查代碼中的類型錯誤、未定義變量等問題,提高代碼質(zhì)量。
- SonarQube: 代碼質(zhì)量管理平臺,可以分析多種語言的代碼,包括PHP,可以檢測代碼中的安全漏洞、代碼異味等問題。
-
動態(tài)分析工具:
- OWASP ZAP: 開源的Web應(yīng)用程序安全測試工具,可以進(jìn)行SQL注入、XSS等漏洞的掃描。
- Burp Suite: 商業(yè)的Web應(yīng)用程序安全測試工具,功能強(qiáng)大,可以進(jìn)行各種漏洞的掃描和利用。
-
代碼搜索工具:
- grep: linux下的文本搜索工具,可以快速查找代碼中的關(guān)鍵字。
- ack: 比grep更適合代碼搜索的工具,可以忽略版本控制目錄和二進(jìn)制文件。
-
ide插件:
- phpstorm: 強(qiáng)大的PHP IDE,有很多安全相關(guān)的插件,可以輔助代碼審計。
- VS Code: 輕量級的代碼編輯器,也有很多安全相關(guān)的插件。
選擇合適的工具,可以大大提高代碼審計的效率。但是,工具只是輔助,最終還是要靠人工進(jìn)行分析和判斷。
遠(yuǎn)程代碼執(zhí)行漏洞(RCE)在PHP代碼審計中如何避免?
遠(yuǎn)程代碼執(zhí)行(RCE)漏洞,一旦被利用,攻擊者可以直接控制服務(wù)器,后果非常嚴(yán)重。
避免RCE漏洞,最重要的是不要讓用戶能夠執(zhí)行任意代碼。
-
禁用危險函數(shù): 在php.ini中禁用eval()、system()、exec()、shell_exec()、passthru()、proc_open()、popen()等危險函數(shù)。
disable_functions = eval,system,exec,shell_exec,passthru,proc_open,popen
-
嚴(yán)格控制參數(shù): 如果必須使用system()、exec()等函數(shù),要對參數(shù)進(jìn)行嚴(yán)格的控制,防止用戶注入惡意代碼。
-
避免使用unserialize(): unserialize()函數(shù)可以將序列化的數(shù)據(jù)反序列化成對象,如果序列化的數(shù)據(jù)包含惡意代碼,可能會導(dǎo)致RCE漏洞。盡量避免使用unserialize()函數(shù)。如果必須使用,要對序列化的數(shù)據(jù)進(jìn)行嚴(yán)格的驗證。
-
使用沙箱環(huán)境: 可以使用沙箱環(huán)境來限制代碼的執(zhí)行權(quán)限,防止代碼執(zhí)行惡意操作。
-
代碼審計: 定期進(jìn)行代碼審計,查找潛在的RCE漏洞。
RCE漏洞的防御是一個復(fù)雜的問題,需要從多個方面入手,才能有效地避免。
審計代碼,就像醫(yī)生看病,需要細(xì)心、耐心,找到病根,才能藥到病除。希望這些建議能幫助你更好地進(jìn)行PHP代碼審計,保護(hù)你的網(wǎng)站安全。