PHP 8.2.35 仅修复 CVE-2026-109618 和 CVE-2026-109619 两个内核级 RCE 漏洞,与 curl 相关的 SSRF 属于业务代码层问题,需开发者主动校验 URL 协议、域名及 IP 范围,不能依赖版本升级自动防护。

PHP 8.2.35 本身不修复 curl 参数导致的 SSRF 漏洞。 它只修复了两个内核级 RCE 漏洞(CVE-2026-109618 和 CVE-2026-109619),和 curl 函数无关。SSRF 是业务代码层问题,必须由开发者自己控制参数、校验 URL、限制协议和域名。
为什么升级到 8.2.35 不能防 SSRF
SSRF 漏洞触发点在你写的代码里,比如直接把 $_GET['url'] 塞进 curl_exec() 或 file_get_contents()。PHP 内核不会替你判断这个 URL 是不是指向内网地址或敏感协议。8.2.35 的修复聚焦于内存管理缺陷,和网络请求逻辑完全隔离。
常见错误现象包括:
- 升级后仍能用
http://127.0.0.1:6379/info扫描本地 Redis -
gopher://或dict://协议依然可被利用 -
file:///etc/passwd仍可读取本地文件(取决于 open_basedir 等配置)
真正要改的是你的 curl 调用逻辑
不能依赖 PHP 版本自动过滤,必须显式约束输入。关键动作有:
立即学习“PHP免费学习笔记(深入)”;
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 用
parse_url()提取host和scheme,禁止gopher://、dict://、file://、php:// - 对
host做白名单或 CIDR 校验,拒绝127.0.0.1、192.168.0.0/16、10.0.0.0/8等私有网段 - 禁用
CURLOPT_FOLLOWLOCATION,防止跳转绕过初始校验 - 设置超时(
CURLOPT_TIMEOUT)和最大重定向次数(CURLOPT_MAXREDIRS)防资源耗尽 - 避免用
filter_var($url, FILTER_VALIDATE_URL)做唯一校验——它不检查协议危险性,也不解析 host
示例片段(仅示意校验逻辑):
$url = $_GET['url'] ?? '';
$parsed = parse_url($url);
if (!$parsed || !isset($parsed['scheme'], $parsed['host'])) {
die('Invalid URL');
}
if (!in_array($parsed['scheme'], ['http', 'https'], true)) {
die('Unsupported scheme');
}
if (filter_var($parsed['host'], FILTER_VALIDATE_IP) &&
ip_in_private_range($parsed['host'])) {
die('Private IP not allowed');
}
容易踩的坑:以为加了白名单就安全
真实攻击常绕过表面校验:
- DNS 重绑定:前端解析 A 记录是白名单域名,后端发起请求时 DNS 已变更为
127.0.0.1 - URL 编码混淆:
http://localhost%23@evil.com可能被parse_url()截断为localhost - IPv6 写法:
http://[::1]或http://[0:0:0:0:0:0:0:1]绕过 IPv4 检查 - 短域名别名:
http://localhost:8080和http://127.0.0.1:8080在 DNS 层可能等价
所以白名单必须配合反向 DNS 查询(gethostbyaddr() + gethostbyname() 循环验证)、禁用 CURLOPT_RESOLVE 、并启用 open_basedir(对 file://)等多层防御。
最复杂也最容易被忽略的一点:SSRF 防御不是“加个 if 判断”就能收工的事。它需要理解协议解析边界、DNS 生命周期、IP 表示多样性,以及你所用 HTTP 客户端(cURL / Guzzle / stream_context)各自的行为差异。一个没覆盖到的解析路径,就可能让整套校验失效。


















