QQ登录
只需一步,快速开始
 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 91|回复: 3

老 PHP 升不上去,这个 9.2 漏洞怎么扛

[复制链接]

5

主题

4

回帖

309

积分

中级会员

积分
309
发表于 2026-10-23 20:30:49 | 显示全部楼层 |阅读模式
上一篇说了 PHP2Shell(CVE-2026-109618 / CVE-2026-109619)只能靠升 PHP 修。这篇讲另一半现实:升不了的时候怎么办。

先立个规矩:缓解动作要照官方口径来,别凭直觉拍。 我自己就差点在这上面栽了一跤(后面讲)。下面每一条都标了官方出处,你要改的时候可以对照。

一、先看清洞从哪进来

两个洞都通过特制的 multipart POST 请求触发;109619 在 FPM 模式下走 session.upload_progress。

先看自己机器现在的状态:
  1. php -i | grep -E '^post_max_size|^memory_limit|^session.upload_progress|^upload_max_filesize'
复制代码

真实输出(PHP 8.3 默认值,对照用):
  1. memory_limit => -1 => -1
  2. post_max_size => 8M => 8M
  3. upload_max_filesize => 2M => 2M
  4. session.upload_progress.cleanup => On => On
  5. session.upload_progress.enabled => On => On
复制代码

session.upload_progress.enabled => On 就是 109619 的入口。

二、官方缓解口径(照着改,别自己发挥)

针对 109618(OOM 破坏)

官方方向是 memory_limit = -1——不是压低,是放开。因为这个洞就在 OOM 处理路径上,人为压低内存反而可能把请求推进那个分支。

关键是要用管理员级配置设,让应用改不了:
  1. ; FPM pool(/etc/php/8.3/fpm/pool.d/www.conf)
  2. php_admin_value[memory_limit] = -1
复制代码
  1. ; mod_php(Apache 配置里)
  2. php_admin_value memory_limit -1
复制代码

配套三件事(很重要,否则等于开了个 DoS 口子):

· 把请求体卡死:post_max_size 保守取 8M(需要上传的取 32M),并保证 upload_max_filesize 小于 post_max_size;
· 在 web 服务器/代理层也限请求体(nginx client_max_body_size),别只靠 PHP;
· 条件允许的话,用容器 / cgroup 的内存上限兜底。

⚠️ 不要用 RLIMIT_AS / RLIMIT_DATA——官方明确警告这两个会让底层分配走向不可控。

⚠️ 不受管的上限本身有风险,所以改完必须重启所有 worker,并确认没有别的地方(.user.ini、应用里的 ini_set)把 memory_limit 又设回有限值:
  1. php -i | grep '^memory_limit'          # 期望 -1
  2. grep -rn 'memory_limit' /www/wwwroot/你的站点/.user.ini 2>/dev/null
复制代码

针对 109619(状态残留)
  1. session.upload_progress.enabled = 0
  2. session.use_strict_mode = 1
复制代码

⚠️ 两个必须写成布尔,FPM 池里用 php_admin_flag:
  1. ; FPM pool
  2. php_admin_flag[session.upload_progress.enabled] = off
  3. php_admin_flag[session.use_strict_mode] = on
复制代码

⚠️ php.ini 和 FPM 池是两份配置,FPM 读池里的那份。只改 php.ini 在 FPM 环境下经常不生效,这就是很多"我明明改了还是被打"的来源。

⚠️ 不要靠 ini_set() 或 .user.ini 来做这个缓解——请求级设置挡不住引擎级利用。改完重启所有 worker。

其他官方提示

· 8.5 分支:官方建议设 fatal_error_backtraces = 0。
· 如果站点根本不用 multipart 表单:直接在前端把 multipart 请求挡掉,比什么都干脆。
· WAF 规则可以加,但只能当辅助——WAF 是绕过游戏,别当唯一防线。
· 实在顶不住的业务,先下线比带着洞在网上跑强。

三、我自己踩的那一下(真实案例)

我手上有一台:ThinkPHP5 的业务站,PHP 7.3.31,CentOS 7 + 宝塔,程序升不了级、版本锁死,7.3 连 backport 都没有——只能缓解。

漏洞出来当天早上,我第一反应是"OOM 洞嘛,那就把内存压小":memory_limit = 64M、post_max_size = 2M、nginx client_max_body_size 2m,当时觉得挺合理。后来对官方口径复核,发现方向反了——109618 要的是 memory_limit = -1,我压到 64M 恰好是把它往 OOM 分支上推。

所以那台机的处置是两段:

1. 当天先做的:限请求体(nginx + PHP 层)、敏感路径 403、exec/system 之类保持禁用、改动前全部备份(*.bak-20261022)、全盘查入侵痕迹(干净);
2. 复核后要改的:memory_limit 按官方口径改回 -1(以 php_admin_value 设,防应用覆盖),session.upload_progress 关掉 + use_strict_mode 打开。

这件事给我的教训就一句:安全缓解最容易犯的错不是不做,而是"凭直觉做反了"。 官方的缓解建议哪怕看着别扭,也先照做,再理解为什么。

四、改完怎么验证
  1. # 配置读的是哪一份(多版本环境关键)
  2. php -i | grep 'Loaded Configuration File'
  3. # 四项核对
  4. php -i | grep -E '^memory_limit|^post_max_size|^session.upload_progress.enabled|^session.use_strict_mode'
  5. systemctl restart php-fpm && systemctl status php-fpm --no-pager | head -3
  6. curl -sI https://你的域名 | head -1        # 站点还活着
复制代码

memory_limit = -1、post_max_size 在 8M/32M、upload_progress 是 Off、use_strict_mode 是 On、站点 200——这才叫改完了。

五、顺手看有没有已经被打过

这个洞的特征是大的 multipart POST,翻访问日志:
  1. grep -E 'POST' /www/wwwlogs/access.log | awk '{print $1, $7, $9, $10}' | sort | uniq -c | sort -rn | head -20
复制代码

重点三样:同一 IP 短时间大量 POST;Content-Length 异常大但 URL 是正常页面;POST 之后紧跟可疑路径(往 /tmp 写文件、新出现的 .php)。

再看进程和新增文件:
  1. ps auxf | grep -iE 'www|php' | grep -v grep
  2. find /www/wwwroot -name '*.php' -newermt '2026-10-20' | head -20
  3. crontab -l; ls -lt /etc/cron.d/ | head
复制代码

最后一条最实用:最近两天被改过/新增的 php 文件——正常业务不会在半夜动几十个文件。

我那台查完是干净的,但这是查过才敢说,不是"应该没事"。

六、缓解只是争取时间

这四条闸能把机器从"随便一个脚本都能试"降到"需要针对你定制",但它不是补丁:

· 官方 exp 迭代后,绕过手法一定会出现;
· 业务一旦放开上传(post_max_size 变大),闸一就松了一半。

而且补丁打完要把 memory_limit 恢复成一个真实值——补丁后的引擎有软 OOM 和硬 OOM 两级处理,有限上限才是正常状态,-1 只是过渡。

所以正确姿势:缓解先顶上 → 把升级排进计划 → 给 EOL 分支定一个迁移日期。 老版本 PHP 本身早就不修了,这次是 PHP2Shell,下次还有别的——EOL 的机器,永远在等下一个洞。

小结

目标官方口径写在哪
掐 109618memory_limit = -1(php_admin_value)FPM 池 / Apache
限请求体post_max_size 8M(有上传 32M)+ nginx 层php.ini + nginx
掐 109619session.upload_progress.enabled=0、session.use_strict_mode=1FPM 池(php_admin_flag)
8.5 附加fatal_error_backtraces = 0php.ini


一句话:缓解是给自己争时间的,不是给自己安心的。 升得了就升;升不了就把闸拉上、日志盯住、升级排进本季度计划。

2

主题

1

回帖

115

积分

注册会员

积分
115
发表于 3 天前 | 显示全部楼层
学习了啊啊,不错

5

主题

4

回帖

309

积分

中级会员

积分
309
 楼主| 发表于 3 天前 | 显示全部楼层
谢谢,互相学习~

这洞最头疼的就是「升不动」这种情况。后面我把「升不了、只能先缓解」那部分单独再写细一点,把官方口径和自查命令列全。

2

主题

2

回帖

128

积分

注册会员

积分
128
发表于 3 天前 | 显示全部楼层
补充一点:如果一时半会升不了 PHP,除了按官方口径做缓解,最快能落地的往往是在前面那层(nginx / WAF)先把畸形的 multipart 请求挡掉,先扛过窗口期。

但缓解终究只是缓解,条件是「能升就升」,别拿缓解当长期方案。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|七亿社区站长论坛

GMT+8, 2026-11-1 22:41 , Processed in 0.062485 second(s), 5 queries , Redis On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表