Redaxo 媒体池存储型XSS漏洞披露 (CVE-2024-50803)

0 阅读3分钟

CVE-2024-50803: Redaxo 媒体池存储型XSS漏洞

项目标题与描述

本项目披露并记录了在 Redaxo 内容管理系统中发现的一个安全漏洞。Redaxo 是一个流行的开源 CMS,以其灵活性和对开发人员友好的架构而闻名。

在版本 5.18.0 之前的 Redaxo 中,mediapool(媒体池)功能存在一个存储型跨站脚本(Stored XSS) 漏洞。该漏洞允许具有足够权限(如管理员或内容编辑者)的攻击者通过上传特制的恶意 SVG 文件,在用户浏览器中执行任意脚本代码。

CVE ID: CVE-2024-50803
发现者: Praison (2024年9月)
漏洞状态: 已修复

功能特性

  • 漏洞详情: 清晰描述存储型XSS漏洞的触发位置(媒体池)与攻击向量(恶意SVG文件)。
  • 影响范围: 明确指出受影响版本为 < 5.18.0
  • 修复指引: 提供升级到已修复版本(5.18.0 或更高版本)的解决方案。
  • 参考资料: 包含官方 CVE 记录、Redaxo 发布版本链接以及详细的技术分析文章。
  • 风险评级: 适用于需要评估其 Redaxo 实例安全风险的安全团队和系统管理员。

安装指南

本项目为漏洞披露信息,无需安装。如需修复漏洞,请参考以下步骤:

  1. 确认当前版本: 登录 Redaxo 后台,在系统设置或 redaxo/src/core/version.php 文件中查看当前版本号。

  2. 备份环境: 在进行任何升级操作前,请务必备份您的网站文件与数据库。

  3. 升级 Redaxo: 根据您的安装方式:

    • 完整包: 从 Redaxo 官方发布页 下载 5.18.0 或更高版本,覆盖安装。
    • Composer: 运行 composer update redaxo/core 命令更新核心库。
  4. 验证修复: 升级后,确认版本已变为 5.18.0 或以上,并检查媒体池功能是否正常运行。

使用说明

漏洞复现(仅供安全测试)

此漏洞利用需拥有媒体池上传权限。以下是简化后的概念验证步骤:

  1. 创建恶意 SVG 文件(例如 xss.svg):

    <svg xmlns="http://www.w3.org/2000/svg">
      <script>alert('CVE-2024-50803: Stored XSS');</script>
    </svg>
    
  2. 登录 具有媒体池上传权限的 Redaxo 后台账户。

  3. 上传 xss.svg 文件到媒体池。

  4. 触发 漏洞:当任何用户访问包含该恶意 SVG 文件的页面(如媒体池预览、文章引用)时,JavaScript 代码将在其浏览器中执行。

修复建议

  • 立即升级: 将 Redaxo 更新至 5.18.0 或更高版本。
  • 临时措施(如无法立即升级):
    • 严格限制媒体池的上传权限,仅授予绝对信任的用户。
    • 在上传层或 Web 服务器层面(如 mod_security 规则)阻止 SVG 文件中 <script> 标签的代码。
  • 参考详情: 完整的技术分析文章可查阅:Medium Write-up

核心代码

以下是该漏洞相关的核心概念代码片段(非 Redaxo 源码),用于说明漏洞原理与修复逻辑。

漏洞示例:不安全的文件处理

// 漏洞环境中潜在的不安全代码逻辑(概念示例)
function unsafe_addMediaToPool($uploadedFile) {
    $filename = $uploadedFile['name'];
    $tmpPath = $uploadedFile['tmp_name'];
    $targetDir = "/var/www/redaxo/media/pool/";
    
    // 仅通过扩展名或 MIME 类型粗略验证
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    if (in_array(strtolower($ext), ['jpg', 'png', 'svg', 'gif'])) {
        // 将文件移动到媒体池,未对内容(如 SVG 中的脚本)进行净化
        move_uploaded_file($tmpPath, $targetDir . $filename);
        return "文件上传成功: " . $filename;
    }
    return "不支持的文件类型";
}

// 当用户请求渲染该文件时,浏览器会执行恶意脚本
function unsafe_renderMediaFile($filename) {
    // 直接将用户上传的文件内容输出到 HTML
    $filePath = "/var/www/redaxo/media/pool/" . $filename;
    if (file_exists($filePath)) {
        // 根据文件类型设置 Content-Type
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $filePath);
        finfo_close($finfo);
        header("Content-Type: " . $mime);
        // 直接输出文件原始内容,未进行任何清理
        readfile($filePath);
    }
}

修复方案:内容净化与安全响应头

// 修复后的安全处理逻辑(概念示例)
function safe_addMediaToPool($uploadedFile) {
    $filename = $uploadedFile['name'];
    $tmpPath = $uploadedFile['tmp_name'];
    $targetDir = "/var/www/redaxo/media/pool/";
    
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    if (strtolower($ext) === 'svg') {
        // 对 SVG 文件进行内容净化,移除潜在脚本标签
        $safeContent = sanitize_svg_content(file_get_contents($tmpPath));
        if ($safeContent === false) {
            return "SVG 文件包含恶意内容,已被阻止。";
        }
        file_put_contents($targetDir . $filename, $safeContent);
        return "SVG 文件已安全上传。";
    }
    // 其他文件类型处理逻辑...
}

function sanitize_svg_content($svgContent) {
    // 使用 HTML 解析库或正则表达式移除 <script> 标签、onclick 等事件处理器
    $svgContent = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $svgContent);
    $svgContent = preg_replace('/ on\w+="[^"]*"/i', '', $svgContent);
    return $svgContent;
}

// 输出时增加 Content-Security-Policy 响应头
function safe_renderMediaFile($filename) {
    header("Content-Security-Policy: script-src 'none'; object-src 'none'");
    // ... 其他输出逻辑
}

6HFtX5dABrKlqXeO5PUv/2gA9/fmz80szKgTbcq8vou2fHu2BzmJ43hLlOCqiYyS