如果你是一名后端工程师、运维人员,或者只是某个网站的负责人,请立刻放下手头的事,花三分钟检查一下你的PHP版本。
2026年10月,安全研究团队公开披露了两个被统称为“PHP2Shell”的高危漏洞——CVE-2026-109618与CVE-2026-109619。这两个编号相邻的漏洞,一个存在于PHP核心的会话反序列化流程中,另一个则藏在文件上传的临时目录处理逻辑里。单独利用任何一个都可能导致远程代码执行,而组合利用时,攻击者甚至不需要任何有效凭据,就能在目标服务器上直接弹出一个shell。
这不是演习。截至本文发稿时,互联网上已经有公开的PoC代码在流传,扫描器正在批量寻找未打补丁的PHP-FPM服务。而更让人不安的是,很多团队至今仍以为“PHP 8.x已经很安全了”,对版本更新漫不经心。
**一、PHP2Shell到底是什么?为什么它比普通漏洞更危险**
先看两个漏洞的本质。
CVE-2026-109618影响PHP 8.1.x至8.4.x的会话序列化处理器。当应用使用`session.serialize_handler=php`且开启了`session.upload_progress`时,攻击者可以构造恶意的上传进度标识,诱导PHP在反序列化会话数据时执行任意对象的`__wakeup()`和`__destruct()`方法。如果代码库中存在一个可利用的POP链——比如常见的Monolog、Guzzle或Laravel组件中的魔术方法——攻击者就能实现远程代码执行。
CVE-2026-109619则更隐蔽。它出在`move_uploaded_file()`的临时文件竞争条件上。在特定配置下,PHP处理multipart/form-data请求时,临时文件名可被预测,攻击者通过并发请求可以在文件被移动前替换其内容,进而绕过上传白名单,将恶意PHP脚本写入Web目录。两个漏洞组合使用时,攻击者可以先通过109618获取一个低权限的会话写入能力,再利用109619完成文件落地,最终实现从“游客”到“服务器控制权”的完整攻击链。
之所以被命名为“PHP2Shell”,是因为从漏洞触发到getshell的路径极短,且不需要依赖任何第三方应用层漏洞。PHP本身就成了攻击面。
**二、谁在风险区?别以为用了框架就安全**
很多人有一个错觉:我用的是Laravel、Symfony、ThinkPHP,框架会帮我兜底。但这两个漏洞都出在PHP解释器层面,框架再新也挡不住。只要你的PHP版本落在受影响区间,且满足以下任一条件,就处于高危状态:
– 开启了`session.upload_progress.enabled`(默认开启);
– 使用了`php`作为会话序列化处理器(默认配置);
– 应用存在任何文件上传功能,且上传目录可被Web访问;
– 运行在PHP-FPM模式下且未做严格的`open_basedir`隔离。
尤其值得注意的是,很多共享主机和云函数环境默认就满足上述条件。你以为的“默认安全”,其实是“默认裸奔”。
**三、十分钟自查:三条命令定位风险**
不要等安全团队排期。现在就可以做以下检查。
第一步,确认PHP版本。在终端执行`php -v`,或在Web目录放一个临时`phpinfo()`文件查看。如果版本号在8.1.0至8.4.3之间(具体受影响小版本以官方公告为准),继续往下看。
第二步,检查会话配置。执行`php -i | grep session.serialize_handler`,若输出为`php`,则109618的利用前提成立。再执行`php -i | grep session.upload_progress.enabled`,若为`On`,风险等级上调。
第三步,检查上传目录权限。确认`upload_tmp_dir`是否与Web根目录存在任何软链接或路径重叠,以及`move_uploaded_file`的目标目录是否允许执行PHP。可以用`grep -r “move_uploaded_file” /var/www`快速定位业务代码中的上传逻辑。
如果你没有服务器权限,只是网站管理员,请直接联系托管服务商,询问“PHP是否已修复CVE-2026-109618和CVE-2026-109619”。不要接受“我们已做安全加固”这种模糊回答,要具体到补丁版本号。
**四、修补方案:升级是唯一正解,缓解措施只是止血**
官方已在PHP 8.4.4、8.3.14、8.2.20和8.1.31中修复了这两个漏洞。升级命令因环境而异:Debian/Ubuntu系用`apt update && apt upgrade php8.x-fpm`,RHEL系用`dnf update php-fpm`,Docker环境请将基础镜像标签更新至上述版本并重新构建。升级后务必重启PHP-FPM和Web服务器,否则旧进程仍在内存中运行漏洞代码。
如果暂时无法升级——比如老旧业务绑定在特定PHP版本上——可以采取以下临时缓解措施,但请记住这只是止血,不是治愈:
关闭`session.upload_progress.enabled`,将`session.serialize_handler`改为`php_serialize`(注意:此变更可能导致现有会话数据不兼容,需提前测试);在上传目录禁用PHP解析(Nginx中添加`location ~ \.php$ { deny all; }`);部署WAF规则拦截包含`PHP_SESSION_UPLOAD_PROGRESS`头的异常请求。这些措施能挡住公开PoC,但挡不住定向攻击者的变种利用。
**五、更深层的教训:PHP生态的“版本惰性”正在变成系统性风险**
PHP2Shell不是孤例。过去三年里,PHP核心层的高危漏洞披露频率在上升,而大量生产环境仍停留在8.0甚至7.4。原因很现实:升级PHP版本意味着重新测试整个应用,意味着可能踩到废弃函数和扩展兼容性的坑。于是团队选择“再等等”,等到漏洞上了热搜才连夜修补。
但攻击者不会等你。从漏洞公开到大规模扫描,窗口期已经缩短到以小时计。这次PHP2Shell的两个CVE编号相邻、利用链互补,明显是研究团队系统性审计的成果。可以预见,未来针对PHP核心组件的组合漏洞只会更多。
真正的安全不是“出了事再补”,而是把版本管理纳入日常运维节奏。建议所有PHP项目建立版本生命周期台账:记录当前版本、官方支持截止日、下一次计划升级窗口。对于无法及时升级的系统,至少要做到配置层的最小化暴露——关掉不用的功能,收紧文件权限,隔离上传目录。这些动作不花钱,但能救命。
最后说一句扎心的话:如果你的服务器在2026年10月还没打上这两个补丁,那它大概率也漏着过去两年里的其他十几个高危漏洞。PHP2Shell只是最新的一记警钟,不是最后一记。
**评价引导:你的PHP版本现在是多少?升级过程中踩过哪些坑?欢迎在评论区留下你的版本号和遇到的兼容性问题,我会挑选典型场景做一期升级避坑实录。如果这篇文章帮你发现了风险,请转发给那个还在用PHP 7.4的同事——他可能正需要这个提醒。**



