php 8.5.5 不提供自动 ssrf 防护,需开发者在业务层显式实现白名单校验、协议限制、域名/ip 检查、url 归一化及跳转链验证等措施。

PHP 8.5.5 中 SSRF 防御不能靠框架自动解决
PHP 本身不内置 SSRF 防护机制,PHP 8.5.5 作为维护版本,只修复底层网络请求相关 bug(如 cURL 的 DNS 解析异常、file_get_contents() 对 URL 协议校验松动等),但不会自动拦截内网地址或过滤恶意 URL。所有 SSRF 防御逻辑必须由开发者在业务层显式实现。
用白名单限制 file_get_contents 和 cURL 目标协议与域名
绝大多数 SSRF 漏洞源于用户可控输入直接拼入 file_get_contents($url) 或 curl_setopt($ch, CURLOPT_URL, $url)。必须拒绝非预期协议和不可信域名:
- 只允许
https://和http://,明确禁止file://、gopher://、dict://、ftp://等高危协议 - 对域名做白名单匹配(不是简单字符串包含),例如用
parse_url()提取host,再比对预设数组:in_array($parsed['host'], ['api.example.com', 'cdn.example.net']) - 禁止 IP 地址直连(包括
127.0.0.1、192.168.0.0/16、10.0.0.0/8),可用filter_var($ip, FILTER_VALIDATE_IP)+ip2long()判断是否为私有地址段 - 若必须支持动态域名,需配合 DNS 解析后校验 A 记录——但注意:DNS 解析本身可能被污染或劫持,不能单独依赖
警惕 URL 解析歧义和双重编码绕过
黑名单(如正则匹配 127\.0\.0\.1)在 PHP 8.5.5 下依然无效,因为底层 cURL 和 stream wrapper 遵循 RFC 标准解析,而 PHP 层字符串匹配无法覆盖所有合法变体:
-
127.1、0x7f000001、2130706433都会被解析为127.0.0.1,正则很难全覆盖 - 双重 URL 编码如
%252e%252e%252f(即../的二次编码)可能绕过 WAF,但 PHP 会自动解码一次;关键是要在parse_url()前先做urldecode()归一化,再校验 - 利用
@符号分隔的 URL(如http://attacker.com@127.0.0.1/admin)中,parse_url()默认提取的是attacker.com,但实际请求发往127.0.0.1—— 必须手动检查user和pass字段是否含可疑 host 片段
对用户输入的 URL 做强制重定向跳转验证(慎用)
某些场景下需允许任意外部 URL(如 OAuth 回调地址),但又怕 SSRF。此时可启用“跳转链验证”:
- 用
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)+CURLOPT_MAXREDIRS限制跳转次数 - 开启
CURLOPT_HEADERFUNCTION回调,逐跳记录Location响应头 - 最终目标必须落在白名单域名上,且中间跳转不能进入内网地址(每跳都需做 IP 段校验)
- 注意:该方法开销大、易被 302 循环攻击拖垮服务,仅适用于低频、可信度稍高的入口(如管理员配置项)
真正难防的不是单次请求,而是开发者把 $_GET['url'] 直接喂给 file_get_contents 还加个 allow_url_fopen=On —— 这种组合在 PHP 8.5.5 里依然畅通无阻,得靠代码审查卡死。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











