XXE漏洞原理及实例分析
0x00 漏洞原理
1.背景知识
XML(eXtensible Markup Language)是一种标记语言,用于描述和传输结构化的数据和信息。它被设计用来在不同系统之间交换数据,并且可以在不同的应用程序中共享和解释。
在解析外部实体的过程中,XML解析器可以根据URL中指定的方案(协议)来查询各种网络协议和服务(DNS,FTP,HTTP,SMB等)。 外部实体对于在文档中创建动态引用非常有用,这样对引用资源所做的任何更改都会在文档中自动更新。 但是,在处理外部实体时,可以针对应用程序启动许多攻击。 这些攻击包括泄露本地系统文件,这些文件可能包含密码和私人用户数据等敏感数据,或利用各种方案的网络访问功能来操纵内部应用程序。 通过将这些攻击与其他实现缺陷相结合,这些攻击的范围可以扩展到客户端内存损坏,任意代码执行,甚至服务中断,具体取决于这些攻击的上下文。
2.基础知识
DTD(Document Type Definition)是一种用于定义 XML 文档结构和内容的语法规范。它是一种基于标记的语言,用于描述 XML 文档中可以包含的元素、属性、实体、数据类型以及它们之间的关系。DTD 可以确保 XML 文档遵循特定的结构和语义。
以下是 DTD 的一些关键概念和特点:
- 元素定义: DTD 允许定义 XML 文档中的元素,包括元素名称、内容类型(如文本、其他元素等)以及出现次数(一次、零次或多次等)。
- 属性定义: 可以定义元素可以包含的属性及其数据类型。属性定义允许指定是否必需、默认值等。
- 实体定义: 实体用于定义可重用的文本块或特殊字符,可以在 XML 文档中引用。有两种类型的实体:内部实体和外部实体。
- 内容模型: DTD 可以定义元素之间的关系,如顺序、选择和重复。这些定义构成了元素的内容模型。
- <!DOCTYPE> 声明: 用于将 DTD 与 XML 文档关联起来。在 XML 文档中,通常以 <!DOCTYPE> 声明的形式指定 DTD 的位置和名称。
DTD 的主要作用是确保 XML 文档遵循特定的结构和语义,使文档更加具有可预测性和一致性。然而,DTD 有一些限制,例如不支持数据类型验证和命名空间,因此在更复杂的场景下,通常会使用其他模式语言如 XML Schema 来进行更严格的验证和定义。
一个简单的 DTD 示例,定义了一个包含书籍信息的 XML 文档的结构:
<!DOCTYPE bookstore [
<!ELEMENT bookstore (book+)>
<!ELEMENT book (title, author, price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
这个 DTD 描述了 <bookstore> 元素包含多个 <book> 元素,每个 <book> 元素包含一个 <title> 元素、一个 <author> 元素和一个 <price> 元素。
除了在 DTD 中定义元素(其实就是对应 XML 中的标签)以外,我们还能在 DTD 中定义实体(对应XML 标签中的内容),毕竟 XML 中除了能标签以外,还需要有些内容是固定的。
2.1 内部实体
这里 定义元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体(这是我们在这篇文章中第一次看到实体的真面目,实体其实可以看成一个变量,到时候我们可以在 XML 中通过 & 符号进行引用),那么 XML 就可以写成这样
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "test" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>
我们使用 &xxe 对 上面定义的 xxe 实体进行了引用,到时候输出的时候 &xxe 就会被 "test" 替换。
2.2 外部实体
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/test.dtd" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>
2.3 通用实体
从另一个角度看,实体也可以分成两个派别(通用实体和参数实体)
用 &实体名; 引用的实体,他在DTD 中定义,在 XML 文档中引用
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE updateProfile [<!ENTITY file SYSTEM "file:///c:/windows/win.ini"> ]>
<updateProfile>
<firstname>Joe</firstname>
<lastname>&file;</lastname>
...
</updateProfile>
2.4 参数实体
(1)使用 % 实体名(这里面空格不能少) 在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用
(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用
<!ENTITY % an-element "<!ELEMENT mytag (subtag)>">
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd">
%an-element; %remote-dtd;
0x01 实例分析
1. CVE-2019-13990
分析完了,后续更新。
0xFF 参考文献
PortSwigger:https://portswigger.net/web-security/xxe
文章评论