PHP 爆发近几年最严重的安全漏洞「php2shell」,9.2 分,能直接拿下服务器权限,WordPress 站点都要注意了!
前几天刚说了WordPress 最近漏洞为什么这么多?这不 PHP 也爆最严重的漏洞,官方已经预告了两个严重级别的远程代码执行漏洞,编号 CVE-2026-109618 和 CVE-2026-109619,官方给的 CVSS v4.0 评分是 9.2 分。
https://www.php.net/archive/2026.php#2026-10-20-1

这两个漏洞都是远程代码执行漏洞,这意味着攻击者可以在服务器上运行自己的代码,然后拿到服务器的控制权,并且这两个漏洞会影响 PHP 5、6、7 和 8 等几乎所有版本,安全圈管它叫 php2shell,这个名称来源于泄露截图中显示的一款漏洞利用工具。
补丁原定周四发,因为细节提前泄漏,官方把时间提前到了 UTC 时间 10 月 21 日 14 点,也就是北京时间今晚 10 点,而且明说了:要是细节继续扩散或者出现真实攻击,还会再提前。
PHP 撑着全球一大半的网站,WordPress、Drupal、Joomla、Magento 全在它上面跑,这次挨打的是地基,不是房子。
漏洞是怎么泄露出来的?
时间线很紧凑,一天之内走完了从泄漏到官宣:
| 时间(UTC) | 事件 |
|---|---|
| 10/20 15:20 | Hacker News 出现爆料帖,预告两个 PHP 严重漏洞(随后被删) |
| 10/20 16:39 | 安全研究员 Kevin Beaumont 公开点名 CVE-2026-109618 和 CVE-2026-109619 |
| 10/20 19:33 | PHP 官方在 php.announce 发预告,确认两个漏洞,官宣提前发布 |
| 10/21 14:00 | 计划发布补丁(北京时间 22:00),可能提前 |
已有安全公司跟进确认,称已经复现了 CVE-2026-109618。
好消息是:截至各家发稿,还没有厂商确认出现真实在野攻击。😄
坏消息是:补丁一发布,大概率 15 分钟内就会出现大规模自动化扫描。😮💨
这次漏洞影响哪些用户?
按目前公开的信息:
影响范围:据报是 PHP 5 及以后的所有版本。一些安全公司的 说法更直接,直接按「所有版本都受影响」来处理。PHP 官方要等今晚发版时才公布确切的受影响版本和修复版本。
漏洞在哪一层:泄漏出来的信息指向 PHP 处理文件上传的那段逻辑,也就是 multipart/form-data 请求,再加上 session 上传进度(session.upload_progress)那个特性。具体等 PHP 今晚确认。
关键点:这段逻辑跑在 WordPress、Laravel 这些应用代码之前,所以你网站上有没有上传表单,跟安不安全没关系。
顺带说一个数字,你就知道这次的面有多广:根据安全公司 Mallory 统计 Shodan 的数据,10 月 20 日那天,对外暴露且 HTTP 头里报了 PHP 版本的主机大约 150 万台,其中 约 88.4 万台报的是 8.1 或更老的版本,占 59%。
也就是说,一大半暴露在公网上的 PHP 主机,属于"可能受影响、又拿不到官方补丁"的那一批。
WordPress 站长该关心什么?
PHP 官方目前只维护 8.2、8.3、8.4、8.5 这四个分支,也就是说,PHP 8.1 及更早的版本,拿不到官方补丁。
而 WordPress 站点的现实是,一大把还跑在 7.4、8.0、8.1 上,这批站点今晚之后就处在「漏洞公开、没有补丁」的状态里。
最好的解决方案是:让服务商给你 backport 补丁,或者赶紧迁到已经修复的 PHP 版本,说白了,这次是逼着大家升级 PHP 了。
补丁出来之前,现在能做什么?
今晚 10 点之前,你手上能用的只有这两招,根据多位安全研究者的说法,这只是降低风险的权宜之计,不是修复。PHP 核心开发者 Gina Peter Banyard 的原话是,唯一的缓解措施就是打补丁升级。
第一招:关掉 session 上传进度
在 php.ini 里加:
session.upload_progress.enabled = Off
如果你用 PHP-FPM(nginx / Apache 后面跑 PHP 基本都是),必须在每个 pool 配置里用 php_admin_flag 锁死,比如在 /etc/php/8.3/fpm/pool.d/www.conf:
php_admin_flag[session.upload_progress.enabled] = off
为什么非得写进 pool?这是实测出来的坑:只写进 php.ini 或 conf.d,站点根目录下一个 .user.ini 就能把它改回去。用了 php_admin_flag,.user.ini 就改不动了。
然后重启对应的 PHP-FPM,比如 sudo systemctl restart php8.3-fpm。
这个修改是有副作用,但是很小:靠这个特性做的上传进度条会失效。
共享主机改不了 php.ini 怎么办:在站点 index.php 所在目录放一个 .user.ini,内容写:
session.upload_progress.enabled = Off
PHP 默认每 5 分钟重新读一次,所以可能要等几分钟生效。如果 PHP 是以 Apache 模块方式跑的,.user.ini 会被忽略,改用 .htaccess:
php_flag session.upload_progress.enabled off
注意:Apache + PHP-FPM 的组合不认这行,会直接 500,出现 500 就删掉。
第二招:在 Web 服务器层把所有 multipart 请求挡掉
这招更硬。注意要挡所有 HTTP 方法,不能只挡 POST,因为 PHP 8.4 加了 request_parse_body(),其他方法也能解析 multipart。
nginx,在 http 段加一个 map(Debian/Ubuntu 可以新建 /etc/nginx/conf.d/ 下的文件):
map $http_content_type $block_multipart {
default 0;
"~*multipart" 1;
}
然后在每一个把请求转给 PHP 的 server 块顶部加:
if ($block_multipart) {
return 403;
}
想更彻底就用 return 444;,直接断连接不给响应。改完 sudo nginx -t 然后 reload。
Apache 2.4,放在 .htaccess 里 WordPress 规则上面,或者写进虚拟主机配置:
<If "req('Content-Type') =~ /multipart/i">
Require all denied
</If>
千万别把 req('Content-Type') 换成 %{CONTENT_TYPE},后者在 Apache 表达式里是响应的类型,换过去等于没挡。
LiteSpeed(.htaccess,放在 # BEGIN WordPress 之外):
RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart [NC]
RewriteRule ^ - [F]
这个副作用就很大,挡了 multipart,文件上传就全废了,WordPress 媒体库上传、带附件的联系表单都会失效。Contact Form 7 就算表单里没有文件字段,提交也是走 multipart,所以也会受影响。普通页面、登录、JSON 接口、普通表单不受影响。
打完补丁记得把这层挡拆掉。
下面这些事情,别白忙,没用!
WordPress 安全插件对此没用:包括开了 Extended Protection 的 Wordfence。它靠 auto_prepend_file 加载,等它跑起来的时候,PHP 早就把请求体解析完了。
file_uploads = Off 没用:PHP 照样解析 multipart 请求体,只是不保存文件。
disable_functions 禁掉 system 之类的没用:漏洞在解析阶段。
上传大小限制没用:没有所谓的"安全阈值",post_max_size = 0 反而是无限制。
Laravel 维护模式、应用层中间件、登录校验,全都没用:都跑在 PHP 解析之后。
WAF 只在一种情况下有用:你的服务器不能被直接访问。攻击者直接拿 IP 打过来,Cloudflare 之类的就绕过去了,所以 Web 服务器层那道拦截必须自己加。
Cloudflare 昨天发了紧急 WAF 规则更新(规则名 Generic Rules - Anomalous Execution),没点名 CVE,时间点很像是冲这个来的,但官方没确认。
PHP 官方补丁出来之后怎么做?
今晚 10 点盯住 php.net 和 php.announce,先看官方公告里各分支的修复版本号,然后按这个顺序处理:
- 先升对外网暴露的机器。
- 注意版本号陷阱:Debian / Ubuntu 是 backport 安全修复,版本号可能看着没变。更新前先
sudo apt update,再apt-cache policy php8.3-fpm看候选版本;更新后用zcat /usr/share/doc/php8.3-fpm/changelog.Debian.gz | head -20确认里面提到了这两个 CVE。 - 先查有没有被 hold:
apt-mark showhold,被 hold 的包更新会静默失败,不报错也不提示。 - 重启 PHP-FPM 每个分支,还有那些长驻的 PHP 进程:队列 worker、Horizon、调度器、Octane。它们不重启就一直跑着旧二进制。
- Docker 要重新拉基础镜像 + rebuild + 重新部署,现有镜像不会自己变。
- 找出还在跑旧 PHP 的进程:
ls -l /proc/*/exe 2>/dev/null | grep -i 'php.*deleted',列出来逐个重启。 - 共享主机:催服务商确认装的是修复版本。还停在 8.1 及以下的站点,要么一直保留上面两道缓解,要么趁这次迁走。
一个提醒:如果你的 PHP 落后很多(比如还在 8.3.15,仓库里已经是 8.3.35),这次安全更新会一次带来二十来个版本的其他改动,更新完留点时间把站点点一遍。
打完补丁别急着收工,回头查一遍,把时间往回推到 10 月 20 日 15:00(UTC)左右,也就是第一个爆料帖出现之前,从那之后开始查:
1. Web 服务器和 PHP 日志里有没有异常的 multipart 请求,有没有 PHP-FPM worker 崩溃。
2. Web 根目录、上传目录、插件目录、mu-plugins 有没有新增或改动过的文件:
find /var/www -type f -newermt '2026-10-20 15:00 UTC'
3. 有没有多出来的 .user.ini,auto_prepend_file 有没有被改。
4. cron、systemd、Supervisor 里有没有新条目,有没有新 SSH key。
5. PHP 用户有没有异常进程或外连。
6. 后台有没有多出来的管理员账号。
另外建议装个进程监控,盯住 PHP 工作进程派生子进程这件事。正常的 php-fpm、apache2 绝不应该去拉 sh、bash、python、curl、wget。Florian Roth 那个 process-watcher 是免费的,开 observe 模式先跑着就行:
https://github.com/Neo23x0/process-watcher
真查到东西了:先断网隔离,保住 Web 和 PHP 日志,然后重建服务器,把 PHP 用户能读到的所有密钥全轮换一遍,包括 .env、数据库密码、API key。
多说两句
这次跟以往最大的不同是:锅不在 WordPress,也不在插件,在 PHP 自己。
也就是说,管好插件目录没用,装 WordPress 安全插件没用,改主题代码更没用。能做的只有升级 PHP,以及在升级前先把门堵上。
说实在的,这也算一次硬提醒:还停在 PHP 8.1 或者 7.x 的站点,今天是拿不到官方补丁的。趁着这次,把 PHP 升到 8.3 或 8.4 吧。
