线上环境必须执行 composer install --no-dev --optimize-autoloader,否则 rce 必然发生;禁用 input() 直接参与危险函数调用,严格白名单校验动态执行,全面排查 vendor/ 中低星、久未更新的第三方包。

线上环境只要没加 --no-dev,RCE 就不是“会不会发生”,而是“什么时候发生”。
composer install 必须带 --no-dev 和 --optimize-autoloader
很多线上服务器跑着 phpunit、symfony/var-dumper 甚至 laravel/framework ——这些包本身没漏洞,但一旦和 ThinkPHP 的路由解析、模板渲染、日志写入等环节组合,就可能成为 RCE 链的跳板。
- 执行命令必须是
composer install --no-dev --optimize-autoloader,缺一不可 -
--no-dev防止开发依赖混入线上;--optimize-autoloader不仅提速,还让自动加载器不响应未声明类的反射调用 - 上线前快速验证:
ls vendor/ | grep -E '^(phpunit|symfony|laravel|mockery)',输出为空才安全 - CI/CD 流水线里加检查:
composer show --dev | wc -l,结果非 0 就中断发布
input() 函数不能直接进 call_user_func / eval / system
ThinkPHP 的 input() 默认允许点号语法(如 input('filter.method')),而老版本中它能穿透到对象方法调用。攻击者传 filter=system&data=id,配合某些模板驱动或日志逻辑,就能触发任意函数执行。
- 永远不要写
call_user_func(input('callback'))或eval(input('code')) - 如需动态调用,硬编码白名单:
$allowed = ['md5', 'urlencode', 'strtoupper']; if (!in_array($func, $allowed)) { throw new Exception('Invalid function'); } - ThinkPHP 6.0+ 默认禁用点语法,但迁移项目要注意
app.app_multi_module和app.use_route配置会影响参数解析路径,别以为升级了就万事大吉
全局搜 eval、assert、call_user_func,尤其盯 vendor/ 非官方扩展
不少社区扩展包(比如“万能导出”“动态表单生成”类)为了省事,在核心逻辑里直接用 eval($code) 或 call_user_func(input('xxx'))。这类代码只要参数可控,RCE 就是零点击、无版本限制。
- 本地执行:
grep -r "eval\|assert\|call_user_func\|call_user_func_array" app/ extend/ --include="*.php" - 重点检查
vendor/下 star 数低、最近更新超 1 年、作者不活跃的第三方包 - 替换方案不是正则过滤函数名(
system可被sy\stem绕过),而是严格白名单 +array_key_exists()校验
最危险的不是你写了 eval,而是你忘了删掉别人写的 eval ——尤其是那个三年前从 GitHub 拷过来、只改了两行、再没人碰过的导出组件。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











