PHP禁用危险函数,提升CMS站点安全性
CMS站点被入侵,很多时候不是因为程序本身有漏洞,而是PHP允许执行系统命令,攻击者上传一个WebShell就能直接控制服务器。
禁用exec、system、passthru这类危险函数,是成本最低、效果最直接的安全加固手段。
本文面向零基础用户,讲清楚为什么要禁、禁哪些、怎么禁,以及改完后如何验证不误伤站点正常功能。
先确认你的站点是否真的需要这些函数
PHP的disable_functions指令可以屏蔽指定函数,被屏蔽的函数调用时会直接报错或返回失败。
对大多数CMS(如WordPress、织梦、帝国、ZBlog)来说,日常运行不需要调用系统级命令函数,因此可以安全禁用。
判断原则:如果你的站点没有使用图像处理库的exec调用、没有自定义的Shell脚本触发、没有Composer在运行期执行外部命令,那么禁用以下函数通常不会影响前台访问。
需要提前检查三件事:
- 当前PHP版本(
php -v或宝塔面板软件商店查看) - 站点是否有插件或主题依赖
shell_exec、popen、proc_open - 是否方便回滚(改
php.ini前先备份)
找到正在生效的php.ini文件
很多新手改了php.ini却不生效,原因是改错了文件。
PHP可能同时存在多个配置文件,必须找到当前Web服务实际加载的那个。
命令行方式(SSH登录服务器后执行):
php -i | grep "Loaded Configuration File"
输出示例:
Loaded Configuration File => /www/server/php/74/etc/php.ini
这个路径就是你要修改的文件。
如果使用宝塔面板,也可以在“软件商店 → PHP 7.4 → 配置修改”中直接编辑,面板会自动定位到正确文件。
编辑php.ini禁用危险函数
打开php.ini,搜索disable_functions。
默认情况下这一行可能是空的,或者被注释掉了。
修改为:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
说明几个关键函数:
exec、shell_exec、system、passthru:直接执行系统命令,WebShell最常调用proc_open、popen:打开进程管道,可间接执行命令curl_exec:部分CMS的采集功能会用到,禁用前确认站点没有远程采集需求parse_ini_file、show_source:常用于读取敏感配置文件或源码
如果你使用的是宝塔面板,操作路径为:软件商店 → 已安装 → PHP版本 → 设置 → 禁用函数,在列表中添加上述函数并保存。
重载PHP并验证是否生效
修改php.ini后必须重载PHP服务,否则配置不会生效。
命令行方式:
systemctl reload php-fpm
# 或
service php-fpm reload
宝塔面板方式:软件商店 → PHP版本 → 重载配置。
验证方法有两种。
第一种,创建一个临时PHP文件:
访问后如果输出bool(false),说明函数已被禁用。
验证完记得删除该文件。
第二种,直接查看PHP信息:
php -i | grep disable_functions
输出中应包含你配置的函数列表。
改完后站点报403怎么办
禁用函数后出现403或500,通常是某个插件或主题仍在调用被禁函数。
排查顺序如下:
- 查看PHP错误日志(宝塔面板 → 网站 → 对应站点 → 日志),搜索
disable_functions或函数名 - 临时注释掉
disable_functions这一行,重载PHP,确认站点恢复 - 逐个恢复被禁函数,定位是哪一个导致的冲突
- 常见冲突函数是
curl_exec(采集类插件)和proc_open(某些备份插件)
建议:如果站点确实需要curl_exec,可以只保留exec、system、shell_exec、passthru这几个高危函数,不必追求一次禁全。
安全加固是逐步收紧的过程,不是一刀切。
容易被忽略的配套设置
只禁函数还不够,建议同时检查以下配置:
open_basedir:限制PHP只能访问指定目录,防止跨站读取allow_url_include = Off:禁止远程文件包含,避免RFI攻击expose_php = Off:隐藏PHP版本信息,减少被针对性扫描- 文件上传目录禁止执行PHP:在Nginx中添加
location ~* /uploads/.*\.php$ { deny all; }
这些设置配合disable_functions使用,才能真正把WebShell的利用链切断。
常见疑问
禁用后网站前台打开空白或报错,是不是禁错了?
先看错误日志,确认是哪个函数被调用。多数情况是缓存插件或图片处理库依赖exec,临时恢复该函数即可。
宝塔面板里禁用了,但phpinfo还是显示函数存在?
检查是否修改了正确的PHP版本。宝塔多版本共存时,站点可能使用的是另一个PHP版本,需要在对应版本的设置中操作。
禁用函数会影响网站速度吗?
不会。disable_functions只是在函数调用时拦截,不参与正常请求处理,对性能没有负面影响。
虚拟主机没有php.ini修改权限怎么办?
部分虚拟主机支持在网站根目录放置.user.ini文件,写入disable_functions = exec,system,但并非所有环境都支持,建议以主机商说明为准。
安全加固没有一步到位的方案,禁用危险函数是性价比最高的一环。
建议先在测试环境验证,确认CMS前后台、插件、计划任务都正常后,再同步到生产环境。
改完后保留一份原始php.ini备份,遇到403或500报错时能快速回滚,避免影响线上业务。