作者:Drunkbaby
原文地址:https://www.freebuf.com/articles/web/330086.html
前置知识
XML 定义实体
XML 实体允许定义在分析 XML 文档时将由内容替换的标记,这里我的理解就
是定义变量,然后赋值的意思一致。
就比如一些文件上传的 payload 中就会有。
XML 文档有自己的一个格式规范,这个格式规范是由一个叫做 DTD(document type definition) 的东西控制的,他就是长得下面这个样子
//这一行是 XML 文档定义
上面这个 DTD 就定义了 XML 的根元素是 message,然后跟元素下面有一些子元素,那么 XML 到时候必须像下面这么写
Myself
Someone
This is an amazing book
而我们必须在 DTD 中创建一个实体,DTD 也就是定义文档类型的文件,一般来说都有
一旦解析器处理了 XML 文档,它将用定义的常量“Jo Smith”替换定义的实体&js
大多数情况下,框架会根据 xml 结构自动填充 Java 对象。
通俗一点自己写一段代码的话
示例代码:
]>
这里 定义元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体(这是我们在这篇文章中第一次看到实体的真面目,实体其实可以看成一个变量,到时候我们可以在 XML 中通过 & 符号进行引用),那么 XML 就可以写成这样
示例代码:
&xxe;
mypass
我们使用 &xxe 对 上面定义的 xxe 实体进行了引用,到时候输出的时候 &xxe 就会被 "test" 替换。
什么是 XXE
个人认为,XXE 可以归结为一句话:构造恶意 DTD
介绍 XXE 之前,我先来说一下普通的 XML 注入,这个的利用面比较狭窄,如果有的话应该也是逻辑漏洞。
既然能插入 XML 代码,那我们肯定不能善罢甘休,我们需要更多,于是出现了 XXE。
XML 外部实体注入,全称为 XML external entity injection,某些应用程序允许 XML 格式的数据输入和解析,可以通过引入外部实体的方式进行攻击。
我们之前在0x01当中所讲的例子均为内部实体,但是实体实际上可以从外部的 dtd 文件中引用,我们看下面的代码:
示例代码:
]>
&xxe;
mypass
这样对引用资源所做的任何更改都会在文档中自动更新,非常方便(
方便永远是安全的敌人
)
当然,还有一种引用方式是使用 引用
公用 DTD
的方法,语法如下:
DTD标识名” “公用DTD的URI”>
这个在我们的攻击中也可以起到和 SYSTEM 一样的作用
重点二:
我们上面已经将实体分成了两个派别(内部实体和外部外部),但是实际上从另一个角度看,实体也可以分成两个派别(通用实体和参数实体),别晕。。
1.通用实体
用 &实体名; 引用的实体,他在DTD 中定义,在 XML 文档中引用
示例代码:
]>
Joe
&file;
...
2.参数实体:
(1)使用% 实体名(这
里面空格不能少
)
在 DTD 中定义,并且
只能在 DTD 中使用
%实体名;
引用
(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用
示例代码:
">
%an-element; %remote-dtd;
参数实体在我们 Blind XXE 中起到了至关重要的作用
XXE 的危害
-
1.像上文那个 file://xxx 的,很明显可以造成敏感数据泄露。
-
2.可以利用 XXE 执行 SSRF 攻击。
-
3.利用盲 XXE 将泄露数据外带;通过报错信息检索数据。
-
4.XXE 与文件上传结合,造成 getshell。
我们后续慢慢看 XXE 的危害。
XXE 几种攻击方式学习
1. 通过 File 协议进行文件读取
示例代码:
]>
Joe
&file;
...
这里的 firstname 以及 lastname 都是在 XML 文件中解析的,我们尝试自己构造 payload 的话可以是这样
]>
&test;
test -> "file:///etc/passwd" 通俗易懂
我们依靠一道靶场来加强一下感受
##### Lab: Exploiting XXE using external entities to retrieve files
进入靶场之后,先点击任意一个商品 - "view details",再 Check stock 并抓包。
这里的 productId 以及 storeId 是通过 XML 的形式传进来的,尝试通过 File 协议进行文件读取
payload:
]>
&test;
4
至于为什么会产生这个漏洞,如果想学习代码审计的师傅可以移步至我博客细究一下
代码审计XXE注入 | 芜风
(https://withd-raw.github.io/2022/04/18/WebGoat%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1-05-XXE%E6%B3%A8%E5%85%A5/
)
2. XXE 盲注
XXE 盲注的一般思路,需要使用第三方平台协助攻击。
(1) 基本盲注
以 Port 靶场为例。
##### Lab: Blind XXE with out-of-band interaction via XML parameter entities
payload:
%xxe; ]>
&xxe;
1
(2) 多个 DTD 的调用攻击
这里以 PHP 代码为例进行说明
xml.php
libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
?>
直接上 payload,并用 payload 加以理解
%remote;%int;%send;
]
这是我们对要进行渗透的 payload,有三个参数%remote, %int, %send;后面接的网站 http://ip/test.dtd 是我们挂在服务器/第三方网站的恶意 DTD。我们在这个第三方网站的恶意 DTD 中添加第二层恶意 DTD
test.dtd
接着,%int去调用 test.dtd 当中的 file,这里稍微慢一点,分析一下% int "
如此一来,%int 成为了这个网站的恶意 DTD,在 %int 里面定义了一个 %send 的变量名称。
由此,最后一个调用的参数%send就相当于我们在上面一个案例中的基础 payload
]>
&send;
这样,我们三层的 payload 经过抽丝剥茧,变成了一层简单的 payload。
接下来我们来看一道简单的 Port 靶场上的盲注
##### Lab: Exploiting blind XXE to exfiltrate data using a malicious external DTD
依旧是在 Stock 界面进行抓包,同样是 XML 形式
Port 里面的渗透测试是给我们第三方的服务器的,也就是 exploit server,但是在真正的渗透测试中,如果要测盲注的话,还是需要自己的服务器的。
按照之前的思路,进行多层恶意 DTD 的构造,并把这个恶意 DTD 挂在第三方服务器上面。
这里点 Store,因为存储之后,就等于你在你自己的服务器上面有了这个恶意的 DTD,一会儿复用即可。恶意 DTD 的 URL 我放在下面,每个人进靶场都是不一样的
成功,我们 exploit 的/etc/hostname在 GET 请求参数中
(3) 报错型盲注
evil.dtd