一个伪linux粉丝的blog

  1. 首页
  2. network
  3. 正文

PHP2Shell 紧急升级:Oracle Linux 7.9 编译 PHP 8.5 实录

24 10 月, 2026 16点热度 0人点赞 0条评论

一直有人说 PHP 是世界上最好的语言——这次 7 成网站用行动(被迫)投了赞成票,然后 PHP 官方连夜发布了两个 CVSS 9.2 的 RCE 补丁。

于是我这个 Oracle Linux 7.9 的"钉子户",也必须把去年 php 翻车的升级工程再战一次。

TL;DR:PHP 官方于 2026-10-21 发布紧急安全更新,修复两个 CVSS 9.2 的未授权 RCE 漏洞(代号 PHP2Shell),修复版本为 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12。由于 Oracle Linux 7.9 自带依赖库全面低于 PHP 8.5 门槛,本文记录在不动系统库的前提下,通过"独立目录源码编译 + PKG_CONFIG_PATH 引导"完成升级的全过程,以及 12 个踩坑点的规避方案。

 

一、漏洞背景:为什么必须马上升级

2026 年 10 月 21 日,PHP 官方罕见地提前一天预告安全发布节奏,随后放出两个 CVSS v4.0 评分 9.2 / 10 的严重漏洞补丁,业内统称为 PHP2Shell:

CVE 编号 触发条件 危害
CVE-2026-109618 PHP 处理内存耗尽错误时的异常退出流程,请求体尚未完成初始化即进入清理阶段 内存破坏 → RCE
CVE-2026-109619 FPM worker 处理新请求时未清理上一请求的内部状态,触发 Use-After-Free 内存破坏 → RCE

两者均可在默认配置下被未授权攻击者通过特制 HTTP POST 请求直接利用,影响范围覆盖 PHP 5.4 至 8.5.11——也就是说,与你写的业务代码质量无关,哪怕站点只输出一行 Hello World 也会中招。

官方修复版本:PHP 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12。PHP 8.1 及以下已 EOL,没有官方补丁,必须升级。

风险等级:Cloudflare CEO 公开披露,漏洞公告发布后 45 分钟内攻击尝试从数千次飙升至数十万次,2 小时内累计数百万次;亚马逊蜜罐早在 10 月 17 日就已捕获野外利用尝试。升级是唯一可靠的修复方式,不存在完整的临时缓解方案。

📌 我在 2025 年 10 月踩过一次 LNMP 升级 PHP 8.3.25 失败回滚的坑(点这里回看),这次借助 PHP2Shell 的契机,终于把升级一鼓作气推到了 8.5.12。

影响面有多广?——7 成网站都在枪口下

根据 W3Techs 于 2026 年 10 月 22 日(漏洞发布次日)的统计,在能识别服务端编程语言的网站中,约 69.3% 使用 PHP。也就是说,全球近 7 成网站——无论规模大小——都在本次 PHP2Shell 的潜在射程之内。

其中受影响最大的几类场景:

受影响对象 原因
WordPress / Drupal / Joomla! 站点 CMS 核心即 PHP,漏洞在引擎层,与主题插件无关,必须升级 PHP 本体
cPanel / Plesk 虚拟主机面板 面板随附 PHP 运行时,用户无权自行编译升级,需等厂商推送
部分厂商设备、Windows 桌面应用 内嵌 PHP 运行时,往往是最容易被遗忘的死角

💡 给读者的自查建议:

  • WordPress 用户:后台「站点健康 → 工具」可直接查看当前 PHP 版本;
  • 虚拟主机用户:登录 cPanel/Plesk 的 “Select PHP Version / PHP Settings” 查看并切换版本;
  • 自建服务器:php -v 一条命令见分晓。

PHP 8.1 及以下没有官方补丁,7 成网站里没升级的每一个,都是攻击者的活靶子。

二、本次升级的核心挑战

系统太老,PHP 太新。 Oracle Linux 7.9 自带的 libxml2、OpenSSL、zlib、libcurl、libzip 等基础库版本全部低于 PHP 8.5 的最低要求,且不能直接覆盖系统库——否则会破坏 yum、sshd、curl 等核心工具,风险极高。

最终采用 “逐个源码编译依赖到独立目录 + 环境变量引导 PHP 链接” 的方式完成,全程零系统库覆盖,可随时回滚。

升级前自查清单

  • [x] 备份 /usr/local/php 与 /usr/local/php/etc 全套配置
  • [x] 备份 php-fpm.conf、www.conf、php.ini
  • [x] 记录当前 php -v、php -m 输出,用于升级后比对
  • [x] 准备好回滚脚本(见文末)
  • [x] 选择业务低峰期执行 (个人博客,没啥访问)

三、最终成功的步骤

1. 安装编译工具链

系统自带的 GCC 4.8.5 无法编译 PHP 8.5 的 SHA-NI 优化代码,必须安装 devtoolset-11:

Shell
1
2
3
4
sudo yum install -y centos-release-scl
sudo yum install -y devtoolset-11-gcc devtoolset-11-gcc-c++ devtoolset-11-binutils
scl enable devtoolset-11 bash
gcc --version   # 确认 11.2.1

⚠️ 关键:后续所有编译操作都必须在 scl enable devtoolset-11 bash 的会话中执行,否则 configure 阶段会莫名报错。

2. 逐个编译依赖库(全部装到独立目录)

依赖 系统版本 PHP 8.5 要求 编译安装路径
libxml2 2.9.1 ≥ 2.9.4 /usr/local/libxml2-new(2.9.14)
OpenSSL 1.0.2k ≥ 1.1.1 /usr/local/openssl3(3.5.0)
zlib 1.2.7 ≥ 1.2.11 /usr/local/zlib-new(1.3.2)
libcurl 7.29.0 ≥ 7.61.0 /usr/local/curl-new(8.23.0)
libiconv 系统 iconv 不满足 errno 检查失败 /usr/local/libiconv(1.17)
libzip 无 / 过旧 ≥ 0.11 /usr/local/libzip-new(1.11.4,CMake 构建)

每个库编译安装后,都执行:

Shell
1
2
echo "/usr/local/xxx/lib" | sudo tee /etc/ld.so.conf.d/xxx.conf
sudo ldconfig

⚠️ libzip 特别提醒:用 CMake 构建时默认装到 lib64,ldconfig 路径必须写 /usr/local/libzip-new/lib64,不能想当然写 lib。

3. 配置 PHP 编译参数

下载并校验源码:

Shell
1
2
3
4
5
6
7
cd /usr/local/src
wget https://www.php.net/distributions/php-8.5.12.tar.gz
sha256sum php-8.5.12.tar.gz
# 官方 .tar.bz2 SHA256: ffb60edc437ced63b5137e4984db379a8111c50049c711510d8b958277efc1a8
# 请以 https://www.php.net/releases/8_5_12.php 公布的 .gz 哈希为准
tar -xzf php-8.5.12.tar.gz
cd php-8.5.12

重新激活 devtoolset-11(新开 shell 忘了就前功尽弃):

Shell
1
2
scl enable devtoolset-11 bash
gcc --version   # 确认 11.2.1+

设置环境变量:

Shell
1
2
3
export PKG_CONFIG_PATH=/usr/local/libzip-new/lib64/pkgconfig:/usr/local/openssl3/lib64/pkgconfig:/usr/local/libxml2-new/lib/pkgconfig:/usr/local/zlib-new/lib/pkgconfig:/usr/local/curl-new/lib/pkgconfig
 
export LDFLAGS="-Wl,-rpath,/usr/local/libzip-new/lib64 -Wl,-rpath,/usr/local/openssl3/lib64 -Wl,-rpath,/usr/local/libxml2-new/lib -Wl,-rpath,/usr/local/zlib-new/lib -Wl,-rpath,/usr/local/curl-new/lib -Wl,-rpath,/usr/local/libiconv/lib"

configure 命令(最终可用版本):

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
./configure \
  --prefix=/usr/local/php85 \
  --with-config-file-path=/usr/local/php85/etc \
  --with-config-file-scan-dir=/usr/local/php85/etc/php.d \
  --enable-fpm \
  --with-fpm-user=www \
  --with-fpm-group=www \
  --enable-cli \
  --with-openssl \
  --with-curl=/usr/local/curl-new \
  --with-zlib \
  --with-zlib-dir=/usr/local/zlib-new \
  --with-iconv=/usr/local/libiconv \
  --with-libzip=/usr/local/libzip-new \
  --with-mysqli=mysqlnd \
  --with-pdo-mysql=mysqlnd \
  --enable-mbstring \
  --enable-xml \
  --with-zip \
  --enable-bcmath \
  --enable-soap \
  --enable-sockets \
  --without-pdo-sqlite \
  --without-sqlite3

📝 --with-zlib-dir 和 --with-libzip 在 PHP 8.5 中已不被识别(加上不报错),真正生效的是 PKG_CONFIG_PATH。SQLite 因系统版本过旧直接禁用,业务无依赖。

4. 编译安装

Shell
1
2
make -j$(nproc)
sudo make install

安装后三项验证:

1
2
3
/usr/local/php85/bin/php -v
/usr/local/php85/bin/php -m | grep -E <span class="hljs-string">'iconv|curl|openssl|mbstring|xml|zip'</span>
ldd /usr/local/php85/bin/php | grep -E <span class="hljs-string">'ssl|curl|xml|z|zip'</span>

ldd 输出必须指向 /usr/local/xxx-new 下你新编译的库,而不是 /usr/lib64 的旧库——这是判断 rpath 是否生效的金标准。

5. 切换到 LNMP 环境

Shell
1
2
3
4
5
6
7
8
9
10
11
12
# 1. 停止旧 FPM
lnmp php-fpm stop
 
# 2. 备份旧 PHP 目录
mv /usr/local/php /usr/local/php-$(date +%Y%m%d)-bak
 
# 3. 创建软链接(LNMP 脚本通过此路径访问)
ln -s /usr/local/php85 /usr/local/php
 
# 4. 复制并编辑配置
cp /usr/local/php85/etc/php-fpm.conf.default /usr/local/php85/etc/php-fpm.conf
cp /usr/local/php85/etc/php-fpm.d/www.conf.default /usr/local/php85/etc/php-fpm.d/www.conf

编辑 www.conf,确保 Socket 路径与 Nginx 一致:

Shell
1
2
3
4
listen = /tmp/php-cgi.sock
listen.owner = www
listen.group = www
listen.mode = 0660

⚠️ 如果 www.conf 中存在 listen.acl_users,它会覆盖 owner/group 设置,必须注释掉。

Shell
1
2
3
# 5. 启动
lnmp php-fpm start
lnmp nginx reload

四、12 个坑速查表(Ctrl+F 定位即用)

# 现象 根因 规避方案
1 dnf 命令不存在 OL7.9 只有 yum 直接用 yum 即可
2 --enable-opcache 警告 PHP 8.5 OPcache 已随核心编译 删除该选项即可
3 configure 报 libxml2 过旧 系统 2.9.1 < 2.9.4 源码编译 2.9.14 到 /usr/local/libxml2-new,走 PKG_CONFIG_PATH
4 OpenSSL 1.0.2k 过旧 / curl 8.23 拒绝 1.1.1 curl 8.23 明确要求 OpenSSL 3.0+ PHP 与 curl 统一用 OpenSSL 3.5.0,避免两套并存
5 configure 选错 OpenSSL shell 残留旧 PKG_CONFIG_PATH unset PKG_CONFIG_PATH 后用 env PKG_CONFIG_PATH=... ./configure 临时指定
6 zlib 1.2.7 过旧 < 1.2.11 编译 zlib 1.3.2 到独立目录
7 iconv errno 检查失败 glibc iconv 不满足 编译 GNU libiconv 1.17,--with-iconv=/usr/local/libiconv
8 libzip .pc 找不到 CMake 默认装到 lib64 ldconfig 与 PKG_CONFIG_PATH 路径都用 lib64
9 attribute(target("sha")) is unknown GCC 4.8.5 不识别 SHA-NI 安装 devtoolset-11。不存在 --disable-hash-sha-ni 这个选项,别去试
10 SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 未定义 系统 SQLite 太老 业务无依赖则 --without-pdo-sqlite --without-sqlite3
11 切换后 502,Socket 属主是 root FPM 主进程 root 启动,Socket 默认 root 显式配置 listen.owner/group/mode,注释 listen.acl_users,用 ls -l /tmp/php-cgi.sock 验证
12 php-fpm 不在 bin PHP 8.5 装到 sbin /usr/local/php85/sbin/php-fpm,但 LNMP 通过软链接访问,软链接指对即可

五、上线后验证清单

升级完成、业务恢复正常后,不要马上关会话,跑完这 6 项再收工:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 版本必须 ≥ 8.5.12
/usr/local/php85/bin/php -v
 
# 2. 关键扩展加载正常
/usr/local/php85/bin/php -m | grep -E 'iconv|curl|openssl|mbstring|xml|zip'
 
# 3. 二进制动态链接指向新编译库
ldd /usr/local/php85/bin/php | grep -E 'ssl|curl|xml|z|zip'
 
# 4. Socket 属主为 www
ls -l /tmp/php-cgi.sock
 
# 5. FPM 进程监听正常
ps -ef | grep php-fpm
 
# 6. 访问 phpinfo() 页面(截图存档)

【此处补一张 phpinfo() 截图,显示 PHP Version 8.5.12 与加载的扩展】

此外,结合本次 PHP2Shell 漏洞特征(CVE-2026-109619 涉及跨请求状态残留),强烈建议同步检查 php.ini 中的 session.gc_maxlifetime 与 FPM 的 pm.max_requests,适当调低 pm.max_requests(例如 500)可让 worker 周期性重建,进一步降低跨请求内存状态污染的暴露面。

六、回滚预案(万一出问题)

Shell
1
2
3
4
5
lnmp php-fpm stop
rm /usr/local/php
ln -s /usr/local/php-$(date +%Y%m%d)-bak /usr/local/php
lnmp php-fpm start
lnmp nginx reload

关键:备份目录名带时间戳,回滚只需改一次软链接指向,不动任何库文件,5 分钟内可恢复业务。

七、复盘与建议

  • PHP 8.1 及以下没有补丁,仍在用的读者请尽快评估升级到 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12。
  • 临时缓解不可靠:WAF 规则、禁用某些函数等手段都挡不住该漏洞的利用链,升级是唯一正解。
  • AI 时代的漏洞节奏变了:本次漏洞攻防两侧都在提速——常态化保持 PHP 版本跟进,比临时救火成本低得多。
  • 老系统 ≠ 不能升级:本篇证明 OL7.9 + 源码编译依赖同样能跑到 PHP 8.5.12,关键是"独立目录 + PKG_CONFIG_PATH + rpath"三板斧,不动系统库零风险。

参考链接

  • PHP 官方 8.5.12 发布公告:https://www.php.net/releases/8_5_12.php
  • PHP 官方 8.x ChangeLog:https://www.php.net/ChangeLog-8.php
  • W3Techs 服务端语言占有率统计(2026-10-22):https://w3techs.com/technologies/details/pl-php
  • WatchTowr 漏洞 FAQ:https://watchtowr.com/intelligence/php-cve-2026-109618-faq
  • Datadog Security Labs 分析:https://securitylabs.datadoghq.com/articles/php2shell-critical-vulnerabilities-in-php
  • 我上次升级失败的复盘:https://blog.wanjie.info/2025/10/lnmp-php-8-3-25-upgrade-failure-rollback/

相关文章:

  1. LAMP 系统性能调优,第 2 部分: 优化 Apache 和 PHP
  2. 普通usb ZC0301 WebCam成功设置为Web Cam Server
  3. plowshare -- command-line application to download files for file-sharing websites
  4. Moving WordPress blog to a new server
标签: CVE-2026-109618 CVE-2026-109619 libzip CMake LNMP OpenSSL 3.x 源码编译 PHP 8.5 编译 PHP2Shell
最后更新:24 10 月, 2026

wanjie

这个人很懒,什么都没留下

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

This site uses Akismet to reduce spam. Learn how your comment data is processed.

归档
分类
  • network / 337篇
  • Uncategorized / 117篇
  • unix/linux / 128篇
  • 业界资讯 / 38篇
  • 公司杂事 / 11篇
  • 数码影像 / 14篇
  • 美剧 / 3篇
  • 美图共赏 / 21篇
  • 英语学习 / 3篇
标签聚合
泰国 dreamhost kernel kubectl 网站运营 unveiled today squid Google Voice postgres ldap openssl Google 职责 docker 网通 brew 虚拟主机 Linux k8s Opera Mini Nginx wget gitlab 邮件归档 Ubuntu d90 deepseek Google Adwords nexus VPS

COPYRIGHT © 2008-2026 wanjie.info. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang