xxe漏洞总结
0x 01 基础知识
XML基础知识
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
XML语法规则如下:
- 所有的XML元素都必须有一个关闭标签
- XML标签对大小写敏感
- XML必须正确嵌套
- XML属性值必须加引号””
- 实体引用(在标签属性,以及对应的位置值可能会出现<>符号,但是这些符号在对应的XML中都是有特殊含义的,这时候我们必须使用对应html的实体对应的表示,比如<傅好对应的实体就是lt,>符号对应的实体就是gt)
- 在XML中,空格会被保留(案例如:
a空格B
,这时候a和B之间的空格就会被保留)
1 | <?xml version="1.0" encoding="UTF-8"?> //xml声明 |
XML DTD介绍
DTD文档类型定义,约束了xml文档的结构。拥有正确语法的XML被称为“形式良好”的XML,通过DTD验证约束XML是“合法”的XML。
示例代码:
1 | <?xml version="1.0"?>//这一行是 XML 文档定义 |
上面这个 DTD 就定义了 XML 的根元素是 message,然后跟元素下面有一些子元素,那么 XML 到时候必须像下面这么写
示例代码:
1 | <message> |
其实除了在 DTD 中定义元素(其实就是对应 XML 中的标签)以外,我们还能在 DTD 中定义实体(对应XML 标签中的内容)
示例代码:
1 | <?xml version="1.0" encoding="ISO-8859-1"?> |
这里 定义元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体(这是我们在这篇文章中第一次看到实体的真面目,实体其实可以看成一个变量,到时候我们可以在 XML 中通过 & 符号进行引用),那么 XML 就可以写成这样
示例代码:
1 | <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 | <?xml version="1.0" encoding="utf-8"?> |
注意:
直接读取php文件会报错,因为php文件里面有<>//等特殊字符,xml解析时候会当成xml语法来解析。这时候就分不清处哪个是真正的xml语句了,
直接利用file协议读取PHP文件,就会产生报错,那么需要base64编码来读取
3.2 无回显读取本地敏感文件(Blind OOB XXE)
- 攻击流程:
- 客户端发送payload 1给web服务器
- web服务器向vps获取恶意DTD,并执行文件读取payload2
- web服务器带着回显结果访问VPS上特定的FTP或者HTTP
- 通过VPS获得回显(nc监听端口)
我们选择使用外部DTD,在主机上编写一个dtd文件:
1 | <!ENTITY % file SYSTEM “PHP://filter/read=convert.base64-encode/resource=/etc/passwd”> |
Payload如下:
1 | <?xml version=”1.0” encoding=”utf-8” ?> |
我们先声明一个外部的DTD引用,然后再xml文档内容中引用外部DTD中的一般实体。
3.3 HTTP 内网主机探测
我们可以尝试读取 /etc/network/interfaces 或者 /proc/net/arp 或者 /etc/host
1 | /proc/net/fib_trie 路由树 |
利用http协议继续访问内网主机或者进行内网主机端口扫描
最后放一个payload集合:https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation/
参考资料: