disable_functions对thinkphp几乎无效,因其不依赖exec/system等函数运行,攻击者可通过模板渲染(如{:system('id')})、反序列化、路由解析等绕过;真正风险在于参数可控性、runtime目录权限过大及模板引擎滥用。

ThinkPHP 本身不依赖 exec、system 等函数运行,禁用它们不会拦住真实攻击路径——真正危险的是参数可控性,而不是函数是否存在。
为什么 disable_functions 对 ThinkPHP 几乎无效
攻击者根本不需要调用 exec 就能执行任意代码:模板引擎里写 {:system('id')}、反序列化触发 __destruct、路由解析时动态加载类,都能绕过 disable_functions。PHP 的 eval() 和 assert()(PHP 7.2+ 默认启用)更不受该配置限制。
-
disable_functions只拦截 PHP 内置函数调用,对模板渲染、动态类加载、反射调用完全无感 - ThinkPHP 5.1+ 默认开启模板编译缓存,若攻击者能写入
runtime/view/,可直接落地恶意 PHP 文件 - 禁用
file_put_contents会导致日志写入失败、缓存无法生成,反而暴露错误路径和物理结构
ThinkPHP 模板层才是高危入口,不是 system()
ThinkPHP 的 think\template\driver\File 允许在模板中用 {:function()} 执行任意 PHP 表达式。一旦用户输入未过滤就进模板(比如富文本字段、页面标题),eval 就在后台静默触发。
- 危险写法示例:
{:shell_exec('ls -la')}或{:call_user_func('phpinfo')} - ThinkPHP 6.x 默认关闭
tpl_deny_func,需手动在config/template.php中显式添加:'tpl_deny_func' => ['exec','shell_exec','system','passthru','popen','proc_open'] - 更稳妥做法是禁用函数调用语法:把
'tpl_begin' => '{'改成'tpl_begin' => '{@',并确保所有变量输出都经htmlspecialchars()过滤
Runtime 目录权限比禁用函数更重要
runtime/ 是日志、缓存、模板编译的落盘位置。如果 Web 进程对该目录有写+执行权限,攻击者上传一句话木马后,只需触发一次模板编译,就能让恶意代码变成可访问的 PHP 文件。
- 典型错误:
chmod -R 777 runtime/—— 等于给攻击者配了把万能钥匙 - 正确权限(Linux):
chown -R www-data:www-data runtime/ && chmod -R 755 runtime/ && find runtime/ -type f -exec chmod 644 {} \; - Nginx 必须额外加规则禁止直接访问:
location ~ ^/runtime/.*\.php$ { return 403; },否则即使权限收紧,仍可能被绕过
真正要限制的不是“能不能调用 system”,而是“谁控制了调用它的上下文”。模板变量是否过滤、runtime 是否可写、上传目录是否禁 PHP 解析——这些点串起来,才构成实际防线。单靠禁函数,只是在补漏,不是筑墙。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











