
CVE-2025-64500 是一个影响广泛使用的 Symfony PHP 框架 的中等严重性漏洞。该漏洞源于 Symfony HTTP Foundation 组件对 URL 中 PATH_INFO 的解析存在缺陷,攻击者可利用特制 URL 绕过路由级别的访问控制,导致有限的授权绕过。
该项目旨在帮助开发者理解漏洞原理、评估影响范围,并快速修复或规避此安全问题,保障应用安全。
PATH_INFO 解析缺陷的根本原因运行以下命令将 symfony/http-foundation 组件更新到安全版本:
composer update symfony/http-foundation确保你的 Symfony 版本已包含修复补丁:
symfony/http-foundation 组件版本需 ≥ 7.1.2若无法立即更新,可采取以下临时措施:
PATH_INFO 进行严格校验和过滤PATH_INFO 格式PATH_INFO 异常访问模式的日志记录与实时监控更新后,可通过以下方式验证漏洞是否已修复:
PATH_INFO 的请求,访问原本需要特定权限的路由,确认是否被正确拦截。以下是一个简单的检测脚本示例(仅供安全测试使用):
<?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,则可能存在漏洞
?>composer audit)以下代码展示了受影响的 PATH_INFO 解析逻辑(简化示意):
<?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
// 修复后版本:增强 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
// 自定义 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');
}
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。