XML External Entity 漏洞

Posted 信息安全club

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XML External Entity 漏洞相关的知识,希望对你有一定的参考价值。

 白首相知犹按剑——王维


XML External Entity(XXE)是Server side Request Forgery 的一种,本质上也是轻信了不安全的输入造成的漏洞。在2017年的OWASP TOP 10里它排名上升到第四位。



01

什么是XXE?


让我们以例子来看一下什么是XML外部实体(XXE),以下是一个普通的XML

XML External Entity 漏洞

有些XML文档包含system标识符定义的“实体”,在DOCTYPE头部标签中呈现。这些定义的’实体’能够访问本地或者远程的内容。比如,

XML External Entity 漏洞

在上面的代码中, XML外部实体 ‘entityex’ 被赋予的值为:file://etc/passwd。在解析XML文档的过程中,实体’entityex’的值会被替换为URI(file://etc/passwd)内容值(也就是passwd文件的内容)。 关键字’SYSTEM’会告诉XML解析器,’entityex’实体的值将从其后的URI中读取。因此,XML实体被使用的次数越多,越有帮助。

02

 XXE攻击


有了XML实体,关键字’SYSTEM’会令XML解析器从URI中读取内容,并允许它在XML文档中被替换。因此,攻击者可以通过实体将他自定义的值发送给应用程序,然后让应用程序去呈现。 简单来说,攻击者强制XML解析器去访问攻击者指定的资源内容(可能是系统上本地文件亦或是远程系统上的文件)。比如,下面的代码将获取系统上folder/file的内容并呈献给用户。

XML External Entity 漏洞


让我们用Acunetix维护的demo站点 http://testhtml5.vulnweb.com/演示一下。 访问 http://testhtml5.vulnweb.com/ 站点,点击 ‘Login’下面的 ‘Forgot Password’ 链接。注意观察应用程序怎样使用XML传输数据,过程如下图所示:

请求:

XML External Entity 漏洞

响应:

观察上面的请求与响应,我们可以看到,应用程序正在解析XML内容,接受特定的输入,然后将其呈现给用户。为了测试验证XML解析器确实正在解析和执行我们自定义的XML内容,我们发送如下的请求

修改后的请求和响应:

如上图所示,我们在上面的请求中定义了一个名为myentity、值为’testing’的实体。 响应报文清晰地展示了解析器已经解析了我们发送的XML实体,然后并将实体内容呈现出来了。 由此,我们可以确认,这个应用程序存在XXE漏洞。


03

 XXE防御


XXE会造成服务器上敏感数据的泄露,和潜在的服务器拒绝服务攻击。出现漏洞如何补救呢?XXE主要问题就是XML解析器解析了用户发送的不可信数据。然而,要去校验DTD(document type definition)中SYSTEM标识符定义的数据,并不容易,也不大可能。大部分的XML解析器默认对于XXE攻击是脆弱的。因此,最好的解决办法就是配置XML处理器去使用本地静态的DTD,不允许XML中含有任何自己声明的DTD。

比如下面的Java代码,通过设置相应的属性值为false,XML外部实体攻击就能够被阻止。因此,可将外部实体、参数实体和内联DTD 都被设置为false,从而避免基于XXE漏洞的攻击。 

以下代码来自OWASP

import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException; // catching unsupported features
 ...
  
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     String FEATURE = null;
     try {
       // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented
       // Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
       FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
       dbf.setFeature(FEATURE, true);
 
       // If you can't completely disable DTDs, then at least do the following:
       // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
       // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
       // JDK7+ - http://xml.org/sax/features/external-general-entities    
       FEATURE = "http://xml.org/sax/features/external-general-entities";
       dbf.setFeature(FEATURE, false);
 
       // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
       // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
       // JDK7+ - http://xml.org/sax/features/external-parameter-entities    
       FEATURE = "http://xml.org/sax/features/external-parameter-entities";
       dbf.setFeature(FEATURE, false);
 
       // Disable external DTDs as well
       FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
       dbf.setFeature(FEATURE, false);
 
       // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
       dbf.setXIncludeAware(false);
       dbf.setExpandEntityReferences(false);
  
       // And, per Timothy Morgan: "If for some reason support for inline DOCTYPEs are a requirement, then 
       // ensure the entity settings are disabled (as shown above) and beware that SSRF attacks
       // (http://cwe.mitre.org/data/definitions/918.html) and denial 
       // of service attacks (such as billion laughs or decompression bombs via "jar:") are a risk."
 
       // remaining parser logic
       ...
       } catch (ParserConfigurationException e) {
             // This should catch a failed setFeature feature
             logger.info("ParserConfigurationException was thrown. The feature '" +
                 FEATURE + "' is probably not supported by your XML processor.");
             ...
         }
         catch (SAXException e) {
             // On Apache, this should be thrown when disallowing DOCTYPE
             logger.warning("A DOCTYPE was passed into the XML document");
             ...
         }
         catch (IOException e) {
             // XXE that points to a file that doesn't exist
             logger.error("IOException occurred, XXE may still possible: " + e.getMessage());
             ...
         }
       DocumentBuilder safebuilder = dbf.newDocumentBuilder();


以上是关于XML External Entity 漏洞的主要内容,如果未能解决你的问题,请参考以下文章

译Attacking XML with XML External Entity Injection (XXE)

XXE外部实体注入(XML External Entity Injection)学习笔记

XXE: XML eXternal Entity Injection vulnerabilities

XML External Entity attack/XXE攻击

PHP解析xml文件是报错:I/O warning : failed to load external entity

XXE (XML External Entity Injection) :XML外部实体注入