XXE漏洞学习笔记

 

 

导读

1.XML基础知识

2.DTD基础知识-定义-内外DTD声明-优势

3.DTD基础知识-元素

4.DTD基础知识-实体-外部实体支持协议

5.XXE漏洞原理-有回显和无回显漏洞利用

6.其他危害-payload

7.检测和防御

 

1.XML基础知识

1.1XML定义:

XML 指可扩展标记语言(Extensible Markup Language)

XML 被设计用来传输存储数据。
HTML 被设计用来显示数据

XML把数据从HTML分离,XML是独立于软件和硬件的信息传输工具。
XML语言没有预定义的标签,允许作者定义自己的标签和自己的文档结构
1.2XML 文档构建模块
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
  • 元素
  • 属性
  • 实体
  • PCDATA
  • CDATA
下面是每个构建模块的简要描述。
1.3元素
元素是 XML 以及 HTML 文档的主要构建模块
HTML 元素的例子是 "body" 和 "table"。XML 元素的例子是 "note" 和 "message" 。元素可包含文本、其他元素或者是空的。空的 HTML 元素的例子是 "hr"、"br" 以及 "img"。
实例:
<body>body text in between</body>
<message>some message in between</message>
1.4属性
属性可提供有关元素的额外信息
属性总是被置于某元素的开始标签中。属性总是以名称/值的形式成对出现的。下面的 "img" 元素拥有关于源文件的额外信息:

元素的名称是 "img"。属性的名称是 "src"。属性的值是 "computer.gif"。由于元素本身为空,它被一个 " /" 关闭
1.5实体引用:
在 XML 中,一些字符拥有特殊的意义。
如果您把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。
这样会产生 XML 错误:
< 1000 then</message>
为了避免这个错误,请用实体引用来代替 "<" 字符
当文档被 XML 解析器解析时,实体就会被展开。
注释:在 XML 中,只有字符 "<" 和 "&" 确实是非法的。大于号是合法的,但是用实体引用来代替它是一个好习惯。

1.6PCDATA

PCDATA 的意思是被解析的字符数据(parsed character data)。
可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
文本中的标签会被当作标记来处理,而实体会被展开。
不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &amp;、&lt; 以及 &gt; 实体来分别替换它们。

1.7CDATA

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

CDATA 是不会被解析器解析的文本

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

1.8XML的语法规则:

XML 文档必须有一个根元素
XML 元素都必须有一个关闭标签
XML 标签对大小敏感
XML 元素必须被正确的嵌套
XML 属性值必须加引导
<!--自定义的4个子元素,即girl对象的属性-->
<eye>大眼睛</eye>
<face>可爱的脸庞</face>
<summary>可爱美丽的女孩</summary>
<!--根元素的闭合-->

1.9XML 中的注释

在 XML 中编写注释的语法与 HTML 的语法很相似:

<!-- This is a comment --> 

 

2.DTD基础知识-定义-内外DTD声明-优势

2.1DTD (Document Type Definition)文档类型定义

DTD(文档类型定义)的作用是定义XML文档的合法构建模块
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

上述XML代码基本分为三个部分:

第一部分是XML的声明;

第二部分是XML的DTD文档类型定义

第三部分是XML语句

而外部实体攻击主要利用DTD的外部实体来进行注入的。

DTD有两种构建方式,分别为内部DTD声明外部DTD声明

2.2内部DTD声明:
<!DOCTYPE 根元素 [元素声明]>

实例:如上述代码

2.3外部DTD声明

假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
 
这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD: (在 IE5 中打开,并选择“查看源代码”命令。)

这是包含 DTD 的 "note.dtd" 文件:

2.4引用公共DTD(了解)

示例:

命名方法:以!DOCTYPE开始,configuration是文档根元素名称;
PUBLIC表示是公共DTD;-表示是非ISO组织;mybatis.org表示组织;
DTD 表示类型;Config 表示标签;3.0是标签后附带的版本号;
EN表示DTD语言是英语;最后是DTD的URL;
2.5为什么使用 DTD?
通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述。
通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
而您的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
您还可以使用 DTD 来验证您自身的数据。

 

3. DTD基础知识-元素

3.1 声明一个元素

在 DTD 中,XML 元素通过元素声明来进行声明。元素声明使用下面的语法:

或者 

3.2 空元素

空元素通过类别关键词EMPTY进行声明:

例子:

XML例子:

3.3只有 PCDATA 的元素

只有 PCDATA 的元素通过圆括号中的 #PCDATA 进行声明:

<!ELEMENT 元素名称 (#PCDATA)>
例子:
<!ELEMENT from (#PCDATA)>

3.4带有子元素(序列)的元素 

带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:

或者

例子:

当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素。"note" 元素的完整声明是:

 

4.DTD基础知识-实体-外部实体支持协议

4.1简介

实体是用于定义引用普通文本或特殊字符的快捷方式的变量。

实体引用是对实体的引用。

实体可在内部或外部进行声明。

4.2分类

XML 中的实体分为以下五种:字符实体,命名实体,外部实体,参数实体,内部实体,普通实体和参数实体都分为内部实体和外部

实体两种,外部实体定义需要加上 SYSTEM关键字,其内容是URL所指向的外部文件实际的内容。如果不加SYSTEM关键字,则为内部实体,表示实体指代内容为字符串。
4.3有回显信息的测试代码

注意:libxml2.9.1及以后,默认不解析外部实体。测试的时候window下使用的是php5.2(libxml Version 2.7.7 ), php5.3(libxml Version 2.7.8)。Linux中需要将libxml低于libxml2.9.1的版本编译到PHP中,可以使用phpinfo()查看libxml的版本信息。 
4.4字符实体
指用十进制格式(&#aaa;)或十六进制格式(&#xaaa;)来指定任意 Unicode 字符。对 XML 解析器而言,字符实体与直接输入指定字符的效果完全相同。
比如:
%号要进行实体编码成&#x25;

4.5一个内部实体(也有叫命名实体的,把嵌套实体当做内部实体)声明

语法:

例子:

注释: 

一个实体由三部分构成:&符号, 实体名称, 分号 (;),这里&不论在GET还是在POST中都需要进行URL编码,因为是使用参数传入xml的,&符号会被认为是参数间的连接符号,示例:

4.6一个外部实体声明

语法:

例子:

上述代码中,XML的外部实体“xxe”被赋予的值为:file:///etc/passwd

当XML解析器解析xml文档是,会将URL中的值读出,并把读出内容替换掉xxe,变成file:///ect/passwd的内容。

默认协议

外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:

PHP拓展协议

 

 4.7参数实体声明

参数实体只用于 DTD 和文档的内部子集中,XML的规范定义中,只有在DTD中才能引用参数实体. 参数实体的声明和引用都是以百分号%。并且参数实体的引用在DTD是理解解析的,替换文本将变成DTD的一部分。该类型的实体用“%”字符(或十六进制编码的%)声明,并且仅在经过解析和验证后才用于替换DTD中的文本或其他内容:
语法

示例

外部evil.dtd中的内容。

可以看到win.ini中的敏感文件都已经被读取出来

 

参数实体xxe中包含外部实体的声明,用于替代<foo>标签中的实体引用参数。

这里,一定要注意流程,参数实体在DTD中解析是优先于XML文本中的内部实体解析。
参数实体有几个特性,这几个特性也决定了它能被利用的程度:
l  只能在DTD内部 
l  立即引用
l  实体嵌套 

 5.XXE漏洞原理-有回显和无回显漏洞利用

5.1 XXE漏洞简介

XXE漏洞全称XML External Entity Injection 即xml外部实体,

从安全角度理解成XML External Entity attack 外部实体注入攻击。

XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件和代码,造成任意文件读取、命令执行、内网端口扫描、攻击内网网站、发起Dos攻击等危害。
内网探测和入侵是利用xxe中支持的协议进行内网主机和端口发现,可以理解是使用xxe进行SSRF的利用,基本上啥都能做了:-)

近期看到OWASP TOP 10 2017 版中添加了XXE的内容便对XXE的一些知识进行梳理和总结,XXE可以使用例如http,file等协议,所以可以利用支持的协议进行内网探测和内网入侵,这部分的内容后续在SSRF中补充。

要点:libxml2.9.1及以后,默认不解析外部实体。测试的时候window下使用的是php5.2(libxml Version 2.7.7 ), php5.3(libxml Version 2.7.8)。Linux中需要将libxml低于libxml2.9.1的版本编译到PHP中,可以使用phpinfo()查看libxml的版本信息。

参考链接:
http://vulhub.org/#/environments/php_xxe/

5.2测试源码

有回显有报错测试代码:

无回显无报错测试代码:

 

5.3使用DTD的利用方式

一般xxe利用分为两大场景:有回显和无回显。有回显的情况可以直接在页面中看到Payload的执行结果或现象,无回显的情况又称为blind xxe,可以使用外带数据通道提取数据。

1. 有回显情况:

有回显的情况可以使用如下的两种方式进行XXE注入攻击。

外部实体声明

参数实体声明

外部evil.dtd中的内容。

 

 

2. 无回显的情况:

可以使用外带数据通道提取数据,先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)xxx.xxx.xxx。

 

evil.dtd的内容,内部的%号要进行实体编码成 &#x25;

有报错直接查看报错信息。 

无报错需要访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据。

 

6.其他危害

6.1DDOS
<!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 实体具体还有 “lol” 字符串,然后一个 lol2 实体引用了 10 次 lol 实体,一个 lol3 实体引用了 10 次 lol2 实体,此时一个 lol3 实体就含有 10^2 个 “lol” 了,以此类推,lol9 实体含有 10^8 个 “lol” 字符串,最后再引用lol9。

待补充

7.防御

漏洞检测
1)观察请求中是否存在 Content-Type为xml相关的数据包,以及是否发送xml请求数据,则程序后端很大概率存在xml解析逻辑
2)业务上传xml文件数据的请求接口,可通过上传含外部实体加载的POC去验证是否存在漏洞

漏洞防御
主要介绍Java和php的通用防御方式。
1)Java

  • dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true); //禁用DTD (doctypes),几乎可以防御所有XXE攻击
  • 如果不能禁用DTD,可以使用下两项,必须两项同时存在
  • bf.setFeature("http://xml.org/sax/features/external-general-entities",false); //防止外部普通实体POC 攻击
  • dbf.setFeature("http://xml.org/sax/features/external-parameter-entities",false); //防止外部参数实体POC攻击

2)php
libxml_disable_entity_loader(true); //禁止加载外部实体

 

 

 

 

 

 

 

posted @ 2019-08-24 20:15  汉广5651552  阅读(594)  评论(0编辑  收藏  举报