PHP 提供了大量系統級函數,賦予腳本強大能力的同時,也帶來了極高的安全風險。一旦應用存在代碼注入、文件包含、反序列化等漏洞,攻擊者可利用這些函數執行任意命令、讀寫文件、竊取數據甚至控制服務器。本文對常見高危函數進行分級梳理,說明風險成因並給出具體防範配置建議。
| 函數 | 功能 | 典型利用場景 | 防範建議 |
|---|---|---|---|
exec() | 執行外部命令,返回最後一行輸出 | exec("cat /etc/passwd")、反彈 Shell | 禁用:disable_functions=exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec |
passthru() | 執行命令並直接輸出原始結果 | 輸出二進制數據、繞過輸出捕獲 | |
shell_exec() | 通過 Shell 執行命令,返回完整輸出字符串 | `id` 反引號等價調用 | |
system() | 執行命令並輸出,返回最後一行 | 同 exec,但自動輸出 | |
proc_open() | 打開進程管道,雙向通信 | 交互式 Shell、繞過 disable_functions (配合 proc_get_status) | |
popen() | 打開進程管道,單向讀/寫 | 寫入惡意腳本、讀取敏感文件 | |
pcntl_exec() | 在當前進程空間執行新程序 | 繞過 disable_functions 限制 | 禁用 pcntl 擴展或具體函數 |
dl() | 運行時加載 PHP 擴展 | 加載惡意 .so/.dll 實現持久化 | enable_dl=Off (PHP 5.3+ 默認關閉) |
mail() | 發送郵件 (第五參數傳遞 sendmail 參數) | mail("a","b","c","d","-X /var/www/shell.php") 寫 Webshell | 禁用或限制第五參數,使用 PHPMailer 等庫 |
putenv() | 設置環境變量 | CVE-2021-41773 (Path Traversal via LD_PRELOAD) | PHP 5.2.6+ 已修復,仍建議 disable_functions=putenv |
ini_set()/ini_alter()/ini_restore() | 修改/恢復 PHP 配置 | 運行時開啟 allow_url_include、修改 disable_functions | 禁用,配置應在 php.ini 靜態設置 |
| 函數 | 風險 | 防範 |
|---|---|---|
scandir()/readdir()/opendir() | 目錄遍歷,洩露項目結構、敏感文件 | 禁用或配合 open_basedir 限制訪問範圍 |
file_get_contents()/readfile()/fopen() | 任意文件讀取 (配合 php://filter、phar:// 等封裝協議) | open_basedir、禁用危險封裝協議、allow_url_fopen=Off |
chdir()/chroot() | 改變工作目錄/根目錄,可能逃逸限制 | 禁用,open_basedir 已提供目錄限制 |
symlink()/link()/readlink() | 創建/讀取符號鏈接,繞過 open_basedir 訪問受限文件 | 禁用,文件系統層面限制權限 |
error_log() | 早期版本可繞過 safe_mode 執行命令 | 升級 PHP、禁用或限制日誌路徑 |
syslog() | 調用系統日誌,可能洩露內部信息 | 按需禁用 |
; 1. 核心禁用列表 (根據業務精簡,避免誤傷正常功能)
disable_functions = exec,passthru,shell_exec,system,proc_open,proc_get_status,proc_close,proc_nice,proc_terminate,popen,pclose,pcntl_exec,pcntl_fork,pcntl_signal,pcntl_alarm,pcntl_wait,pcntl_waitpid,pcntl_wexitstatus,pcntl_wifsignaled,pcntl_wifexited,pcntl_wifstopped,pcntl_wstopsig,pcntl_wtermsig,dl,mail,putenv,ini_set,ini_alter,ini_restore,chroot,chgrp,chown,symlink,link,readlink,scandir,readdir,opendir,chdir
; 2. 文件系統訪問控制
open_basedir = /var/www/html:/tmp:/var/lib/php/session
; 僅允許腳本訪問項目目錄、臨時目錄、Session 目錄
; 3. 禁用危險的流封裝協議
; allow_url_fopen = Off ; 禁止 HTTP/FTP 遠程文件包含
; allow_url_include = Off ; 禁止遠程代碼包含 (默認 Off)
; 4. 會話與上傳安全
session.cookie_httponly = 1
session.cookie_secure = 1 ; 僅 HTTPS
session.use_strict_mode = 1
file_uploads = On
upload_tmp_dir = /var/www/tmp_upload
upload_max_filesize = 10M
max_file_uploads = 20
; 5. 錯誤顯示與日誌
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/error.log
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
; 6. 其他加固
expose_php = Off ; 隱藏 PHP 版本
max_execution_time = 30
memory_limit = 128M
post_max_size = 20M
eval/assert/preg_replace(/e)/create_function 等動態代碼執行點。--disable-cli,防止攻擊者通過 Webshell 啟動交互式 Shell 進程。「禁用函數」是基線防護,**而非銀彈**。攻擊者仍可利用 LD_PRELOAD、PHP-FPM 未授權訪問、擴展漏洞 (如 imagick CVE-2016-3714) 繞過限制。完整的防禦體系需包含:代碼層面輸入驗證與輸出編碼、配置層面最小權限原則、運行時層面行為監控與阻斷、基礎設施層面網絡隔離與不可變部署。定期更新 PHP 版本、關注 CVE 公告、進行滲透測試,方能構建纵深防御。