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 实例安全风险的安全团队和系统管理员。
安装指南
本项目为漏洞披露信息,无需安装。如需修复漏洞,请参考以下步骤:
-
确认当前版本: 登录 Redaxo 后台,在系统设置或
redaxo/src/core/version.php文件中查看当前版本号。 -
备份环境: 在进行任何升级操作前,请务必备份您的网站文件与数据库。
-
升级 Redaxo: 根据您的安装方式:
- 完整包: 从 Redaxo 官方发布页 下载 5.18.0 或更高版本,覆盖安装。
- Composer: 运行
composer update redaxo/core命令更新核心库。
-
验证修复: 升级后,确认版本已变为 5.18.0 或以上,并检查媒体池功能是否正常运行。
使用说明
漏洞复现(仅供安全测试)
此漏洞利用需拥有媒体池上传权限。以下是简化后的概念验证步骤:
-
创建恶意 SVG 文件(例如
xss.svg):<svg xmlns="http://www.w3.org/2000/svg"> <script>alert('CVE-2024-50803: Stored XSS');</script> </svg> -
登录 具有媒体池上传权限的 Redaxo 后台账户。
-
上传
xss.svg文件到媒体池。 -
触发 漏洞:当任何用户访问包含该恶意 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