HTML 过滤器需要做什么来防止 SVG 攻击?

信息安全 Web应用程序 xss html
2021-09-08 16:38:42

我最近了解到 SVG(可缩放矢量图形)图像为网络上的微妙攻击带来了许多机会。(参见下面的论文。)虽然 SVG 图像可能看起来像图像,但文件格式实际上可以包含 Javascript,它可以触发 HTML、Flash 或其他内容的加载或执行。因此,SVG 格式引入了新的潜在方法来尝试将恶意内容潜入网页或绕过 HTML 过滤器。

我正在编写一个 HTML 过滤器来清理用户提供的 HTML。我需要在我的 HTML 过滤器中做什么以确保 SVG 图像不能用于绕过我的过滤器?我需要阻止哪些 HTML 标记和属性?过滤 CSS 时我需要做什么吗?如果我想简单地阻止所有 SVG 图像,那么 SVG 可以通过哪些方式嵌入到 HTML 文档中?

参考:

另请参阅SVG 上传的漏洞利用或其他安全风险?(一个不同但相关的问题)和Mike Samuel 在其他地方的回答

3个回答

我是你链接的这篇论文的作者之一。我注意到,这个帖子中给出的一些建议是善意的,经过深思熟虑的,但并非 100% 正确。

例如,在处理通过<img>或 CSS 背景嵌入的 SVG 时,Opera 无法提供可靠的安全性。这是一个示例,只是为了好玩,我们创建了一个嵌入的 SVG <img>,其中包含一个 PDF,该 PDF 将打开一个skype:URL,然后调用您:

我们创建了 SVGPurifier - 一组扩展 HTMLPurifier 以处理 SVG 清理的规则。回到我们写这些规则的时候(如果你愿意,你可以拥有它们——让我知道,我会把它们放在 Github 上),我们测试的每个浏览器都以不同的方式处理 SVG。还强烈依赖于它的嵌入方式:内联、带<embed>/ <object><applet><img>、 SVG 中的 SVG、backgroundCSSlist-stylecontent...

事实证明,如果您的威胁模型主要涉及 XSS 及其他内容,那么在 SVG 中找到一个无害的子集是可能的。如果您的威胁模型还包括例如缓解 UI 重叠、侧通道、历史窃取攻击等等,它会变得更加困难。下面是一个有趣的片段,展示了我们如何使用非常模糊的 JavaScript URI 处理程序导致 XSS:http: //jsbin.com/uxadon

然后我们有内联 SVG。在我个人看来,这是 W3C/WHATWG 有史以来最糟糕的想法之一。允许 HTML5 文档中的 XML 文档,强制它们遵守 HTML5 解析规则等等……安全噩梦。这是内联 SVG 的一个引人入胜的示例,其中包含的 JavaScript 显示了您将要处理的内容:http: //pastebin.com/rmbiqZgd

为了不让整个事情最终陷入对 SVG 在安全/XSS 环境中的可怕程度的长叹中,这里有一些建议。如果您真的并且仍然想要/正在使用此 HTML 过滤器,请考虑执行以下操作:

  • 给我们一个公开的测试,在那里我们可以锤击那个东西。

  • 灵活设置您的规则,期待每天都有新的绕过。

  • 确保了解过滤内联 SVG 的含义。

  • 尝试看看 HTMLPurifier 方法是否是最好的。白名单,不要黑名单。

  • 不惜一切代价避免正则表达式。这不是使用正则表达式的地方。

  • 确保您的子集仅允许那些已在所有相关浏览器中测试安全问题的元素。还记得 SVG 键盘记录器吗?http://html5sec.org/#132

  • 研究已经发布的基于 SVG 的攻击,并准备好定期发现更多信息:http ://html5sec.org/?svg

我喜欢有人尝试构建一个经过适当维护甚至可以工作的 HTML+SVG 过滤器的想法,我非常乐意对其进行测试——正如我假设的许多其他人一样。但请注意:HTML 过滤已经非常困难了——而 SVG 只是给它增加了一个全新的难度。

据我所知,可以使用以下方式来引用 svg。

  1. <img src="http://example.com/some-svg.svg">
  2. 任何带有 css 样式的标签。例如style="background-image:url(http://example.com/some-svg.svg)
  3. 过滤扩展是不够的。HTTP 标头确定内容类型,而不是扩展名。文件.jpg可以作为 SVG 读取。因此,任何远程图像都是危险的。
  4. 您可以在网页中内联任何 XML 格式,包括 SVG。

即使您检查了上述所有项目,也不能确定没有 SVG 注入可能。您可能想要加入白名单而不是黑名单。

一个简单的方法是不允许用户生成的 HTML 出现在您的网站上。通过使用 [b]bold[/b] 之类的伪代码,您可以使用标签过滤掉任何内容,并确保只有您的代码可以制作 HTML 标签。如果您需要能够使用 < 和 > 符号,仍然需要做很多工作来防止 HTML 标记被使用,但这是一个更容易解决的问题。