多站点共用thinkphp框架时,必须识别并锁定真实共享路径,在源头统一打补丁或升级至5.1.41+/6.x;验证需逐站测试poc、日志和批量探测;后续须强制路由、禁敏感路径、监控版本。

多站点共用 ThinkPHP 框架时,不能只在某个项目里修一修就完事。核心问题是:框架代码被多个站点共享(比如放在公共 vendor 目录、软链接引用或统一部署路径),一旦某处未更新,整个共享链路就存在风险。统一打补丁的关键,在于识别共享层级、锁定真实框架路径,并批量验证修复效果。
先确认框架是否真共享
很多团队以为“共用框架”,实际只是各项目都 composer install 了一遍,彼此独立。真正共享的情况有三种:
- 所有站点指向同一份 vendor/topthink/thinkphp 目录(通过 symlink 或 NFS 挂载)
- 使用全局 Composer Home + 自定义仓库镜像,强制所有项目安装相同版本的 thinkphp 包
- 运维打包镜像时,把框架源码固定写入基础镜像,多个站点容器共用底层 /var/www/framework
执行 find /var/www -name "thinkphp" -type d 2>/dev/null | xargs ls -ld 查看 inode 和路径,比对是否为同一物理目录。不是共享的,就按单项目方式逐个升级;是共享的,才进入下一步。
补丁必须作用于共享源目录
如果确认共享,补丁只能打在源头——即所有站点实际加载的那一个 thinkphp 目录。不要在各项目里改 config 或加中间件拦截,那只是绕过,不解决根本问题。
- CVE-2018-20062 的修复本质是收紧 think\App::invokeFunction() 的调用校验,需修改 library/think/App.php 中的
invokeFunction方法,增加对$function和$vars[0]的白名单限制(如仅允许htmlspecialchars、urlencode等安全函数) - 更稳妥的做法是升级到 ThinkPHP 5.1.41+ 或 6.x,官方已移除
invokefunction路由入口,且默认关闭非强制路由下的控制器名动态解析 - 若无法升级,可用 patch 文件统一覆盖:下载官方发布的 tp5-rce-fix-2018.patch,在共享目录执行
patch -p1
验证所有站点是否生效
补丁打完不等于漏洞消失。必须对每个站点做回归验证:
- 构造原始 PoC 请求:
GET /index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1,检查是否返回 404 或 500,而非输出 phpinfo() - 检查日志中是否仍有
invokefunction、call_user_func_array、system等关键词高频出现(尤其 access.log 和 error.log) - 用 Burp Suite 或 curl 批量探测所有站点域名的相同入口路径,避免漏掉子站或测试环境
后续加固不能只靠补丁
补丁防利用,但不防其他入口。共用框架环境下,一次配置失误可能全盘失守:
- 在共享的 config/app.php 中设置
'url_route_must' => true,强制开启路由规则,关闭默认的控制器名解析 - 所有站点的 .htaccess 或 Nginx 配置中,禁止访问
runtime/、vendor/、application/config/等敏感路径 - 建立统一的监控脚本,每日扫描各站点 vendor 目录下的 thinkphp 版本号(读取 composer.lock 或 thinkphp/library/think/Env.php),发现降级或回滚立即告警
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











