AI两天挖出PHP的22年老雷

博客分类: 

PHP2Shell漏洞

10月21日晚上,PHP官方发了个紧急补丁,一次修掉两个CVSS 9.2分的严重漏洞,社区给它们起的代号简单粗暴:PHP2Shell。意思是攻击者往你的网站发一个请求,就能在服务器上拿到一个shell。不用账号,不用密码,不用骗任何人点链接。

我职业第一份工作是写PHP的,现在这个博客也是Drupal跑的,底层还是PHP。所以这事出来,我第一件事不是看分析文章,是扫了一遍自己博客的响应头。

响应头告诉我的事

结果有点讽刺。PHP版本倒是没暴露,X-Powered-By被关掉了。但Server头大大方方写着nginx/1.14.0 (Ubuntu),还有一行X-Generator: Drupal 7,生怕别人不知道我跑的是什么。

后来想想,藏PHP版本这事本身就没意义。这次的漏洞在PHP引擎里。跟你写了什么代码无关,跟框架无关,跟藏没藏版本号更无关。WordPress、Laravel、Drupal、ThinkPHP,一视同仁。官方措辞罕见地直接:没有完整的缓解办法,升级是唯一安全的选择。

具体是两个洞:CVE-2026-109618,内存耗尽场景下的内存破坏;CVE-2026-109619,全局状态残留。听着抽象,我打个比方。PHP为了跑得快,进程是复用的,一个worker接待完这个请求,清理一下现场,接着接待下一个。这两个洞坏就坏在"清理现场"这一步:攻击者发一个特制的multipart请求,把worker的内存状态搞乱,下一个请求进来,接手的是上一轮的残局,顺着残局就能把指令塞进去执行。

运行模式也全军覆没:PHP-FPM、Apache mod_php、php-cgi、FrankenPHP、LiteSpeed,都在名单上。其中mod_php最要命,有验证说它能在你的网站代码还没开始执行时就触发。你的代码一行都没跑,服务器已经易主了。

发现只花两天,修复用了两个月

这个洞的时间线比漏洞本身还精彩。

2024年,PHP基金会做外部安全审计,就发现内存耗尽场景下有异常。但当时没人能想明白这玩意怎么被利用,线索一搁就是两年。据报道这问题在PHP里埋了大概22年。

转机是AI。安全公司Calif用GPT-5.6 Sol辅助研究,两天就独立发现了漏洞,还把利用链写了出来。卡兹克那句总结很传神:发现只花2天,修复用了两个月。

然后披露过程就乱套了。漏洞信息提前泄露,官方被迫提前扔出补丁。Calif自己还误发了一段演示视频,展示攻击代码在多个真实目标上跑通,视频副本在社交平台疯传。

更刺激的是,攻击者比补丁跑得还快。亚马逊威胁情报在官方补丁发布前4天就监测到了利用尝试。Cloudflare说漏洞公开前10小时已有数千次攻击。SOCRadar在一台暴露的攻击者服务器上翻出了针对PHP 8.4.26的现成利用工具和三个预筛脚本,专门筛哪些网站满足利用链的前置条件。Freebuf报道说利用尝试到了数百万次量级,目标是把中招的机器编进Mirai僵尸网络的一个变种。

不过到目前为止,这些尝试全都失败了。VulnCheck的判断是武器化难度比预期高,攻击者得摸清目标环境的具体配置才打得动。这个"全失败"能维持多久,没人敢打包票。

修复就一件事,但要做得干净

先说结论:升级PHP,没有第二条路。WAF、改配置、关功能这些手段,只能帮你争取时间,救不了命。

各分支的最低安全版本:8.2升到8.2.35,8.3升到8.3.36,8.4升到8.4.27,8.5升到8.5.12。如果你还在8.1或更早,官方已经停止维护,没有补丁,要么迁移,要么找发行版厂商要backport。

Ubuntu/Debian的升级命令长这样:

sudo apt-get update
sudo apt-get install --only-upgrade php8.3 php8.3-fpm php8.3-cli # 版本号按实际替换
sudo systemctl restart php8.3-fpm # mod_php 则 restart apache2

CentOS/RHEL系用dnf update 'php*',Docker环境别指望容器自己更新,得重建镜像再滚动发布。这里最容易漏的一步:升级完必须重启PHP-FPM或Apache,旧进程不会自己换新二进制。我见过不止一次"补丁装了、服务没重启、扫描器还在报"的乌龙。

实在没法立刻升级的,过渡期有三件事可以做。让WAF上虚拟补丁顶住,这是买时间的主力。php.ini里把session.upload_progress.enabled设为0,能掐断CVE-2026-109619的部分利用路径。PHP 8.5以上再把fatal_error_backtraces设为0。改完照样要重启。心里还要清楚:官方原话是,这些都不构成完整缓解。

升级完还得排查有没有已经失陷。几个常用动作:

# 最近7天新增或被改过的PHP文件
find /var/www/html -name "*.php" -mtime -7 -ls

# 常见webshell特征
grep -rn "eval.*base64_decode\|system(\|passthru(\|shell_exec(" /var/www/html --include="*.php"

# FPM日志里有没有异常的segfault或OOM
tail -n 100 /var/log/php8.3-fpm.log

说实话这几条命令给不了太多安全感。利用尝试从补丁前4天就开始了,真中招的机器,webshell未必长成教科书里的样子。文件完整性监控、进程行为告警这些平时嫌吵的东西,这种时候才知道值。

引擎级的洞,跟以前的洞不一样

这次最让我别扭的一点是:应用是无辜的。我们习惯了漏洞等于"哪行代码写错了",review代码、跑SAST就能心里有底。这回底在运行时下面。你代码写得再干净,PHP引擎自己漏了,一样一锅端。有点像当年log4j给Java生态上的一课:依赖的深度,就是攻击面的深度。

另一个信号更长期。PHP基金会说7月以来已经给15个漏洞编了CVE,还审了上百份错误或重复报告。AI把"发现"这一端压缩了,22年的老雷两天就能挖出来。但验证、修复、发布补丁这一端还是人肉,两个月起步。这个不对称只会越来越明显,以后"漏洞爆发"的频率和节奏,大概率是AI说了算。

写到这里,我自己博客服务器的PHP版本还没确认。响应头上看不出来,这事只能登服务器跑一句php -v。挺讽刺的,一个写了十几年Web的人,对自己服务器上跑着什么版本,第一反应居然是不知道。我先去确认了。你的生产环境如果还有PHP,趁今晚也看一眼吧。

You voted 4. Total votes: 1

添加新评论