PHP-FPM也不安全?PHP2Shell 受影响版本、自查方法与修复命令

千敏君_5147

千敏君_5147

2026-10-22

667人浏览

原创

哪怕你用的是php-fpm,也没法完全排除php2shell的攻击风险。正确操作是先核对fpm的实际二进制文件、池配置和供应商提供的安全补丁,再逐个池替换工作进程;只看cli版本号或者网页返回的响应头,都不能单独作为漏洞已经修复的有效证明。

PHP 官方网站相关页面截图

为什么 FPM 的工作方式不能成为免修理由

PHP-FPM靠一组常驻工作进程处理用户请求。官方披露OOM漏洞时明确提过,FPM会在请求启动失败时直接退出对应的子进程,所以它和mod_php在请求启动阶段的风险路径确实存在差异。但只要请求成功启动,后续应用的所有操作,还是有可能走到需要打补丁的危险处理流程里,没法完全规避风险。

官方 OOM 公告说明 FPM 与 mod_php 的启动失败处理差异

已经有另一个公开的状态漏洞验证了,只要满足特定应用操作的条件,FPM的攻击路径完全可以被触发。生产环境请求会留下和当前请求绑定的状态数据,如果中途遇到致命错误打断了清理流程,下一个后续请求在完成正常初始化之前就调用了旧状态,很可能出现危险的越权访问。进程池复用的机制本来就是让不同请求共享同一个worker进程的生命周期,框架自带的请求隔离,根本不等于PHP解释器内部的状态隔离。

官方状态漏洞公告解释已验证的 FPM 路径所需应用条件

先查网站到底连接哪一个池

  1. 先看网站虚拟主机的FastCGI转发目标,把对应的套接字路径或者内网端口记下来,再顺着找到对应的FPM池,核对池配置文件、关联服务名和实际执行文件,别只看系统默认的PHP命令版本就下判断。

  2. 用FPM二进制的完整路径查询实际运行的版本,再结合系统的软件包信息核对补丁是否到位。上游官方发布的最低修复版本门槛是8.2.35、8.3.36、8.4.27、8.5.12,各个发行版自己做的回补包,要以对应发行商的官方公告为准。

  3. 从做了访问控制的站点诊断入口,读取当前请求对应的SAPI类型和实际版本。运维用的诊断页面只需要展示必要的几个字段就行,绝对不能把完整的phpinfo输出长期暴露给公网访客。

# Ubuntu 8.3 FPM 示例,服务名与路径按实际环境替换
php-fpm8.3 -v
dpkg-query -W php8.3-fpm php8.3-common
systemctl show php8.3-fpm --property=ExecStart,MainPID

要是你的虚拟主机是转发到容器里的FPM,直接在宿主机上跑上面这些命令,查出来的结果根本代表不了容器内部的版本。必须进到实际跑服务的容器里读取版本号和镜像摘要,还要确认负载均衡后面没有漏网的旧容器还在接收用户流量。

btpanel phpsite 宝塔面板PHP网站
btpanel phpsite 宝塔面板PHP网站

宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理

下载

按部署形态安排安全切换

形态 切换方法 特别检查
单个 FPM 服务 维护窗口内更新并重启 套接字权限和启动日志
多个版本或多个池 逐项核对并替换 旧分支服务是否遗留
容器 FPM 新镜像重建容器 所有副本的镜像摘要

正式替换之前,一定要先检查配置语法有没有问题、旧的扩展能不能兼容新版本,替换完成之后再观察新启动的进程是不是运行稳定。只让代理重载配置,根本更新不了底层的FPM二进制文件;只随便发一次普通请求测试,也没法证明每一个后端节点都已经完成了修复。

# 安装供应商修复包后,在维护窗口执行
sudo php-fpm8.3 -t
sudo systemctl restart php8.3-fpm
systemctl is-active php8.3-fpm
systemctl show php8.3-fpm --property=MainPID,ExecMainStartTimestamp

只读脚本用来识别运行上下文

<?php // 读取当前进程,不探测或连接 FPM 端口。
echo json_encode([
    'version'=>PHP_VERSION,
    'sapi'=>PHP_SAPI,
    'is_fpm_request'=>PHP_SAPI === 'fpm-fcgi',
    'loaded_ini'=>php_ini_loaded_file() ?: '(none)',
    'upload_progress'=>ini_get('session.upload_progress.enabled'),
    'note'=>'Run inside the protected target environment for real FPM evidence'
],JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), PHP_EOL;

把这段代码存成sapi-check.php,放到目标环境里用对应的解释器运行就行。这段代码之前在PHP 8.5.10的WebAssembly环境里测试过,所以示例截图里会显示sapi是wasm、is_fpm_request为false,这个测试结果不能当成生产环境FPM检测通过的依据。

只读示例的真实运行输出:当前 SAPI 与 FPM 判断结果,演示环境会如实显示不是 FPM

切换后出现五零二,先保留失败现场

代理返回502网关错误,一般只是说明它暂时连不上上游的FPM服务,不能上来就直接断定是补丁本身有问题。先检查FPM服务有没有正常启动、套接字文件有没有生成、文件所属的用户有没有变,再和代理配置里写的路径做比对。要是升级的时候跨了PHP大版本分支,默认的套接字文件名很可能跟着变,很容易出现路径不匹配的问题。

如果服务刚启动就直接退出,去看启动日志里第一条报的致命错误就行,常见的原因无非是旧扩展加载失败、配置指令和新版本不兼容、监听端口被别的进程占了。别上来就清空所有配置瞎试错,先保留新旧配置的差异,找个没有流量的节点先把服务调通再说。

集群做验收的时候,要给每一个后端节点单独留检查结果,还要想办法让测试请求绕过页面缓存直接打到PHP解释器上。不然静态缓存返回200成功,只能说明缓存层正常,根本验证不到后端PHP的状态。业务层面的检查至少要覆盖登录、数据库查询、文件上传、常见错误页面这几个场景,才能让升级带来的权限问题、扩展兼容问题尽早暴露出来。

所有诊断入口都必须限制在管理网络内访问,检查完之后第一时间删掉。公网随便暴露环境路径和详细配置,只会额外增加信息泄露的风险。所有必要的检查证据存到内部变更单里就行,诊断页面本身不需要长期挂在线上。

FPM 修复容易遗漏的四项

  • 改错配置:PHP的CLI模式和FPM模式加载的php.ini很可能不是同一个文件,一定要核对实际加载的ini文件路径。
  • 池中覆盖设置:全局配置统一更新完之后,还要逐个检查池级的自定义管理值和请求级的参数有没有被旧配置覆盖。
  • 旧进程继续处理长请求:切换版本之前先把节点从流量池摘出来,确认所有旧版本的工作进程全部退出之后再切流量。
  • 漏掉队列服务:后台常驻的PHP解释器队列服务,也要逐个核对软件包版本和运行进程,不能只靠网页端的验收就默认没问题。

最后一定要整理好套接字对应到池、池对应到服务、服务对应到软件包的完整映射关系,下次再做PHP安全更新的时候,直接按这份关系定位就行,不用每次都从系统默认终端的PHP版本开始瞎猜。

php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php漏洞 php php-fpm

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

11204

6

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

6501

5

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

2155

5

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

2023.10.23

4108

4

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

2023.10.23

4834

6

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.03

3791

9

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.09

5457

8

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

4262

8

sprintf函数用法详解
sprintf函数用法详解

sprintf函数的用法:1、格式化字符串;2、指定输出宽度和精度;3、返回值。更多关于sprintf函数用法详解的内容,大家可以阅读下面的文章。

2023.11.27

12202

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习