如何配置禁用所有危险的PHP函数 disable_functions最佳实践
disable_functions 配置:从语法细节到实战避坑指南
在PHP安全配置中,disable_functions 是一个关键防线,但配置不当,这道防线可能形同虚设。今天,我们就来深入聊聊其中的门道。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
disable_functions 为什么不能只填函数名列表
很多朋友以为,在 php.ini 里简单写上 disable_functions = exec,system,passthru 就万事大吉了。但问题恰恰出在这里:PHP解析这个配置项时,会把整个字符串当作一个函数名去匹配。这意味着,任何多余的标点、空格甚至换行,都可能导致解析失败,最终一个函数都没禁掉。
结果呢?你可能会在 phpinfo() 里看到 disable_functions 的值为空,或者只有列表里的第一个函数生效了。更危险的是,你以为已经禁用了 shell_exec,攻击者却依然能在线上调用它。
- 格式必须精确:必须使用无空格的英文逗号分隔。正确写法是
exec,system,passthru,而exec, system, passthru(逗号后有空格)就是错误的。 - 禁止换行:值中不能包含换行符,否则PHP会截断解析,后面的内容全部被忽略。
- 大小写敏感:函数名必须小写,写
EXEC是无效的。 - 不支持通配符:这个列表不支持正则或通配符匹配,每个函数名都必须老老实实写全。
哪些函数真正该禁、哪些其实没必要动
禁用函数是个平衡的艺术。禁得太多,可能会“误伤”正常业务,导致Composer、Lara vel的文件锁或WordPress的更新机制瘫痪;禁得太少,又等于给攻击者留了后门。核心原则其实很明确:只瞄准那些能直接执行系统命令或任意读写文件的高危函数,其他风险相对较低的,完全可以交给 open_basedir 和严格的系统权限来控制。
那么,哪些是真正高危、应该优先列入黑名单的呢?通常是WebShell利用链上的常客:
- 命令执行类:
exec、shell_exec、system、passthru,这是最直接的威胁。 - 进程控制类:
popen、proc_open。它们比exec更隐蔽,能绕过一些简单的检测。 - 常被忽略的:
pcntl_exec。这个函数容易被遗漏,但在某些环境下可以绕过部分disable_functions的检查。 - 文件与网络操作:
curl_exec、file_get_contents。它们本身无害,但一旦配合php://filter封装协议或SSRF漏洞,就能读取服务器上的敏感文件。
反过来,有些函数虽然名声在外,但实际没必要禁用,因为它们要么影响面太大,要么在新版本中风险已降低:
立即学习“PHP免费学习笔记(深入)”;
assert:在PHP 7.2及以上版本,动态代码执行功能已被默认禁用,且现代攻击更倾向于使用eval。create_function:这个函数在PHP 8.0中已被废弃,禁用它没有实际的安全意义。unserialize:危险的不是这个函数本身,而是反序列化不可信的数据。直接禁用会导致大量依赖它的业务功能崩溃,正确的做法是严格控制输入。
禁用后还要防绕过:proc_open 和 dl 的坑
以为禁了 exec 就高枕无忧了?攻击者的手段可不止这一种。他们可能会转而利用 proc_open 来启动新进程,或者在老版本PHP中,通过 dl 函数动态加载恶意扩展。
这不是危言耸听。像China Chopper、AntSword这类常见的WebShell,其攻击载荷默认就会优先尝试 proc_open,其次才是 exec。
- 务必加入proc_open:必须将
proc_open加入禁用列表。它比exec更隐蔽,返回的是资源句柄,在日志里不那么显眼。 - 关注dl函数:
dl在PHP 8.0+已被移除,但如果你还在使用7.x版本,务必将其禁用。可以通过php -m命令检查是否包含dl模块。 - 注意环境变量函数:
putenv和ini_set本身不能直接执行命令,但它们可以配合其他漏洞修改环境变量或PHP配置(例如绕过open_basedir限制)。从安全加固的角度,建议一并禁用。
验证是否真生效:别只信 phpinfo()
配置写好了,怎么验证?千万别只看 phpinfo() 的输出。它显示的 disable_functions 值只是从 php.ini 读取的配置项,如果中间被 php_admin_value 指令或容器配置覆盖了,phpinfo() 反映的可能就不是运行时的真实情况。
最可靠的方法,永远是直接测试。可以写一小段代码来尝试调用:
echo @exec('id') ?: 'exec disabled';
但这里也有坑:有些函数被禁用后会触发 E_WARNING 错误,而像 proc_open 这类函数,禁用后只是安静地返回 false,不报任何错误,很容易让人误以为它还能用。
- 双重验证:写一个最小化的测试脚本,对每个要禁用的函数,既用
function_exists('xxx')检查,也尝试用try...catch块去调用它,观察实际行为。 - 区分环境测试:务必在CLI(命令行)和FPM(FastCGI进程管理器)两种SAPI下分别测试。FPM的配置可能会在进程池(pool)中被覆盖(例如通过
php_admin_value[disable_functions])。 - 确认重启生效:修改配置后,记得重启PHP服务,并用
ps aux | grep php确认新的进程已经加载了最新配置,避免出现“改了文件却没生效”的尴尬。
最后要提醒的是,不同PHP版本对同一函数的禁用行为可能不一致。比如 pcntl_exec,在某些打了特定补丁的PHP 7.4版本里,仍然存在绕过可能。所以,千万别直接照抄网上的禁用列表,一定要根据你自己服务器上运行的PHP版本进行实测。安全配置,细节决定成败。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
mysql如何在Docker环境下实现数据持久化_挂载宿主机目录与环境变量设置
Docker部署MySQL数据持久化全攻略:避免数据丢失的挂载方法与配置要点 Docker中MySQL数据丢失的根本原因与持久化解决方案 直接执行 docker run mysql:8 0 命令启动MySQL容器时,所有数据库文件默认存储在容器内部的临时存储层。一旦容器被移除或重建,位于 var
MongoDB 事务为何会导致 CPU 占用过高_排查不合理查询引起的事务扫描量
事务CPU高主因是未索引查询、snapshot读关注、跨分片协调及聚合误用;应建索引、降级readConcern、单分片操作、禁用事务内聚合。 事务中未加索引的 find 或 update 会触发全集合扫描 MongoDB事务本身其实并不直接消耗大量CPU资源。问题往往出在事务内部:如果执行的查询缺
怎样将添加表外键约束同步至生产环境_DDL脚本生成与执行
外键约束生成DDL前必须确认引用表已存在,检查表、主键名、列名、类型一致性及权限,并注意MySQL与PostgreSQL在语法、锁机制和校验行为上的关键差异。 外键约束生成 DDL 前必须确认引用表已存在 在生产环境给表加外键,失败的原因十有八九很直接:那条alter table add c
如何处理Java日期存入Oracle变成00:00:00_java.sql.Date与java.sql.Timestamp的区别
应使用 ja va sql Timestamp 或 JDBC 4 2+ 的 LocalDateTime 存储带时间的值 在Ja va应用与Oracle数据库交互时,一个相当经典的“坑”就是时间数据的存储。很多开发者会发现,明明代码里传了一个包含时分秒的时间点,存进数据库再查出来,时间部分却莫名其妙地
如何配置物化视图查询重写_ENABLE QUERY REWRITE自动路由SQL至物化视图
物化视图查询重写:为什么你的配置没生效? 在数据库性能优化领域,物化视图的查询重写功能堪称一把利器。但不少朋友都遇到过这样的困惑:明明按照文档一步步配置了,为什么执行计划还是雷打不动地扫描基表?问题往往出在几个容易被忽略的细节上。今天,我们就来把这些关键点逐一拆解清楚。 物化视图需同时开启全局QUE
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

