禁用危险函数需配合open_basedir、allow_url_include=Off和输入过滤三者协同,核心禁用函数为exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,pcntl_fork,pcntl_waitpid,eval,assert,create_function。

禁用危险函数是防范PHP文件包含攻击的基础环节,但单靠disable_functions远远不够——它只拦住“执行命令”的路,拦不住“读取文件+动态包含”这类绕过路径。真正起效的配置必须配合open_basedir、allow_url_include=Off和输入过滤三者协同。
必须禁用的核心函数(PHP 7.4+ 实测有效)
以下函数全部小写、无空格、逗号紧连,缺一不可:
-
exec,passthru,shell_exec,system,proc_open,popen:直接执行系统命令的主力入口 -
pcntl_exec,pcntl_fork,pcntl_waitpid:常被用于绕过传统禁用,尤其在FPM环境中活跃 -
eval,assert,create_function:支持动态代码执行,是文件包含后RCE的关键跳板 -
include,require,include_once,require_once虽不能禁(会崩框架),但必须配合白名单或路径约束使用
光禁函数没用:关键配套措施
攻击者一旦能写入文件(如上传/tmp/shell.php),再用未被禁的include加载,disable_functions就彻底失效。
-
open_basedir 必须设严:例如
open_basedir = /var/www/html:/tmp,既允许网站运行又支持临时文件操作,但禁止访问/etc、/usr等敏感路径 -
关闭远程包含:
allow_url_include = Off+allow_url_fopen = Off,堵死http://、php://filter、zip://等伪协议利用链 -
限制解析扩展名:Nginx + PHP-FPM环境下,确认
security.limit_extensions = .php,防止.phtml、.php5绕过
验证是否真生效,别信表面结果
仅看phpinfo()或function_exists('exec')会误判——函数名存在≠可调用,函数名不存在≠已被拦截。
- Web端实测:
- CLI端实测:
php -r "var_dump(@exec('id'));" - 组合测试更关键:
file_put_contents('/tmp/test.php', ''); include '/tmp/test.php';——若还能触发命令,说明防护链已断
开发层必须补上的防线
配置只是兜底,业务逻辑才是第一道墙。
- 所有
include/require语句禁用变量拼接,改用白名单数组映射:$whitelist = ['header' => '/var/www/html/inc/header.php']; include $whitelist[$_GET['page']] ?? die('Invalid'); - 用户传入的文件名必须过
basename(),再加正则校验:if (!preg_match('/^[a-zA-Z0-9_]+\.php$/', $file)) die(); - 涉及路径拼接时,用
realpath()比对是否仍在open_basedir范围内,超出即拒绝
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











