XML实体扩展攻击

这里我们主要对CWE-776进行介绍。

漏洞说明

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

POC过程

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

<?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>

上述是1个DTD的定义,如果对XXE有所了解的话,就可以直接看出其端倪。
其中,我们使用ENTITY表示1个实体,其类似编程语言中的变量,例如:

<!ENTITY ZERO "A">

我们可以将其看成定义了1个变量ZERO,其内容为字符A。而调用的方式为"&实体名称;“,在这里为&ZERO;
最常见的就是HTML代码中的尖括号<,其可以表示为&lt;
在实体ZERO中包含1个字符A,其中实体名称ZERO用于表示长度的选择,其等价于2的0次幂,换句话说ZERO的长度为$20=1$。类似地,实体ONE引用了2次实体ZERO,因此XML解析器会将实体ONE展开为长度2,或者$21$。最终我们以实体FOUR进行结束,它将展开为$24=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,那么其将展开为$232$个字符长度。而在计算机系统中,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对象进行检查。

参考文章:

https://cwe.mitre.org/data/definitions/776.html
https://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-entity-expansion

若文章对您有帮助,请打赏1块钱。您的支持,可以让我分享更多精彩的文章。转载请注明来源


知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。