PHP2Shell 在线漏洞检测工具

输入你拥有或获授权测试的网址,逐项查看 PHP 特征、版本线索和表单请求响应,辅助判断 PHP2Shell 暴露风险与后续修复方向。

2

PHP 核心漏洞

9.2

CVSS v4.0 评分(严重)

4

8.2–8.5 的上游修复分支

漏洞概览

PHP2Shell 是什么,为什么需要立即排查?

PHP2Shell 是 CVE-2026-109618 与 CVE-2026-109619 两项 PHP 核心内存安全漏洞的统称,均被评为 CVSS v4.0 9.2 分。攻击者无需登录就可能触发远程代码执行,具体影响取决于版本、运行方式和触发路径。

阅读 PHP 官方公告

受影响的是 PHP 引擎,不只是某个网站程序

PHP-FPM、Apache mod_php、php-cgi、FrankenPHP 和 LiteSpeed 等提供 Web 请求的 PHP 环境都应纳入清单。PHP 官方认为 mod_php 风险最高,已演示的攻击可在应用代码运行之前触发。即使页面简单、应用代码没有已知漏洞,也不能排除风险。

不仅要升级网站,还要确认底层运行时

仅更新 WordPress、Drupal、框架或插件,不等于已更新它们使用的 PHP。需要分别检查网站绑定的 PHP 版本、FPM 池、容器镜像、多个服务节点,以及管理面板或设备中内嵌的 PHP。官方修复版本已于 2026 年 10 月 21 日发布。

检测内容

关注PHP特征、请求响应与补丁状态

七项请求如何帮助排查?

先获取 GET 基线,再针对三种方法分别发送普通表单和 multipart 表单。每项单独观察响应,再进行下一项;这些普通请求用于比较行为,不包含远程代码执行或内存耗尽载荷。

PHP2Shell 七项 HTTP 请求排查说明
顺序 请求方法 发送内容 观察重点
01GET不带请求体页面是否可访问、重定向、公开的 PHP 版本标识与响应头。
02POSTapplication/x-www-form-urlencoded一个普通文本字段,作为 POST 对照。
03POSTmultipart/form-data一个文本字段,与 POST 对照比较;不添加文件部分或上传进度字段。
04PUTapplication/x-www-form-urlencoded一个普通文本字段,观察该路径对 PUT 的处理。
05PUTmultipart/form-data与 PUT 普通表单比较内容类型造成的响应差异。
06PATCHapplication/x-www-form-urlencoded一个普通文本字段,作为 PATCH 对照。
07PATCHmultipart/form-data与 PATCH 对照比较,避免只检查 POST 就推断其他方法的行为。

X-Powered-By 或 Server 中的 PHP 标识,以及类似 PHPSESSID 的会话 Cookie,只能作为运行环境线索。它们可能被隐藏、改写或自定义;存在 Cookie 也不能证明请求体已被 PHP 解析。

这类检查只覆盖输入的网址与路径。不同路由、CDN 规则和可直接访问的源站可能表现不同;不要把首页的结果推广到整个网站。只在已获授权、适合接受表单请求的路径上检查。

如何理解检测结果

区分暴露线索与已核实的修复

公开响应只能提供部分证据。版本号可能隐藏或经过修改,旧版本也可能已获厂商回补;需要结合实际运行环境,避免把证据不足误判为安全。

了解常见判断误区

观察到修复版本线索

公开版本号达到对应分支的修复起点,是有价值的线索,但响应头可能被代理改写,仍需在服务器上确认所有实例实际加载了修复代码。

观察到旧版本风险

低于上游修复版本应优先核查,但发行版和 LTS 厂商可能已经回补补丁。未确认回补状态时应标为待核实,而不是宣称已验证远程代码执行。

请求被拒绝或出现响应差异

普通表单成功而 multipart 返回 4xx,可能与内容类型限制有关;两者都返回 405,也可能只是该路径不支持此方法。仅凭状态码无法区分 CDN、Web 服务器或应用层拒绝。

未发现 PHP 或未取得响应

隐藏版本、代理缓存、自定义 Cookie、连接失败或超时都会限制判断。此时应记录信息不足或未能评估,不能用绿色安全结论代替缺失的证据。

检测流程

从一个网址开始,逐项了解风险

1

输入目标网址

填写你拥有或获授权测试的网站地址,明确要核查的网页路径。

2

逐项检测并查看响应

先查看 GET 基线,再依次对比 POST、PUT、PATCH 下普通表单与 multipart 请求的响应。

3

查看风险提示与修复建议

结合状态码与版本线索理解结果,再对照实际 PHP 环境和厂商公告核实补丁状态。

服务器端排查

如何确认网站实际运行了修复后的 PHP?

外部检测适合发现线索,补丁结论仍需在主机、容器或托管面板中确认。建议按以下顺序记录运行环境、软件包来源、修复版本和更新后的进程状态。

1. 先找到真正处理请求的 PHP

核对站点绑定的 PHP、Web 服务器模块或 FPM 池。多版本共存、多个站点、容器和负载均衡节点需要分别盘点。命令行 php -v 只说明当前 CLI 版本,不能代表网站正在使用的版本;不要为此公开暴露 phpinfo 页面。

php -v

2. 核对完整包版本和厂商公告

按实际系统和安装包名查询版本,再与该发行版的安全公告对照。例如 Ubuntu 24.04 的 8.3.6-0ubuntu0.24.04.13 已包含修复;只看到 PHP 8.3.6 会丢失回补信息。以下是包查询示例,请选择适合系统的一项并替换实际包名。

dpkg-query -W php8.3-fpm
rpm -q php-fpm
查看 Ubuntu 官方修复包清单

3. 应用对应分支的修复版本

使用对应分支的上游修复版、后续安全版本或厂商已确认的回补包。面板、设备和容器自带的 PHP 需按各自供应商方式更新。PHP 8.1 及更早版本已停止常规上游支持,需确认 LTS 厂商修复或迁移;官方此次另提供了 7.4、8.0、8.1 的最小源码回补。

4. 重启并逐实例复核

确认相关 PHP-FPM、Apache 或其他 worker 已重启,容器和多节点部署已替换完成,避免磁盘上的包已更新但旧进程仍在服务。检查异常请求、内存耗尽和 worker 崩溃记录可辅助排查,但没有这些日志不代表未受影响。

自己动手:用 curl 运行七项检查

脚本串行发送 1 次 GET,以及 POST、PUT、PATCH 各两种表单请求,仅使用普通文本字段,不发送文件或上传进度字段。请只对已获授权、适合接受测试表单的路径运行;普通请求仍可能触发应用业务。

Bash / curl
#!/usr/bin/env bash
# PHP2Shell HTTP observations: 7 sequential requests, no exploit payload.
set -u

URL="${1:-https://example.com/}"
case "$URL" in
  http://*|https://*) ;;
  *) printf 'ERROR=HTTP(S)_URL_REQUIRED\n' >&2; exit 2 ;;
esac

if ! command -v curl >/dev/null 2>&1 || ! command -v awk >/dev/null 2>&1; then
  printf 'ERROR=CURL_AND_AWK_REQUIRED\n' >&2
  exit 127
fi

probe() {
  printf '\n[%s/7] %s %s\n' "$1" "$2" "$3"
  local method="$2"
  shift 3
  curl -q --globoff --proto '=http,https' --silent --show-error \
    --connect-timeout 5 --max-time 15 --request "$method" \
    --dump-header - --output /dev/null \
    --write-out '\nHTTP_CODE=%{http_code} TOTAL_SECONDS=%{time_total}\n' \
    "$@" --url "$URL" |
  awk '{
    sub(/\r$/, "")
    line = tolower($0)
    if ($0 ~ /^HTTP\// || line ~ /^(server|x-powered-by|content-type):/ || $0 ~ /^HTTP_CODE=/) {
      print
    } else if (line ~ /^set-cookie:[ \t]*phpsessid[ \t]*=/) {
      print "PHPSESSID=present; value hidden"
    }
  }'
  local curl_status="${PIPESTATUS[0]}"
  if [ "$curl_status" -ne 0 ]; then
    printf 'CURL_EXIT=%s\n' "$curl_status"
    FAILED=1
  fi
}

FAILED=0
probe 1 GET baseline
probe 2 POST urlencoded --data-raw 'php2shell_check=1'
probe 3 POST multipart --form-string 'php2shell_check=1'
probe 4 PUT urlencoded --data-raw 'php2shell_check=1'
probe 5 PUT multipart --form-string 'php2shell_check=1'
probe 6 PATCH urlencoded --data-raw 'php2shell_check=1'
probe 7 PATCH multipart --form-string 'php2shell_check=1'
exit "$FAILED"

脚本适用于 Linux/macOS 的 Bash,以及 Windows 的 WSL 或 Git Bash。保存为 php2shell-self-check.sh,运行下方命令,并将网址换成已获授权的测试页面;不要将整段 Bash 脚本直接粘贴到 PowerShell。

bash php2shell-self-check.sh https://example.com/test.php

连接超时为 5 秒,每项总超时为 15 秒。脚本忽略个人 curl 配置,保留 TLS 校验,不自动跳转或重试;遇到 3xx 时,先确认最终地址仍在授权范围内,再改用该地址运行。PHPSESSID 仅显示存在标记,Cookie 值和响应正文不会输出。

HTTP_CODE 是响应状态,TOTAL_SECONDS 是总耗时;CURL_EXIT 非零表示该项传输失败,脚本仍继续其余检查。脚本最终返回非零表示参数、依赖或传输问题;HTTP 4xx/5xx 会正常记录,退出码不能用来判断漏洞或补丁状态。

如何解读终端输出

版本响应头只是线索

Server 或 X-Powered-By 可能隐藏或过期。请核对网站实际运行的 PHP:各分支最低官方修复版本为 8.2.35、8.3.36、8.4.27、8.5.12;厂商回补需结合完整软件包版本和安全公告确认。

对照同一方法的两种编码

同一方法下,urlencoded 返回 2xx 或 3xx,而 multipart 返回 403 或 406,只能说明响应存在差异。不能据此确认 WAF 已拦截,也不能确认请求在进入 PHP 前就被拒绝。

成功响应不等于 PHP 已解析

multipart 返回 2xx 或 3xx,仅说明收到了成功响应或跳转响应;不能证明正文进入 PHP 并被解析,也不能据此判断漏洞是否存在。

405 与 PHP 标识均不能单独定论

全部返回 405 不证明已经修复;未见 PHP 标识不等于未使用 PHP;出现 PHPSESSID 也不能确定 multipart 已被解析,或响应来自哪一层。

查看官方修复版本与升级建议
暂时无法升级时,缓解措施能做什么?

PHP 官方明确:只有更新才能完整修复,以下配置仅减少部分已知路径的暴露,不应把未打补丁的环境标为安全。修改前应按应用需求和官方公告评估。

  • 关闭 session.upload_progress.enabled,并重启全部 worker。设置必须在请求解析前通过 php.ini、FPM 池或服务器配置生效,不能依赖 ini_set() 或 FPM 的 .user.ini。它仅阻断已确认的 session 路径。
  • PHP 8.5 可按官方建议关闭 fatal_error_backtraces 并重启 worker;这仅覆盖已确认的 fatal backtrace 路径,不覆盖其他变体。
  • 在 Web 服务器或代理层审查请求体、字段数、multipart 部分数量等限制,并检查源站是否能绕过 CDN 直接访问。隐藏错误输出、仅阻止一种方法或仅检查一个路径,都不能替代修复。

官方修复版本

核对 PHP 8.2–8.5 分支的修复起点

按分支分别比较版本:8.3 的修复线不能用于判定 8.4,预发布版本或未知分支也不应直接视为已修复。发行版回补和自行构建的补丁,应核对完整包版本、构建记录及厂商公告。

阅读官方更新建议

使用宝塔面板?在软件商店快速升级 PHP

据宝塔 2026-10-21 公告,面板已同步部分 PHP 安全修复版本。具体开放升级的版本,请以宝塔面板软件商店实际显示为准。

查看宝塔升级公告

升级前请备份网站、数据库及相关配置,并选择合适的维护时间。

  1. 找到网站实际使用的 PHP

    登录宝塔面板,进入「软件商店 → 已安装」,找到当前网站正在使用的 PHP 版本,打开其管理页面。

  2. 更新至对应分支的安全版本

    在对应 PHP 管理页面检查可用更新,按提示升级至上方列出的同分支修复版本,或该分支后续安全版本。

  3. 重启服务并验证网站

    升级后重启对应 PHP 服务,确认所有工作进程已重新加载;核对网站实际运行的 PHP 版本,并检查访问、文件上传和数据库连接等业务。

安装了多个 PHP 版本时,请逐一检查仍在使用的版本。若另行安装新版本,还需确认网站已切换到修复后的 PHP 运行时。

FAQ

PHP2Shell 漏洞检测与修复常见问题

理解版本线索、状态码与厂商回补的区别,避免过度解读检测结果。

PHP2Shell 是什么,哪些网站需要排查?

PHP2Shell 指 CVE-2026-109618 与 CVE-2026-109619 两项 PHP 核心漏洞,可能导致未经认证的远程代码执行。所有使用未修复 PHP 处理 Web 请求的环境都应排查,应用代码本身没有漏洞也不能排除风险。

返回 403、405 或 413,是否说明已受到保护?

不能。认证要求、不支持的请求方法、体积限制或代理都可能产生这些状态码。即使 multipart 请求被拒绝,也只能说明当前路径的响应表现,不能证明 PHP 已修复或所有攻击路径都被阻断。

没有发现 PHP 响应头,是否说明网站不受影响?

不能据此判断。PHP 版本公开可能已关闭,CDN、反向代理或静态首页也可能掩盖后端技术。没有发现特征应视为信息不足,需要进一步核实服务器实际运行环境。

应该升级到哪个版本,旧版本是否一定未修复?

上游修复版本是 PHP 8.2.35、8.3.36、8.4.27、8.5.12,应使用对应分支的修复版或后续安全版本。旧版可能包含厂商回补,应核对完整包版本与厂商公告。PHP 8.1 及更早版本已停止上游常规维护;更新后还需重启相关 worker。

为什么除了 POST,还要查看 PUT 和 PATCH?

不同方法可能走不同的路由和过滤规则。PHP 8.4 起提供 request_parse_body(),应用可以用它解析非 POST 方法的 multipart 请求;这不代表所有应用都会自动解析 PUT 或 PATCH。因此只观察 POST 的行为,不能推断其他方法或其他路径已经受到保护。

POST 返回 200、PUT/PATCH 返回 405,且没有 PHP 标识,该如何判断?

应记录为无法确认 PHP 与补丁状态。POST 的 200 只能说明该路径作出响应,405 只说明某一层拒绝了方法;静态页面、其他后端和隐藏标识的 PHP 都可能出现这种组合。下一步是在服务器核实实际运行环境,而不是直接判定安全或已验证存在漏洞。

漏洞与修复资料核对日期为 2026-10-22。外部观察存在局限,实际处置请以当前 PHP 和对应厂商公告为准。

让网站的 PHP2Shell 风险更清楚

逐项检查公开响应,结合证据理解风险,再对照服务器实际环境落实补丁与修复。

了解检测项目