XML实体扩展攻击必知必会

简介: 在Web开发中,Web安全可能对很多人来说是件遥远的事情。但不得不承认,安全一直都在我们身边,它与开发的过程是形影不离。如果你公司的项目的应用需要使用到一些XML提交的数据,那么这篇文章很有必要看看。即使没有相关的项目,了解一下也无妨。如果你做过微信支付的相关开发,你会发现在微信支付中我们需要向对应的服务器提交一段XML的数据。而曾经就出现过这样1件事情,如下图所示:

引言

在Web开发中,Web安全可能对很多人来说是件遥远的事情。但不得不承认,安全一直都在我们身边,它与开发的过程是形影不离。

如果你公司的项目的应用需要使用到一些XML提交的数据,那么这篇文章很有必要看看。即使没有相关的项目,了解一下也无妨。

如果你做过微信支付的相关开发,你会发现在微信支付中我们需要向对应的服务器提交一段XML的数据。而曾经就出现过这样1件事情,如下图所示:


26.jpg


详情可以查阅官方说明

官方说明详情:

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5

而其中的安全隐患的主角是XXE,不是我们这里要说的XML实体扩展。 而对于XXE的文章,网上可以检索到的比较多,其中如下几篇是个人觉得写得比较好的:

什么是XML实体扩展

XML实体扩展是XML Entity Expansion的直译,它是利用DTD设计中XML实体存在的问题。其对应的安全分类为CWE-776,而XXE为CWE-611

CWE-776:

https://cwe.mitre.org/data/definitions/776.html

CWE-611:

https://cwe.mitre.org/data/definitions/611.html

一般情况下,系统的安全需要从多个维度进行保护。需要注意的是,有些时候XXE会跟其他的安全问题(例如这里的XML实体扩展)组合从而实现更大的安全隐患。

漏洞说明

我们可以根据DTD定义的结构生成XML文档,但是却没有正确的对递归的实体数量进行控制。如果在DTD中包含了大量嵌套或递归的实体,这将在解析时导致数据的急剧增长,从而触发拒绝服务。

下面我们通过1个简单的POC例子来进行说明。

POC过程

假设我们有这样1个DTD的文档定义,我们可以将其看成是1个XML的蠕虫:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE nodes [
  3.   <!ENTITY ZERO "A">
  4.   <!ENTITY ONE "&ZERO;&ZERO;">
  5.   <!ENTITY TWO "&ONE;&ONE;">
  6.   <!ENTITY THREE "&TWO;&TWO;">
  7.   <!ENTITY FOUR "&THREE;&THREE;">
  8. ]>
  9. <data>&FOUR;</data>

上述是1个DTD的定义,如果对XXE有所了解的话,就可以直接看出其端倪。

其中,我们使用ENTITY表示1个实体,其类似编程语言中的变量,例如:

  1. <!ENTITY ZERO "A">

我们可以将其看成定义了1个变量ZERO,其内容为字符A。而调用的方式为"&实体名称;",在这里为&ZERO;

最常见的就是HTML代码中的尖括号<,其可以表示为为&lt;

在实体ZERO中包含1个字符A,其中实体名称ZERO用于表示长度的选择,其等价于2的0次幂,换句话说ZERO的长度为$2^0=1$。类似地,实体ONE引用了2次实体ZERO,因此XML解析器会将实体ONE展开为长度2,或者$2^1$。最终我们以实体FOUR进行结束,它将展开为$2^4=16$个字符长度。

下面我们使用PHP的libxml2库进行解析:

<?php
$xml = <<<DOC
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nodes [
   <!ENTITY ZERO "A">
   <!ENTITY ONE "&ZERO;&ZERO;">
   <!ENTITY TWO "&ONE;&ONE;">
   <!ENTITY THREE "&TWO;&TWO;">
   <!ENTITY FOUR "&THREE;&THREE;">
]>
<data>&FOUR;</data>
DOC;
$value = simplexml_load_string($xml);
var_dump($value);
?>

结果发现PHP程序卡死了。

如果编写到实体THIRTYTWO,那么其将展开为$2^32$个字符长度。而在计算机系统中,1个字符在ASCII编码中等于1个字节,而1个字节的大小为1B,那么实体THIRYTWO将占用4GB的存储空间,换句话说就是要使用到4GB的内存。

2 ** 32 / (1024 * 1024 * 1024) = 4

可以看到,如果XML解析对其进行解析,那么递归的实体引用将允许攻击者以指数的方式展开数据,从而快速消耗所有系统的资源,引起DoS问题。

我们可以根据需要生成更多的数据,这里就不展开说明了。

漏洞解决方案

为了防止由于该漏洞引发的问题,我们可以进行如下的处理:

  • 在解析相关DTD的XML文档之前,对递归实体声明进行扫描,并对潜在危险的内容不执行。
  • 在解析过程中,可以使用XML解析器限制DTD实体的递归展开。

对于PHP语言,我们可以使用libxml_disable_entity_loader函数禁用实体的加载:

libxml_disable_entity_loader(true);

由于在PHP中并没有提供对应的检查机制,因此我们可以手动进行检查:

$dom = new DOMDocument;
$dom->loadXML($xml);
foreach ($dom->childNodes as $child) {
    if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
        throw new InvalidArgumentException(
            'Invalid XML: Detected use of illegal DOCTYPE'
        );
    }
}

另外在使用SimpleXML时,需要使用simplexml_import_dom函数对导入的DOMDocument对象进行检查。

相关文章
|
9月前
|
XML JavaScript 安全
XML( 可扩展编辑语言 ) —— DOM解析
XML( 可扩展编辑语言 ) —— DOM解析
58 2
|
9月前
|
XML 存储 设计模式
XML(可扩展编辑语言) —— DTD
XML(可扩展编辑语言) —— DTD
41 2
|
10月前
|
XML 存储 JSON
XML——可扩展标记语言
XML——可扩展标记语言 XML是被设计用来传输和存储数据(HTML是用来呈现数据的) XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标前,全都是自定义标签,用来表示一些数据。
|
12月前
|
XML Java 数据格式
深入理解Spring IOC之扩展篇(一)、自定义xml标签
深入理解Spring IOC之扩展篇(一)、自定义xml标签
73 0
|
XML SQL 安全
【BP靶场portswigger-服务端10】XML外部实体注入(XXE注入)-9个实验(全)(下)
【BP靶场portswigger-服务端10】XML外部实体注入(XXE注入)-9个实验(全)(下)
191 0
【BP靶场portswigger-服务端10】XML外部实体注入(XXE注入)-9个实验(全)(下)
|
XML JSON 安全
【BP靶场portswigger-服务端10】XML外部实体注入(XXE注入)-9个实验(全)(上)
【BP靶场portswigger-服务端10】XML外部实体注入(XXE注入)-9个实验(全)(上)
206 0
【BP靶场portswigger-服务端10】XML外部实体注入(XXE注入)-9个实验(全)(上)
|
XML 存储 JavaScript
Web阶段:第六章:XML可扩展标记语言
Web阶段:第六章:XML可扩展标记语言
101 0
Web阶段:第六章:XML可扩展标记语言
|
XML JavaScript 前端开发
可扩展标记语言-----XML
XML(Extensible Markup Language):可扩展标记语言 可扩展:标签都是自定义的。
76 0
可扩展标记语言-----XML
|
XML 安全 Java
网络安全-XXE(XML外部实体注入)原理、攻击及防御
网络安全-XXE(XML外部实体注入)原理、攻击及防御
366 0
网络安全-XXE(XML外部实体注入)原理、攻击及防御
|
XML JSON IDE
C#复杂XML反序列化为实体对象两种方式 (上)
C#复杂XML反序列化为实体对象两种方式
189 0
C#复杂XML反序列化为实体对象两种方式 (上)