PHP爆大漏洞,两个9.2分漏洞,还没补丁,已复现其一"

admin 2026-10-24 09:50:57 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

PHP 爆大漏洞,两个 9.2 分漏洞,还没补丁,已复现其一

原创

网络安全透视镜
网络安全透视镜

网络安全透视镜

2026年10月21日 13:44
江苏

去阅读

QUOTE

PHP 官方提前一天发布公告,两个严重漏洞将于 10 月 21 日 14:00 UTC 修复。截至目前, 受影响版本区间与具体成因均未公布 。

2026 年 10 月 20 日,PHP 安全团队发布事前公告,宣布将于 10 月 21 日 14:00 UTC 发布安全版本,修复 两个严重漏洞 。官方对两者的定级相同:PHP 核心远程代码执行,CVSS v4.0 评分 9.2 。

官方公告只写到「两个 critical 漏洞、同一评分、同一发版时间」。受影响版本区间、配置要求、所在函数、CWE 类别,均要等发版时才会公布。

01

OVERVIEW

漏洞简述

1.1 两个编号的漏洞差异

维度 CVE-2026-109618 CVE-2026-109619
官方确认 是 是
官方定级 核心 RCE,CVSS v4.0 9.2 核心 RCE,CVSS v4.0 9.2
受影响版本 未公布 未公布
成因与触发条件 未公布 未公布
第三方复现声明 watchTowr 称已复现,细节未公开 无公开声明
公开可用 PoC 无 无
在野利用 无确认 无确认

1.2 当前可验证的攻击面

公开情报把两者的攻击面指向 PHP 会话上传进度处理路径,即 ext/session/session.c 中的 php\_session\_rfc1867\_callback() 。该功能自 PHP 5.4 引入, session.upload\_progress.enabled 出厂默认 On 。

它是目前 唯一能在本地完整验证、且与多家厂商描述不冲突 的入口。

源码层面存在两个结构上值得怀疑的位置。

长度与缓冲区解耦

value\_len 取自 \data->newlength,指向调用方栈上变量,可被前序回调改写;而 \data->value 指向的缓冲区由 multipart 读取器分配。两者若不保持一致,随后的 ZVAL\_STRINGL 与 smart\_str\_appendl 就是越界写。

生命周期与引用计数

一次请求内 php\_session\_initialize() 会被多次调用,每次进度更新触发一次,而 progress->data、progress->current\_file、progress->sid 都是跨调用存活的裸指针或内联 zval。多次 track\_init 与 zend\_hash\_update 之后,只要有一处引用计数算错,就会出现释放后使用。

02

IMPACT

影响范围

2.1 补丁覆盖边界

分支 状态 官方修复
8.5 活跃支持 有
8.4 活跃支持 有
8.3 安全维护 有
8.2 安全维护,2026-12-31 结束 有,剩两个多月
8.1 及更早 已 EOL 无
5.x / 7.x 已 EOL 无

PHP 5.x、7.x、8.0、8.1 的资产从补丁发布那一刻起进入无官方修复状态。

2.2 部署形态

漏洞位于解释器内部,受害面不是使用了某个特定框架的站点,而是 所有由 PHP 处理请求的服务 。

共享主机与多租户面板,WordPress、Drupal、Joomla、MediaWiki、phpBB、WHMCS,Magento 与 Adobe Commerce、Shopware、WooCommerce,Laravel 与 Symfony 等框架应用,Docker 的 php:\-fpm 与 php:\-apache 基础镜像,厂商随产品捆绑的 PHP 运行时。

捆绑运行时这一类最容易漏掉 。它不出现在依赖清单里,也不出现在 SBOM 里,运维看到的是某个管理系统版本,看不到它内部跑着哪个 PHP。

2.3 容易漏掉的三类资产

容器镜像

FROM php:8.2-fpm 锁定的是 tag,tag 不会自动跟随安全版本更新。多数团队的镜像扫描只看操作系统包,不看 PHP 自身版本。

空壳站点

只做健康检查、只返回静态内容的 index.php,在资产表里通常被标为低价值。但只要它由 PHP 处理、接受 POST,就是一个可用的触发点。

反向代理后的老系统

前面是 nginx,后面是 PHP 5.6 的老业务。nginx 不是 PHP,补不了这个洞。

2.4 两个编号的差异

目前无法拆分。受影响的最低版本、是否影响某个特定 SAPI、是否依赖特定配置、是否与另一个编号连锁,全部未公布。任何给出精确区间的说法目前都没有官方依据。

03

PRECONDITIONS

利用条件与场景

3.1 四条共同条件

条件 默认值
PHP 版本落在受影响区间 视资产,未公布
HTTP 暴露(FPM / mod\_php / CGI) 视部署
session.upload\_progress.enabled = On On
请求能被 PHP 解析(任意 .php 入口) 视站点

第 3 条是影响面覆盖大量默认配置的原因。管理员不需要做错任何事,这项本来就是开的,官方 php.ini 里它处于注释状态,注释即默认值。

3.2 三个常见误判

误判一:网站没有上传功能

会话上传进度是 PHP 会话扩展的内置功能,不是业务代码。SAPI 解析 multipart 请求体时发现 PHP\_SESSION\_UPLOAD\_PROGRESS 字段,就会把进度写进会话存储,这个动作发生在脚本编译执行之前。触发与有没有上传接口无关。

误判二:需要登录才能访问后台

处理早于路由、早于鉴权、早于任何应用代码。攻击者不需要知道站点上有什么页面。

误判三:有 WAF 就安全

如果触发点在请求体解析,请求在进入 WAF 规则匹配之前已经被 PHP 处理过一轮。签名要等 PoC 公开才写得出来。

3.3 cleanup 变量的影响

session.upload\_progress.cleanup 默认 On,请求结束后删除进度数据。cleanup 为 On 时进度数据只在请求生命周期内存在,会话文件在请求结束后被清空为空壳,攻击窗口是请求处理期间,对内存破坏型利用够用,对持久化写入不够。cleanup 为 Off 时数据持久化在会话文件里,通常是运维为了做进度条手动改的,属于少数配置。这个变量决定攻击面能否变成持久化写入原语,但不决定两个编号是否成立。

3.4 典型场景

空壳站点  一个只返回 hello 的 index.php 就是一个可用的触发器。

共享主机  会话目录常常全局共享,站点之间只靠文件权限隔离。目录权限宽松时,影响会横向扩散。

容器  构建一次,跑三年。补丁发布后 pull 到的仍是旧层,除非显式改 tag 或重建镜像。

供应链  WHMCS、部分 ERP、国产 CMS、网络设备管理面自带 PHP 运行时,在补丁窗口里几乎必然被漏掉。

04

REPRODUCTION

复现

4.1 复现级别定义

级别 定义 109618 109619
L0 入口与原语 请求能走到目标处理路径并产生可控副作用 已复现 已复现,属共享入口
L1 崩溃 触发内存破坏,进程崩溃 未复现 未复现
L2 RCE 控制流劫持,执行任意命令 未复现 未复现

L0 是入口层面的验证,不是归因。在官方拆分之前,这条路径无法单独归给某一个编号。

4.2 复现环境

项目 值
运行时 官方镜像 php:8.5.11-cli / php:8.5.11-apache
PHP 版本 PHP 8.5.11 (cli) NTS / Apache 2.4.69 mod\_php
会话处理器 files
关键配置 upload\_progress.enabled=On,cleanup=Off(观察用)

用容器而非本地编译,是因为官方镜像就是目标版本,构建方式可复现。本地编译 8.5.11 需要在 --disable-all 之上自行拼装扩展,反而引入变量。

4.3 PoC-1:最小报文

把入口压到最小的 multipart 请求,221 字节。

...http

POST /empty.php HTTP/1.1

Host: 127.0.0.1:18899

Cookie: PHPSESSID=poc0001

Content-Type: multipart/form-data; boundary=----poc

Content-Length: 221

------poc

Content-Disposition: form-data; name=\"PHP\_SESSION\_UPLOAD\_PROGRESS\"

MARKER\_109618\_109619

------poc

Content-Disposition: form-data; name=\"file\"; filename=\"a.txt\"

Content-Type: text/plain

X

------poc--

四个约束,少一个就不生效。

约束 原因
Content-Length 与字节数完全一致 解析器按长度读,差一个字节就截断
PHPSESSID 只含 [A-Za-z0-9,-] 文件 handler 在 mod\_files.c:168 校验
必须带一个文件 part 会话初始化发生在 FILE\_START,纯表单字段不会落盘
目标脚本存在即可 处理发生在脚本执行之前,不需要它调用 session\_start()

PITFALL

第二行这条容易踩坑。用带下划线的 SID(例如 probe\_0001)时,PHP 会 静默丢弃会话 ,请求照样返回 200,但会话目录里没有文件。排查时很容易误判成漏洞不存在。实际排查中我在这上面绕了一圈,最后用对照实验才定位到字符集校验。

4.4 实测输出

时序取证脚本在脚本第一行读取状态。

...php

<?php

header('Content-Type: text/plain');

$sid = $\_COOKIE['PHPSESSID'] ?? '(none)';

$file = rtrim(ini\get('session.save\_path'), '/') . '/sess\' . $sid;

echo \"session\_status\_at\_script\_start=\" . session\_status() . \"\
\";

echo \"session\_file\_exists\_before\_app\_code=\" . (is\_file($file) ? 'YES' : 'NO') . \"\
\";

echo \"session\_file\_size=\" . (is\_file($file) ? filesize($file) : 0) . \"\
\";

...bash

curl -sS --noproxy '\*' http://127.0.0.1:18899/precheck.php \

-H \"Cookie: PHPSESSID=demo0001\" \

-F \"PHP\_SESSION\_UPLOAD\_PROGRESS=DEMO\_MARKER\_01\" \

-F \"file=@lab/www/plain.txt\"

...output

sid=demo0001

session\_status\_at\_script\_start=1

session\_file\_exists\_before\_app\_code=YES

session\_file\_size=364

session\_status() 返回 1,即 PHP\_SESSION\_NONE,说明脚本执行时会话尚未开启;而会话文件此时已存在。落盘内容:

...session

upload\_progress\_DEMO\_MARKER\_01|a:5:{s:10:\"start\_time\";

i:1792558975;s:14:\"content\_length\";i:364;

s:15:\"bytes\_processed\";i:364;s:4:\"done\";b:1;

s:5:\"files\";a:1:{i:0;a:7:{s:10:\"field\_name\";s:4:\"file\";

s:4:\"name\";s:9:\"plain.txt\";s:8:\"tmp\_name\";

s:27:\"/tmp/php5m67ppuov16gcTMgxqP\";s:5:\"error\";i:0;}}}

4.5 完整验证矩阵

12 项用例,全部通过。

用例 结果
A 对照:普通 multipart,不带进度字段 200,不生成会话文件
B1 带 PHP\_SESSION\_UPLOAD\_PROGRESS 200,生成 sess\_
B2 写入是否早于应用代码 脚本首行观测到文件已存在
B3 脚本是否开启会话 session\_status()=1,未开启
B4 数据是否原样落盘 标记串完整出现
C 文件名是否由 Cookie 决定 sess\_ 按请求生成
D 字段长度是否受业务限制 1 MiB,落盘 1,048,929 字节
E 对照:SID 含下划线 不生成,字符集校验拦截
F 对照:SID 路径穿越 /tmp/poc\_traversal 未创建
G 字段值含 NUL 原样写入,未截断
H 无 Cookie,用 POST PHPSESSID 指定 SID 生成 sess\_
I 对照:PHPSESSID 排在文件字段之后 不生成,FILE\_START 时 SID 未定

D 项说明攻击者能控制多大的写入,唯一边界是 post\_max\_size 与 upload\_max\_filesize。对内存破坏型利用来说,可控写入长度直接影响堆布局的可操作性。E 与 F 项说明校验点位置:SID 字符集校验在 ext/session/mod\_files.c:168,不在 session.c,换用 Redis 或数据库 handler 时这一层是否等价取决于实现。H 与 I 项说明顺序约束:无 Cookie 时可以用 POST 字段指定 SID,但必须排在文件字段之前,顺序错误会得到静默不生效的假阴性。

4.6 三组对照实验

...output

cleanup = On(出厂默认)

HTTP=200

file=lab/www/sessions/sess\_cleanupdemo02 size=0

use\_strict\_mode = 1

session\_file\_exists\_before\_app\_code=NO

sess\_strictdemo03: ABSENT

upload\_progress.enabled = Off

HTTP=200

sess\_mitchk01=ABSENT

cleanup 为 On 时文件被创建但请求结束后被清空,默认配置下持久化写入不成立、请求期间存在攻击者可控数据成立。strict\_mode 打开后攻击者指定的 SID 未被使用,PHP 改用服务端生成的随机 SID,这把攻击者决定文件名降级为文件名不可预测,但不是银弹。upload\_progress 关闭后请求正常,会话文件不再生成,这条缓解实测有效。

4.7 畸形输入阴性结果

...probe

[A 超长 boundary (6000B)] -> 200 OK | 存活=YES

[B boundary 上限 5116] -> 200 OK | 存活=YES

[C 进度字段 1 MiB] -> 200 OK | 存活=YES

[D 截断的 part 头] -> 200 OK | 存活=YES

[E 100KB filename] -> 200 OK | 存活=YES

[F 嵌套数组 name[x][y]] -> 200 OK | 存活=YES

[G 5000 个字段] -> 200 OK | 存活=YES

[H 重复进度字段] -> 200 OK | 存活=YES

[I 无结束 boundary] -> 200 OK | 存活=YES

存活检查: OK

随手构造的畸形输入不足以打崩 8.5.11。这组数据同时给补丁后的回归测试留了基线。

4.8 第三方 PoC 的核验结果

社区流传的第三方武器化 PoC 包声称 618 是内层指针的释放后使用,给出 62,935 字节的请求。核验分三步。

第一步,静态阅读,不执行

...text

VALIDATION.md §7 :

\"No ASAN heap-use-after-free was observed\"

REPORT\_VALIDATION.md §7 :

\"NOT PROVEN: Live RCE achieved with the correct 8.2.34 lsphp delta\"

Runbook 要求用 ps、gdb -p、readelf 登录 origin 主机取地址,那是先拿到主机权限,不属于远程利用。

第二步,源码复核

它声称缓存的 zval 指针会悬空,但:

...c

Z\_TRY\_ADDREF(progress->data); // :3160

zend\_hash\_update(Z\_ARRVAL\_P(sess\_var), progress->key.s, &progress->data); // :3161

每次插入前先加引用,zend\_hash\_update 是 ZVAL\_COPY\_VALUE 所有权转移,因此调用方必须先加引用,否则 bucket 与 progress 共享同一份引用,析构一次就悬空。第二次 zend\_hash\_update 析构的是新反序列化出来的树,不是被缓存的那棵。

第三步,精确复刻实打

在 PHP 8.5.11 加 Apache 2.4.69 mod\_php 下:

运行 结果
run 1(新 SID) HTTP 200,无崩溃,command\_in\_body=False
run 2(新 SID) HTTP 200,无崩溃
run 3(新 SID) HTTP 200,无崩溃
同一 SID 连续 3 次 全部 200,无崩溃

会话文件证明请求确实走到了目标路径,bytes\_processed 记录为 62935,files 数组中第一个元素的 bytes\_processed 为 10370,与它自己报告的数字一致。请求是对的,效果是零。

结论是这份包不能证明 618,也不能证明 619,它更接近一份未完成的研究草稿。

4.9 复现结论与补丁后动作

L0 达成,两个编号共享的攻击面与写入原语,12 项验证全部通过,可稳定复现。L1 未达成,618 的第三方崩溃 PoC 三次全败,619 没有触发条件可试。L2 未达成,没有公开可用的利用链。

...bash

1) 官方 changelog

https://www.php.net/ChangeLog-8.php

2) 源码 diff

git clone --depth 200 https://github.com/php/php-src.git

cd php-src

git log --oneline --all --grep='CVE-2026-1096' -i

git diff php-8.5.11..php-8.5.12 -- ext/session main/rfc1867.c

3) 按 diff 性质定性

加上界检查 -> 越界写/读

加引用计数/延迟释放 -> 释放后使用

加类型或取值校验 -> 代码注入

第三步之后,才谈得上哪个编号对应哪段代码。

05

REMEDIATION

修复建议

5.1 今天:资产盘点

...bash

Linux

php -v; php-fpm -v

ls /usr/sbin/php-fpm\ /usr/local/bin/php\ 2>/dev/null

发行版包

dpkg -l | grep -E 'php[0-9.]+-(fpm|cli|cgi)' || rpm -qa | grep php

容器

docker ps --format '{{.Image}}' | grep -i php

docker images --format '{{.Repository}}:{{.Tag}}' | grep -iE 'php|wordpress|magento'

产出一张表:主机、PHP 版本、SAPI、是否公网可达、是否有业务、能否在两小时内升级。排序规则是公网、有业务、拿不到补丁,三条同时命中的今天就要给出处置决策。

5.2 补丁发布后 0 到 2 小时

以官方 release notes 为准,核对确切的受影响区间与修复版本号,不引用传闻版本。公网层优先升级。必须重启 PHP-FPM 或 Web 服务器,OPcache 与 worker 都是进程级的,只换文件不重启等于没修。验证实际生效的版本:

...bash

php -v

curl -s http://127.0.0.1/\_t.php | grep -E 'PHP Version|Server API'

5.3 补丁不可及时:缓解

官方事前公告称没有 workaround。以下是基于攻击面的缓解,属于降低可达性,不是修复漏洞。

...php.ini

session.upload\_progress.enabled = 0

session.use\_strict\_mode = 1

PHP-FPM 必须在 pool 配置里写:

...pool.d/www.conf

php\_admin\_flag[session.upload\_progress.enabled] = off

php\_admin\_flag[session.use\_strict\_mode] = on

systemctl reload php8.3-fpm # 换成你的版本

验证必须从 HTTP 侧做。

...bash

echo '<?php phpinfo();' > /var/www/html/\_t.php

curl -s http://127.0.0.1/\_t.php | grep -iE 'upload\_progress.enabled|use\_strict\_mode'

rm -f /var/www/html/\_t.php

副作用方面,session.upload\_progress 只服务 PHP 原生进度条,WordPress、Laravel、Magento、Shopware 都不用,关掉通常无感知。session.use\_strict\_mode 是官方推荐的整体加固项,但 Redis 或数据库自定义 handler 若未实现 strict mode 校验,这一项对它无效。不要改 session.serialize\_handler,会破坏现有会话;也不要改 session.upload\_progress.prefix,与本漏洞无关。

访问控制层可以再兜一层,仅在确认不使用进度条时:

...nginx

if ($request\_body ~\* \"PHP\_SESSION\_UPLOAD\_PROGRESS\") { return 403; }

只能当辅助手段。

5.4 补丁后 2 到 24 小时:按行为狩猎

diff 出来之前写不出精确特征,按行为找:

异常子进程  php-fpm、apache、php-cgi 派生 sh、bash、curl、wget、nc、python

命令行特征  /dev/tcp/、mkfifo、base64 -d、certutil

新增文件  Web 根目录新增单文件 PHP,文件名随机、内容混淆

异常外联  请求突增后 Web 主机立即向陌生地址发起出站连接

...bash

ps -eo ppid,pid,user,cmd --sort=ppid | grep -A2 -E 'php-fpm|apache2|httpd'

find /var/www /usr/share/nginx /home/\/public\_html -name '\.php' -mtime -1 -ls 2>/dev/null

确认命中则隔离主机、保留 Web 与 PHP 日志、排查 webshell 与新增计划任务。

5.5 长期:把运行时纳入资产管理

这次暴露的是资产管理问题。多数团队能列出用了哪些框架,列不出跑了哪些 PHP 运行时。把 PHP 版本纳入 CMDB 与 SBOM,与主机、镜像、厂商产品绑定。给 EOL 运行时设定强制退出时间。建立起安全版本发布后数小时内完成公网层升级的演练机制。

END

如果你觉得今天这篇有收获,欢迎 点赞、在看、转发 三连,我们下篇见。

2026精武杯wp(计算机取证)" 网络安全文章

2026精武杯wp(计算机取证)"

本文为2026精武杯计算机取证比赛Writeup,详细记录了计算机取证全过程,包括系统信息提取、开机密码破解、WSL大模型部署分析、加密盘破解、虚拟机取证、区块链钱包助记词恢复等操作,展示了从检材中提取关键证据的完整技术流程。
核弹漏洞|PHP核心RCE泄露波及全网" 网络安全文章

核弹漏洞|PHP核心RCE泄露波及全网"

PHP核心曝出两个CVSS9.2级RCE漏洞(CVE-2026-109618/109619),影响5.4.0起全版本,细节提前泄露且利用工具截图流出,官方确认漏洞真实存在。补丁定于今晚22:00发布,建议立即升级;8.1及更老版本无官方补丁需升级或下线。补丁落地前应监控PHP进程异常子进程,电商及暴露面大的站点优先处理。
评论:0   参与:  0