PHP8.4高危漏洞:一行代码引发9.8分CVE

📅 2026/8/21 20:54:28
PHP8.4高危漏洞:一行代码引发9.8分CVE
导语: 从PHP 8.4起官方将库化放置到src树中, 然而在此新生的字符串转换函数里却遗漏了一行更新, 进而致使一个off-by-N的越界写漏洞直接浮现出CVE - 2026 - 17544, 其 CVSS 达到 9.8 分。仅仅一行PHP代码就能使任何运行于PHP 8.4.x 8.4.24 或者 8.5.x 8.5.9 的进程“stack ”。一、漏洞本质这个洞出在ext///src/.cPHP处理任意精度数学运算的扩展, 存在于某个函数里。通常这种扩展平时存在感不强, 然而只要是涉及金融计算的PHP服务, 或者是涉及密码学的PHP服务, 再或者是涉及区块链金额的PHP服务, 甚至是涉及电商订单金额的PHP服务, 都离不开它。漏洞利用者正是看准了这一点, 那就是你若敢拿它去处理用户输入, 我便敢让你的进程崩溃。当用户传入字符串操作数之际, PHP会率先将其转换成内部结构, 而漏洞所涉根因虽说起来简单, 却能令人气得想骂人, 此函数会做两件事情。将分数部分截断, 当用户所指定的scale精度比操作数的auto scale小时, 把那多出来的尾数部分予以砍掉。修剪尾部零 把整数部分末尾的0删掉让数字更紧凑。问题就出在第二步。代码长这样str_scale - fractional_end - fractional_new_end; // fractional_end NOT updated here ... bc_new_num_nonzeroed(digits, str_scale) // allocates SHORT (trimmed) buffer bc_copy_and_toggle_bcd(nptr, fractional_ptr, fractional_end) // copies UNTRIMMED length留意那一行注释, 它并未被进行更新, 其所指向的乃是原始的尚未被修剪的末尾位置, 而后便是下一步。(, )将缓冲区按照经过trim操作之后的短长度来进行分配, 紧接着, cd(nptr, , )这个操作却依据未经过trim操作的长长度来拷贝数据, 其结果便是, 有一段多出来的数据被写入到了缓冲区边界以外部位, 这属于典型的off - by - N缓冲区溢出情况。NVD给出了CWE - 787越界写的情况, 还给予了CVSS 9.8的评分。漏洞发现者乃是Recep Asan雷杰普·阿桑, 其ID是这样的, PoC作者是如此这般, 且公开仓库已然被放置在了上面。二、PoC下载与复现PoC仓库 //cve-2026-17544-poc仓库里的关键文件就一个 .php 不到50行$trigger 1. . 9 . str_repeat(0, 300) . 1; echo[*] bccomp(1.9 . str_repeat(0, 300) . 1, 0, 300)\n; $r bccomp($trigger, 0, 300); echo[] result: . var_export($r, true) . \n; echo[] PHP . PHP_VERSION . — NO CRASH (patched)\n;触发原理是, 第一参数构造出一个超长小数, 这个超长小 数是由 1.9 加上 300 个 0 再加上 1 组成的, scale 参数传递的是 300。auto scale 会计算为 301, 这里的 301 是 300 个 0 加上 1 得到的, 然而用户传递的 scale 是 300, 就此触发了截断逻辑。接着通过 trim 尾部零的循环计算得出可以删掉 300 个零, 但是, 仍然是指向未 trim 的位置 , 最终表现为拷贝长度等于实际分配的缓冲区长度再加上 300 字节, 进而导致栈/堆缓冲区溢出。复现命令 一行搞定# 漏洞版本 PHP 8.4.23 docker run --rm -v $PWD:/app -w /app php:8.4.23-cli sh -c \ docker-php-ext-install bcmath /dev/ 21 php trigger.php # 输出*** stack smashing detected ***退出码 133 (SIGABRT) # 已修复版本 PHP 8.4.24 docker run --rm -v $PWD:/app -w /app php:8.4.24-cli sh -c \ docker-php-ext-install bcmath /dev/ 21 php trigger.php # 输出int(1)退出码 0于2026年8月12日, 使用Pi 5arm64进行了实际测试, 针对三个版本8.4.23、8.5.8、8.4.24, 对比结果已完全明确, 即, 存有漏洞的版本必定崩溃进行修复后的版本不会崩溃。三、修复方案与原理8.4.24版本, 以及8.5.9版本, 这两个版本是在2026年7月30日发布的, 上游PHP团队在这两个版本里合入了一行修复:// 在原代码基础上加上 fractional_end fractional_new_end;就是仅这样的一行了使得能够在进行trim以后准确无误指向全新的末尾位置所在之处后续的cd会依据正确的括号所具有的长度去拷贝数据缓冲区的长度与之相匹配溢出的情况便随之消失不见了。同时提交了一个回归测试文件.ext目录下的tests文件夹中的GHSA - x692 - q9x7 - 8c3f.phpt文件。覆盖触发路径确保未来重构不会再出同样的bug。针对PHP 8.4的修复, 针对PHP 8.5的修复, 以及: GHSA-x692-q9x7-8c3f。四、危害评估进行PoC创作的人, 在其中给出了一个称得上冷静的对于威胁的评估, 这是值得每一个从事PHP运维工作的人仔细看明白并且弄清楚的。远程的那种具备直接可用性的DoS, 任何会将攻击者所控制的操作数或者scale传递给的服务, 都能够被确定无疑地导致崩溃。常见的引发这种情况的场景涵盖了:崩溃呈现出这样的表现: 开启了栈保护stack-的编译选项后会直接退出, 未开启该功能的二进制文件会悄然破坏保存在栈上的寄存器以及返回地址, 其行为是未定义的, 这有可能导致崩溃, 有可能执行奇特的路径, 有可能在某些架构环境下转变为RCE入口。RCE理论或许能行得通但未曾实际展示给公众看: 道理上经由堆布局调节优化这类行为去构成能够被掌控的RCE链条, 是存在可能性的, 然而却存在着两个既定且无法轻松逾越的限制情况:证明该概念的作者清楚明确表明“困难, 未曾进行演示”, 不要将它当作远程命令执行来使用 —— 起码当下并非如此 —— 然而也别因为这样就不当回事, 那些恶意破解者始终在对技术加以改进。五、缓解与检查清单1. 立即升级PHP2. 审计调用于你的PHP代码之中搜寻, 搜寻( 、bcadd( 、bcsub( 、bcmul( 、bcdiv( 、bcmod( 、bcpow( 、(这种函数调用, 以此确认传入的操作数以及scale参数是不是全部源自可信的源头。要是存在任何一条接纳HTTP/JSON/RPC输入的链路调用了这些函数, 那就马上进行修复。3. 监控stack 日志PHP - FPM模式会在输出, CLI模式也会在输出, 输出的内容是***stack ***。要把这个字符串添加到日志告警规则里, 任何与之相关的崩溃情况都表明被触发了。4. 容器/镜像基线官方镜像中的 php:8.4.x-cli , php:8.4.x-fpm , php:8.4.x- 系列均受此漏洞影响, 将所有8.4.x 和8.5.x 的镜像钉到补丁版本然后再进行build。六、总结有一个名为CVE - 2026 - 17544的漏洞, 它属于教科书般级别的那种因“少写一行代码”而引发的漏洞, 存在这样的指针, 在进行trim操作以后, 按道理是应该更新使其指向新的位置的, 可是开发者遗忘做这件事了, 进而导致缓冲区长度以及拷贝长度出现错位情况, 而这是自1972年C语言诞生开始便一直未曾改变过的一个陷阱。有意思的是, 这个洞在PHP 8.4进行相关变化之前压根不存在, 它是在重构全新代码的时候介入的崭新漏洞, 这再度证实了安全圈那句深入人心的老话, 新代码就等同于新漏洞, 这种变化使得代码在维护和升级方面变得更易操作了然而首次开展大规模重写就出现了一个CVSS 9.8的情况, 这也是一件颇具讽刺意味的事赶紧检查你的PHP版本。