php2shell(CVE-2026-109618 / CVE-2026-109619)的概念验证(PoC)漏洞利用,演示在存在漏洞的 PHP 环境中实现远程代码执行。仅用于安全研究和教育目的。
严重安全公告(CVSS v4.0:9.2 - 严重): 2026 年 10 月 20 日,PHP 核心中两个预认证远程代码执行(RCE)漏洞的详细信息在协调披露之前泄露到网上。利用这些漏洞可直接从 Web 服务器执行任意命令。
php2shell 指两个影响 PHP 核心功能的严重漏洞(CVE-2026-109618 与 CVE-2026-109619)。主要演示的攻击向量是 PHP 核心会话上传进度机制中的堆释放后使用(UAF)漏洞,可导致任意代码执行(zend_call_function / system())。
PHP 的上传进度处理器(ext/session/session.c 中的 php_session_rfc1867_callback)将两个原始 zval * 桶指针(post_bytes_processed 和 current_file_bytes_processed)直接存储在活跃的 HashTable 结构中。
在请求处理过程中:
POST 请求在默认配置值(session.upload_progress.enabled = 1)下激活进度跟踪。zend_hash_update() 使用析构函数 zval_ptr_dtor 销毁先前的数据树,从而释放内存块。zend_fcall_info 和 zend_internal_function 结构。zend_call_function(),导致任意系统命令执行。php-src 构建上确认(包括 8.4.4 和 8.2.34 版本)。zval_ptr_dtor 与 zend_call_function 之间的符号偏移量(--syms)来适配不同发行版的二进制布局(例如 Debian Bookworm、Ubuntu Noble、Ubuntu Jammy)。下表汇总了受 CVE-2026-109618 和 CVE-2026-109619 影响的 PHP 版本,以及它们的支持与补丁状态:
| PHP 分支 | 状态 | 受影响版本 | 修复 / 安全版本 | 备注 |
|---|---|---|---|---|
| PHP 8.5 | 受支持(活跃) | < 8.5.12 | 8.5.12 | 已发布紧急安全版本 |
| PHP 8.4 | 受支持(活跃) | < 8.4.27 | 8.4.27 | 已发布紧急安全版本 |
| PHP 8.3 | 受支持(活跃) | < 8.3.36 | 8.3.36 | 已发布紧急安全版本 |
| PHP 8.2 | 受支持(仅安全修复) | < 8.2.35 | 8.2.35 | 已发布紧急安全版本 |
| PHP 8.1 | 生命周期结束(EOL) | 所有 8.1.x 版本 | 无官方补丁(EOL) | 设置 session.upload_progress.enabled = Off 或使用 ELS/发行版向后移植补丁 |
| PHP 8.0 | 生命周期结束(EOL) | 所有 8.0.x 版本 | 无官方补丁(EOL) | 官方支持已结束;必须采取配置缓解措施 |
| PHP 7.x | 生命周期结束(EOL) | 所有 7.0 - 7.4 版本 | 无官方补丁(EOL) | 核心 ext/session 逻辑存在漏洞;需紧急缓解或升级 |
| PHP 5.x | 生命周期结束(EOL) | 5.4.0+(启用 RFC1867 进度跟踪) | 无官方补丁(EOL) | 官方支持已结束;隔离主机或禁用上传进度 |
[!WARNING] PHP 8.1 及更早的生命周期结束(EOL)版本不会获得 PHP 基金会提供的官方安全补丁。对于这些环境,请立即应用
session.upload_progress.enabled = Off,或使用提供的 C 源码补丁从源码重新编译 PHP。
php2shell 的利用通常表现为由 PHP 工作进程(php-fpm、php-cgi、php-cgi.exe、httpd、apache2)直接派生的异常子进程。
监控并对以下 PHP 工作进程执行行为发出告警:
/bin/sh、/bin/bash、cmd.exe、powershell.exepython、perlcurl、wget、nc、certutil.exe/dev/tcp/、fsockopen、mkfifowhoami、id、uname -a、ipconfig对于未部署端点检测代理的 Linux Web 环境,可运行 Florian Roth 的免费工具 process-watcher(观察模式),以实时标记异常的子进程派生行为。
php.exe、php-cgi.exe)。/tmp、/var/tmp),查找投放的 webshell 或临时执行痕迹。针对 CVE-2026-109618 的全自动一键远程利用程序位于 poc_109618.py。该利用程序通过纯 HTTP 请求远程绕过 ASLR,实现可靠的任意命令执行。
攻击链由四个连续的 HTTP 阶段组成:
--huge-mb,默认 12MB)触发内存耗尽(OOM)条件,从而通过 Set-Cookie: PHPSESSID 触发未初始化内存泄漏,提取 Zend MM 2MB 对齐的 chunk 基址。Set-Cookie 泄漏 ZVAL_PTR_DTOR 函数指针,计算 libphp.so 的基址。zend_string 内伪造一个 HashTable 结构,其 pDestructor 直接指向 libphp.so 中的 zif_system。构造的引用覆盖 PS(http_session_vars)。当 PHP 释放会话数据时,zif_system 执行所提供的命令。[!NOTE] 命令直接嵌入在 167 字节的活跃
zend_string载体中(0x98 头部 + NUL 字节限制),因此内联命令字符串被限制为最大 14 字节(MAX_CMD = 14)。对于更长的命令,可通过短触发器进行链式调用,例如sh</tmp/c(8 字节)或sh</out/c。
默认漏洞利用配置针对 Apache prefork 下的 mod_php,具有以下设置:
display_errors = 1memory_limit = 8M(或足够低于 --huge-mb)max_input_vars = 1000session.use_cookies = 1,session.use_strict_mode = 0session.upload_progress.enabled = 1# Default command execution against target URL
python3 poc_109618.py -u http://127.0.0.1:8088/index.php
# Execute a custom command (max 14 bytes) and verify via local proof file
python3 poc_109618.py -u http://127.0.0.1:8088/index.php -c 'id>/out/p1' --proof-file out/p1
# Execute command writing to webroot and verify via HTTP GET fetch
python3 poc_109618.py -u http://127.0.0.1:8088/index.php -c 'id>p1.txt' --fetch /p1.txt
| 选项 | 描述 | 默认值 |
|---|---|---|
-u、--url | (必填) 目标 PHP 端点 URL | None |
-c、--cmd | 要执行的命令(最大 14 字节) | id>/out/p1 |
--proof-file | 用于在利用后检查的本地证明文件路径;'' 表示禁用 | out/p1 |
--fetch | 利用后用于 GET 的相对 HTTP 路径(例如写入 webroot 时) | "" |
--profile | 目标构建配置:bookworm(官方 php:8.4.26-apache)或 lab(Apache 2.4.68) | bookworm |
--zif-offset | libphp.so 中 zif_system 的偏移量(十六进制格式,例如 0x43a870) | 从偏移量文件加载 |
--dtor-offset | libphp.so 中 ZVAL_PTR_DTOR 的偏移量(十六进制格式,例如 0x613c50) | 从偏移量文件加载 |
--htdata-offset | 167 字节活动字符串载体的块相对偏移量 | 取决于配置(0x690d8 或 0x6e0d8) |
--offsets-file | 用于加载/存储推导出的 libphp 偏移量的路径 | out/offsets.env |
--docker-container | 用于在 localhost 上自动推导偏移量的 Docker 容器名称 | php2shell-target |
--no-auto-offsets | 禁用通过 Docker 辅助程序自动提取偏移量 | False |
--huge-mb | OOM 载荷的大小(MB);必须超过目标的 memory_limit | 12 |
--timeout | 每个请求的网络套接字超时时间(秒) | 30.0 |
--retries | 每个泄漏阶段的尝试次数(阶段 3 运行 retries + 2 次) | 3 |
--no-pre-rotate | 跳过初始 worker 轮换(阶段 0) | False |
--no-retry-rotate | 在失败的阶段尝试之间不轮换 worker | False |
-q、--quiet | 抑制详细输出日志 | False |
该漏洞利用脚本支持基于配置的预设:
--profile bookworm(默认): 针对运行在 Debian 12(Bookworm)上、使用 Apache 2.4.69 的官方 Docker 库镜像 php:8.4.26-apache 进行校准。--profile lab: 针对自定义/最小化 Apache 2.4.68 构建进行校准。当目标为本地 Docker 容器(127.0.0.1 / localhost)时,脚本可以使用 docker/offsets.py 直接从运行中的容器自动提取二进制符号偏移量,并将其缓存到 out/offsets.env。对于二进制布局与 Debian 12 不同的远程目标,请手动提供 --zif-offset 和 --dtor-offset。
在您的软件仓库中的官方供应商软件包更新之前,您可以使用配置更改、自动化脚本,或使用随附的源码补丁编译 PHP 来保护您的环境。
该漏洞依赖于 PHP 的会话上传进度机制(session.upload_progress.enabled),该机制默认启用。禁用此指令可消除攻击向量,同时保留常规文件上传功能:
在您的 php.ini 中:
session.upload_progress.enabled = Off