最有效方式是在php.ini中用disable_functions禁用危险函数,重启Web服务器生效;必须禁用的高危函数包括exec、system、shell_exec、passthru、eval、assert等。

PHP怎么关闭危险函数
直接在 php.ini 中用 disable_functions 配置项禁用,这是最有效、最底层的控制方式。Web 服务器重启后才生效,不能通过 .htaccess 或运行时 ini_set() 修改。
哪些函数必须禁用
常见高危函数包括执行系统命令、读写任意文件、动态代码执行等类型。是否禁用需结合实际业务判断,但以下函数在绝大多数生产环境中应默认禁用:
-
exec、system、shell_exec、passthru—— 直接调用 shell,极易被构造命令注入 -
eval、assert(PHP create_function —— 动态执行字符串代码,绕过所有静态检查 -
file_get_contents、file_put_contents、unlink、copy—— 若参数可控,可能读取敏感文件(如/etc/passwd)或删除关键文件 -
curl_exec、curl_multi_exec—— 可发起 SSRF 请求,尤其当 URL 参数由用户输入拼接时 -
pcntl_exec、proc_open—— 启动新进程,权限失控风险高
disable_functions 配置写法与注意事项
disable_functions 是 PHP INI 指令,值为逗号分隔的函数名列表,**不加空格**,且区分大小写(如 Eval 不会生效,必须写 eval)。错误配置会导致 PHP 启动失败。
disable_functions = exec,system,shell_exec,passthru,eval,assert,file_get_contents,file_put_contents,unlink,copy,curl_exec,pcntl_exec,proc_open
注意:
立即学习“PHP免费学习笔记(深入)”;
- 禁用函数对所有 SAPI 生效(CLI、Apache、FPM),但 CLI 场景下有时需单独配(如某些运维脚本依赖
exec) - 禁用后调用会直接报
Warning: [function] has been disabled for security reasons,返回null或false,不会抛异常 - 部分函数有别名(如
mysql_connect已废弃,但若仍存在旧扩展,也建议禁用),需确认实际加载的扩展模块 - 禁用
file_get_contents可能影响 Composer 自动加载、框架资源读取,务必先测试
为什么不能只靠代码层过滤
业务代码里用 str_replace 过滤 "system" 字符串、或用正则拦截 cat /etc,这类做法完全无效。攻击者可轻松绕过:
- 大小写混淆:
syStEm - 变量拼接:
$a='syst' ; $b='em'; $a.$b -
编码绕过:
base64_decode('c3lzdGVt') - 反射调用:
call_user_func('system', 'id')
真正有效的防护必须落在 PHP 解析器层面——也就是 disable_functions。代码层过滤只适合做二次校验或日志审计,不能替代配置禁用。
线上环境改完 php.ini 后,务必用 php -m 和 php -i | grep disable 确认配置已加载,再重启 PHP-FPM 或 Apache。漏掉重启,等于没关。











