🔒 CVE-2025-64500:Symfony PATH_INFO 解析缺陷导致授权绕过漏洞
📋 项目概述
CVE-2025-64500 是一个影响广泛使用的 Symfony PHP 框架 的中等严重性漏洞。该漏洞源于 Symfony HTTP Foundation 组件对 URL 中 PATH_INFO 的解析存在缺陷,攻击者可利用特制 URL 绕过路由级别的访问控制,导致有限的授权绕过。
该项目旨在帮助开发者理解漏洞原理、评估影响范围,并快速修复或规避此安全问题,保障应用安全。
✨ 功能特性
- 漏洞深度解析 :详细说明
PATH_INFO解析缺陷的根本原因 - 影响范围清晰:明确列出受影响及已修复的组件版本
- 一键修复方案:提供 Composer 更新命令,快速应用安全补丁
- 多层防护指南:提供无法立即更新时的临时工作区和监控策略
- 风险等级评估:基于 CVSS 标准评估漏洞风险,便于确定优先级
🔧 安装与修复指南
系统要求
- 使用 Symfony 框架的 PHP 项目
- 包管理器:Composer
修复步骤
方法一:更新依赖包(推荐)
运行以下命令将 symfony/http-foundation 组件更新到安全版本:
bash
composer update symfony/http-foundation
方法二:检查并更新 Symfony 版本
确保你的 Symfony 版本已包含修复补丁:
symfony/http-foundation组件版本需 ≥ 7.1.2- 对于 Symfony 6.x LTS 版本,请检查是否有可用的向后移植补丁
临时防护措施
若无法立即更新,可采取以下临时措施:
- 自定义中间件 :添加中间件对
PATH_INFO进行严格校验和过滤 - Web 服务器层防护 :在 Nginx 或 Apache 中配置严格的 URL 重写规则,阻止可疑的
PATH_INFO格式 - 监控与日志 :增强对
PATH_INFO异常访问模式的日志记录与实时监控
📖 使用说明
验证修复是否成功
更新后,可通过以下方式验证漏洞是否已修复:
- 检查组件版本:
bash
composer show symfony/http-foundation
确保显示的版本号 ≥ 7.1.2 或为已修复的向后移植版本。
- 手动测试(仅限测试环境) : 尝试构造包含特殊
PATH_INFO的请求,访问原本需要特定权限的路由,确认是否被正确拦截。
漏洞检测示例
以下是一个简单的检测脚本示例(仅供安全测试使用):
php
<?php
// 检测示例:尝试构造可能触发漏洞的请求
$urls = [
'https://your-app.com/admin/section/../../public',
'https://your-app.com/api/secure/%2e%2e%2fprivate'
];
foreach ($urls as $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "URL: $url - HTTP Code: $httpCode\n";
}
// 若原本应返回 403 的 URL 返回了 200,则可能存在漏洞
?>
安全建议
- 及时更新:始终使用 Symfony 组件的最新稳定版本
- 最小权限原则:严格定义路由访问权限,避免过度宽松的规则
- 定期安全审计 :结合自动化工具检查已知漏洞(如使用
composer audit)
💻 核心代码分析
漏洞触发点示例
以下代码展示了受影响的 PATH_INFO 解析逻辑(简化示意):
php
<?php
// 漏洞核心:PATH_INFO 解析不充分
// 文件路径:symfony/http-foundation/Request.php
class Request
{
protected $pathInfo;
public function getPathInfo()
{
if (null !== $this->pathInfo) {
return $this->pathInfo;
}
// 漏洞点:直接从 PATH_INFO 服务器变量获取值,未进行充分过滤
$this->pathInfo = $this->prepareRequestUri();
// 缺少对路径遍历(如 ../)和 URL 编码(如 %2e)的严格检查
// 攻击者可通过构造 /admin/../public 绕过 /admin 的路由保护
return $this->pathInfo;
}
protected function prepareRequestUri()
{
// 从 $_SERVER['PATH_INFO'] 或类似来源获取
$requestUri = $_SERVER['PATH_INFO'] ?? '';
// 缺少安全过滤
return $requestUri;
}
}
修复补丁示例
官方修复补丁的核心改动(基于 Symfony 7.1.2):
php
<?php
// 修复后版本:增强 PATH_INFO 的安全处理
// 文件路径:symfony/http-foundation/Request.php (v7.1.2)
class Request
{
public function getPathInfo()
{
if (null !== $this->pathInfo) {
return $this->pathInfo;
}
$this->pathInfo = $this->prepareRequestUri();
// 新增:对路径进行安全规范化,防止路径遍历
$this->pathInfo = $this->normalizePath($this->pathInfo);
// 新增:检查并阻止包含危险字符的路径
if ($this->isMaliciousPath($this->pathInfo)) {
throw new AccessDeniedException('Malicious path detected.');
}
return $this->pathInfo;
}
protected function normalizePath($path)
{
// 实现路径规范化:移除重复斜杠、解析相对路径等
// 同时正确处理 URL 编码字符,防止 %2e%2e/ 等绕过
return $this->doNormalize($path);
}
protected function isMaliciousPath($path)
{
// 检测常见的路径遍历模式
$maliciousPatterns = ['/\.\./', '/%2e%2e/', '/%2e\//', '/\.%2e/'];
foreach ($maliciousPatterns as $pattern) {
if (preg_match($pattern, $path)) {
return true;
}
}
return false;
}
}
自定义防护中间件示例
若无法立即更新,可部署此中间件作为临时防护:
php
<?php
// 自定义 Symfony 中间件:严格过滤 PATH_INFO
namespace App\Middleware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class PathInfoSecurityMiddleware
{
public function handle(Request $request, callable $next)
{
$pathInfo = $request->getPathInfo();
// 检查路径遍历攻击特征
if (preg_match('/(\.\.|%2e|%2E)/i', $pathInfo)) {
// 记录可疑请求
$this->logSuspiciousRequest($request);
// 拒绝访问
throw new AccessDeniedHttpException('Invalid path format');
}
// 规范化路径
$normalizedPath = $this->secureNormalizePath($pathInfo);
// 如果路径被修改,创建一个新的请求对象
if ($normalizedPath !== $pathInfo) {
$request = $request->duplicate(null, null, null, null, null, [
'PATH_INFO' => $normalizedPath,
'REQUEST_URI' => str_replace($pathInfo, $normalizedPath, $request->getRequestUri())
]);
}
return $next($request);
}
private function secureNormalizePath(string $path): string
{
// 移除多余斜杠
$path = preg_replace('#/{2,}#', '/', $path);
// 解码 URL 编码后再检查
$decodedPath = urldecode($path);
if ($decodedPath !== $path && preg_match('/(\.\.|\.\/)/', $decodedPath)) {
// 包含危险字符,返回空路径或抛出异常
throw new AccessDeniedHttpException('Malicious path encoding detected');
}
return $path;
}
private function logSuspiciousRequest(Request $request): void
{
// 记录可疑请求的详细信息
$logData = [
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $request->getClientIp(),
'method' => $request->getMethod(),
'uri' => $request->getRequestUri(),
'path_info' => $request->getPathInfo(),
'user_agent' => $request->headers->get('User-Agent')
];
// 写入日志文件或发送到监控系统
error_log(json_encode($logData) . PHP_EOL, 3, '/var/log/symfony/path_info_attack.log');
}
}
🔗 参考链接
- Symfony 官方安全公告
- MITRE CVE 记录
- Symfony HTTP Foundation 组件文档FINISHED 6HFtX5dABrKlqXeO5PUv/84SoIo+TE3firf/5vX8AZ5duskFvgt+oJYZvirUBafd