首页 > PHP教程,php安装,php文章 > php2shell 漏洞:PHP 两个 9.2 分 RCE 应急加固指南

php2shell 漏洞:PHP 两个 9.2 分 RCE 应急加固指南

php2shell:PHP 爆出两个 9.2 分 RCE,附全版本应急加固工具包

2026-10-22 · 安全运维 · 阅读约 6 分钟

一句话结论:PHP 官方于 2026-10-21 紧急发布 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35,修复两个未授权远程代码执行漏洞。所有 PHP 5 以来的版本都受影响。临时配置只能降低暴露面,不能替代升级。(应急加固工具包见文末)

一、这是什么漏洞

这两个漏洞被社区合称为 php2shell,是 PHP 内核层面的问题,不是某个 CMS 或插件的问题:

编号名称CVSS v4.0原理
CVE-2026-109618RCE via OOM corruption9.2内存耗尽时 PHP 被打断,请求数据只初始化了一半,清理流程把无效数据当成了有效数据
CVE-2026-109619RCE via stale global state9.2请求的内部状态在其内存被释放后仍然存活,被同一个 worker 处理的下一个请求拿来用(UAF)

三个让人头大的特点:

  • 默认配置就能打。session.upload_progress.enabled 自 PHP 5.4 起默认开启,绝大多数人从来没关注过它。

  • 在业务代码执行之前就完成了利用,应用层的 WAF 和代码审计基本看不见。mod_php 风险最高,一个未授权请求即可触发。

  • 不需要登录、不需要特定接口,成千上万次请求里成一次就能拿到 shell,适合自动化批量扫描。

二、影响范围

官方表述是:PHP 5 以来的每一个版本都受影响。只有下面四个分支拿到了修复版本:

分支受影响区间修复版本状态
8.5.x8.5.0 ~ 8.5.118.5.12受支持
8.4.x8.4.0 ~ 8.4.268.4.27受支持
8.3.x8.3.0 ~ 8.3.358.3.36受支持
8.2.x8.2.0 ~ 8.2.348.2.35受支持(2026 年底 EOL)
8.1 / 8.0 / 7.4全系无正式版本仅有极简源码 backport
7.3 及更早(含 5.x)全系无无补丁、无 backport

受影响的 SAPI 包括 php-fpm、Apache mod_php、php-cgi、FrankenPHP、LiteSpeed。两个坑值得单独提醒:

  • EOL 分支的最后一个版本同样中招。比如 8.1.34、7.2.34、5.4.45,升到分支最后一版也没用。

  • 版本号只能当初筛。Debian、Ubuntu、RHEL、Alpine 等常在不改 PHP 版本号的前提下回迁补丁,php -v 显示旧版本但二进制可能已修好,需要核对包变更日志。

三、临时止血方案(升级前的过渡)

官方明确说明:以下措施只是降低特定攻击路径的暴露面,不是修复。真正解决问题只有一条路——升级。

1. php-fpm pool 级配置(最关键)

; 粘贴进 pool 文件的 [www] 段内部,不要存成 pool.d 下的新文件
; 必须用 php_admin_* —— 应用的 ini_set() 和 .user.ini 覆盖不了

php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M          ; 有上传业务改 32M
php_admin_value[upload_max_filesize] = 2M    ; 必须小于 post_max_size
php_admin_value[max_file_uploads] = 20
php_admin_value[max_input_vars] = 1000
php_admin_value[max_input_nesting_level] = 32
php_admin_flag[session.upload_progress.enabled] = off
php_admin_flag[display_errors] = off
pm.max_requests = 500

; 仅 PHP 8.5 才有这一行,其它分支写了会导致 php-fpm -t 失败
php_admin_flag[fatal_error_backtraces] = off

改完必须 php-fpm -t 校验,然后重启服务让所有 worker 重新加载配置(只 reload 主进程不够)。

2. Web 服务器与代理层

# nginx:请求体上界
client_max_body_size 8m;
client_header_buffer_size 4k;
large_client_header_buffers 4 8k;

# 不需要文件上传的站点,直接拒绝 multipart(最有效的一条)
map $http_content_type $block_multipart {
    default                             0;
    "~*^multipart/form-data(?:\s*;|$)"   1;
}
if ($block_multipart) { return 403; }

3. 三条反模式,别踩

  • 不要用 RLIMIT_AS / RLIMIT_DATA 代替 cgroup:那会自己制造"有漏洞的分配失败",反而打开 CVE-2026-109618。应该用 systemd MemoryMax 做兜底。

  • 不要把 request_terminate_timeout / max_execution_time 调小当防护:那是在制造攻击者可触发的执行超时,官方缓解建议里点名要求"修掉"这类超时。

  • WAF 别只匹配单行干净的 PHP_SESSION_UPLOAD_PROGRESS:PHP 的 multipart 解析器接受折叠头、无冒号行、闭合引号后的垃圾字符,精确匹配会漏;而且这个字段名是可以改的。

4. 排查是否已经被打

ps -eo pid,ppid,args --forest | grep php   # worker 下挂 sh/bash/nc/curl/python = 已失守
dmesg -T | grep -iE "segfault|general protection" | grep -i php
grep -c "PHP_SESSION_UPLOAD_PROGRESS" /var/log/nginx/access.log
grep -l "upload_progress" /var/lib/php/session/sess_* 2>/dev/null | head -20

四、php2shell 应急加固工具包

上面这些步骤散落在官方公告和各家分析里,落地时还要按自己的 PHP 分支做适配(哪些指令存在、哪些写了会让 FPM 起不来)。我把整套东西整理成了一个工具包:

包内文件(共 23 个)

php2shell-kit/
├── README.md                      三步走用法 + 踩坑清单
├── 00-版本矩阵.md                  分支区间 / 修复版本 / EOL / 覆盖性说明
├── 01-受影响版本全量清单.txt         538 个版本逐个列出,Ctrl+F 直接搜
├── 01-受影响版本全量清单.csv         可导入 Excel 做资产比对
├── 99-免责声明.txt
├── probe/
│   └── php2shell-probe.php        通用探针,PHP 5.0 ~ 8.5 全系可用
├── conf/
│   └── php-{8.5,8.4,8.3,8.2,8.1,8.0,7.4,7.3,7.2,7.1,7.0,5.6,5.5,5.4,5.3}.php-fpm.txt
└── scripts/
    ├── php2shell-audit.sh          只读自查:版本盘点 / 配置扫描 / IOC 排查
    └── apply-php-fpm-hardening.sh  备份 + 幂等写入 pool + 语法校验

几个值得单独说的设计:

  • 15 份分支配置,不是复制粘贴。按各分支的指令可用性做了差异:fatal_error_backtraces 只出现在 8.5 那份(其它分支写了 FPM 直接起不来);session.upload_progress.* 只在 5.4+ 出现;max_input_vars 在 5.3.9 之前的分支自动剔除。

  • 538 个版本的全量穷举清单。不想理解区间就 Ctrl+F 搜自己的版本号,比如 8.4.11 或 7.2.9,直接看判定和处置目标。PHP 补丁版本号是连续整数、不跳号,所以区间可以无损展开成完整列表。

  • 一个探针跑遍 5.0 ~ 8.5。不用短数组语法、不用 PHP 8 的 ini_parse_quantity,新函数全部做了 function_exists 保护。通过 HTTP 访问才能拿到 mod_php / php-fpm 的真实生效值——CLI 的 php -i 经常是另一份配置。探针还会轻扫 session 目录,找出被塞进 upload_progress 的对象序列化残留(O:),那是被尝试利用的直接证据。

  • 写入脚本会自动备份、幂等、校验,但故意不自动重启——重启是整个操作里唯一会影响线上业务的一步,应该由人来决定时机。

获取下载地址:

php2shell 应急加固工具包(CVE-2026-109618-109619).zip

(25 个文件,93 KB)

五、最后

处置顺序建议是:今晚做缓解 → 明天升版本 → 顺手排查入侵迹象。对于 7.3 及更早的分支,缓解只是买时间,隔离 + 排期迁移才是正解——一台互联网可达的 EOL 分支 PHP,长期看是守不住的,这类机器上通常还并存着 CVE-2019-11043 之类的旧洞。

免责声明:临时加固操作无法保证堵住漏洞,仅为升级到最新版本争取时间,请尽快升级到最新版。本文及工具包内容基于 PHP 官方公告与公开资料整理,不构成任何形式的安全保证;修改生产环境配置前请务必备份,并以 php.net 官方公告与实际环境验证结果为准。

参考:php.net 安全公告(2026-10-21)· php.net/eol.php · php.net/supported-versions.php · NVD CVE-2019-11043



六、常见问题(FAQ)

php2shell 是什么漏洞?

php2shell 是 2026 年 10 月 PHP 官方紧急修复的两个内核级未授权远程代码执行漏洞的合称:CVE-2026-109618(RCE via OOM corruption,内存耗尽时请求数据半初始化、清理流程误用无效数据)与 CVE-2026-109619(RCE via stale global state,请求内部状态在内存释放后仍被下一请求复用,属 UAF)。两者 CVSS v4.0 均为 9.2,默认配置即可利用,且在应用代码执行之前完成利用。

我的 PHP 版本受影响吗?怎么快速自查?

官方口径是 PHP 5 以来的每一个版本都受影响。按分支判断:8.5.0~8.5.11、8.4.0~8.4.26、8.3.0~8.3.35、8.2.0~8.2.34 全部受影响,需分别升级到 8.5.12、8.4.27、8.3.36、8.2.35;8.1、8.0、7.4 无正式修复版本,仅有极简源码 backport;7.3 及更早(含 5.x)既无补丁也无 backport。可用 php -r 'echo version_compare(PHP_VERSION, "8.4.27", "<") ? "受影响" : "已修复";' 做初筛,或直接查 538 个版本的全量清单。注意 Debian、Ubuntu、RHEL、Alpine 常在不改版本号的情况下回迁补丁,版本号只当初筛,结论以包变更日志为准。

不升级 PHP,只改配置能防住 php2shell 吗?

不能。PHP 官方明确说明,关闭 session.upload_progress.enabled、设置 memory_limit=-1、降低 post_max_size、关闭 fatal_error_backtraces 等措施只是降低特定攻击路径的暴露面,不是修复。底层分配失败仍可能到达有漏洞的代码路径。唯一完整解法是升级到 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35。

php-fpm 应该改哪些配置做临时止血?

在 pool 文件的 [www] 段内部写入:php_admin_value[memory_limit] = -1、php_admin_value[post_max_size] = 8M(有上传业务改 32M)、upload_max_filesize = 2M(必须小于 post_max_size)、max_file_uploads = 20、max_input_vars = 1000、max_input_nesting_level = 32、php_admin_flag[session.upload_progress.enabled] = off、display_errors = off、pm.max_requests = 500。PHP 8.5 可再加 fatal_error_backtraces = off,其它分支写了会导致 php-fpm -t 失败。必须用 php_admin_* 而非 php_value,否则会被应用 ini_set() 覆盖;改完要校验并重启所有 worker。

为什么不能用 RLIMIT_AS 或 RLIMIT_DATA 代替 cgroup?

因为 RLIMIT_AS / RLIMIT_DATA 会主动制造分配失败,而 CVE-2026-109618 的触发条件之一正是内存分配失败,用它顶替 cgroup 等于自己打开漏洞路径。可用性兜底应使用容器或 cgroup 限制(如 systemd MemoryMax),并配置只杀掉受影响 worker 的策略。

PHP 5.4、7.2 这类已 EOL 的版本怎么办?

EOL 分支拿不到任何官方补丁,且分支最后一个版本同样中招(如 8.1.34、7.2.34、5.4.45),升到分支末版无效。可行做法只有:短期用 php-fpm 配置加 Web 服务器层限制做缓解,并把服务挪到 WAF 或内网之后;中期排期迁移到受支持分支(建议 8.3 及以上)。PHP 7.2 还需额外注意 CVE-2019-11043 这类并存的历史漏洞。

怎么判断服务器是否已经被利用?

排查四类迹象:一是 ps -eo pid,ppid,args --forest 看 php-fpm worker 下是否挂出 sh、bash、nc、curl、python 等子进程;二是 dmesg 中是否出现 php 相关 segfault 或 general protection(利用失败常直接段错误);三是访问日志中 PHP_SESSION_UPLOAD_PROGRESS 字段与 5xx 突增;四是 session 目录中是否存在同时含 upload_progress 与序列化对象标记 O: 的残留文件。

php2shell 应急加固工具包里有什么?

一个通用探针 php2shell-probe.php(PHP 5.0~8.5 全系可用,通过 HTTP 输出真实生效 ini 值并轻扫 session 目录残留);15 个 PHP 分支各自的 php-fpm 配置 txt;538 个受影响版本的全量清单(txt 与 csv 两种格式);以及只读自查脚本与带备份、幂等、语法校验但不自动重启的写入脚本。

处置的先后顺序应该怎么安排?

建议三步:当晚先在 php-fpm 与 Web 服务器层做临时缓解并重启 worker;次日尽快升级到官方修复版本并复查生效值;同时排查入侵迹象。对 7.3 及更早分支,缓解只是买时间,隔离加迁移才是正解。

文章网址:https://www.phprm.com/php/php2shell.html

随意转载^^但请附上教程地址。

标签:php安全 CVE漏洞修复

相关文章

发表留言