XXE的防御规则(必须严格遵守否则存在XXE漏洞)

Java

使用XML库的Java应用程序特别容易受到XXE的攻击,因为大多数Java XML解析器的默认设置是启用XXE。要安全地使用这些解析器,您必须在您使用的解析器中显式禁用XXE。下面介绍如何在最常用的Java XML解析器中禁用XXE。

JAXP DocumentBuilderFactory,SAXParserFactory和DOM4J

DocumentBuilderFactory,SAXParserFactory和DOM4J XML Parsers可以使用相同的技术进行配置,以保护它们免受XXE的攻击。此处仅显示了DocumentBuilderFactory示例。JAXP DocumentBuilderFactory setFeature方法允许开发人员控制启用或禁用特定于实现的XML处理器功能。可以在工厂或基础XMLReader setFeature方法上设置这些功能。每个XML处理器实现都有自己的功能,用于管理DTD和外部实体的处理方式。

有关使用SAXParserFactory突出显示的示例代码段的语法,请查看此处

import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException; //捕获不支持的功能
 ...
  
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     字符串FEATURE = null;
     尝试{
       //这是主要的防守。如果不允许DTD(doctypes),则几乎所有XML实体攻击都会被阻止
       //仅限Xerces 2  -  http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
       FEATURE =“http://apache.org/xml/features/disallow-doctype-decl”;
       dbf.setFeature(FEATURE,true);
 
       //如果无法完全禁用DTD,那么至少要执行以下操作:
       // 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);
 
       //也禁用外部DTD
       FEATURE =“http://apache.org/xml/features/nonvalidating/load-external-dtd”;
       dbf.setFeature(FEATURE,false);
 
       //以及这些,根据Timothy Morgan的2014年论文:“XML Schema,DTD和Entity Attacks”
       dbf.setXIncludeAware(假);
       dbf.setExpandEntityReferences(假);
  
       //而且,根据蒂莫西·摩根的说法:“如果由于某种原因支持内联DOCTYPE是必需的,那么 
       //确保禁用实体设置(如上所示)并注意SSRF攻击
       //(http://cwe.mitre.org/data/definitions/918.html)并拒绝 
       //服务攻击(例如十亿笑或通过“jar:”减压炸弹)是一种风险。“
 
       //剩下的解析器逻辑
       ...
       } catch(ParserConfigurationException e){
             //这应该捕获一个失败的setFeature功能
             logger.info(“抛出了ParserConfigurationException。功能'”+
                 您的XML处理器可能不支持FEATURE +“'。”);
             ...
         }
         catch(SAXException e){
             //在Apache上,禁用DOCTYPE时应抛出此值
             logger.warning(“将DOCTYPE传递给XML文档”);
             ...
         }
         catch(IOException e){
             //指向不存在的文件的XXE
             logger.error(“发生IOException,XXE可能仍然可能:”+ e.getMessage());
             ...
         }
       DocumentBuilder safebuilder = dbf.newDocumentBuilder();

Xerces 1 特点

  • 不要设置包括外部实体此功能
    1
    false
  • 不要设置包括参数实体此功能
    1
    false
  • 不要设置包括外部的DTD 此功能
    1
    false

Xerces 2 特点

  • 通过设置禁止内联DTD 此功能
    1
    true
  • 不要设置包括外部实体此功能
    1
    false
  • 不要设置包括参数实体此功能
    1
    false
  • 不要设置包括外部的DTD 此功能
    1
    false

注意:上述防御需要Java 7更新67,Java 8更新20或更高版本,因为DocumentBuilderFactory和SAXParserFactory的上述对策在早期Java版本中被破坏,符合:CVE-2014-6517

XMLInputFactory(一个StAX解析器)

诸如XMLInputFactory之类的StAX解析器允许设置各种属性和功能。

要从XXE保护Java XMLInputFactory,请执行以下操作:

xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD,false); //这将完全禁用该工厂的DTD
xmlInputFactory.setProperty(“javax.xml.stream.isSupportingExternalEntities”,false); //禁用外部实体

的TransformerFactory

要从XXE保护javax.xml.transform.TransformerFactory,请执行以下操作:

TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,“”);
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET,“”);

验证器

要从XXE保护javax.xml.validation.Validator,请执行以下操作:

SchemaFactory factory = SchemaFactory.newInstance(“ http://www.w3.org/2001/XMLSchema ”);
Schema schema = factory.newSchema();
Validator validator = schema.newValidator();
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD,“”);
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA,“”);

在SchemaFactory

要保护来自XXE的javax.xml.validation.SchemaFactory,请执行以下操作:

SchemaFactory factory = SchemaFactory.newInstance(“ http://www.w3.org/2001/XMLSchema ”);
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD,“”);
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA,“”);
Schema schema = factory.newSchema(Source);

SAXTransformerFactory

要从XXE保护javax.xml.transform.sax.SAXTransformerFactory,请执行以下操作:

SAXTransformerFactory sf = SAXTransformerFactory.newInstance();
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,“”);
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET,“”);
sf.newXMLFilter(来源);

注意:使用以下XMLConstants需要JAXP 1.5,它在7u40和Java 8中添加到Java:

  • javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD
  • javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA
  • javax.xml.XMLConstants.ACCESS_EXTERNAL_STYLESHEET

XMLReader的

要从XXE保护Java org.xml.sax.XMLReader,请执行以下操作:

XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature(“ http://apache.org/xml/features/disallow-doctype-decl ”,true);
reader.setFeature(“ http://apache.org/xml/features/nonvalidating/load-external-dtd ”,false); //这可能不是严格要求的,因为根据前一行不应允许DTD。
reader.setFeature(“ http://xml.org/sax/features/external-general-entities ”,false);
reader.setFeature(“ http://xml.org/sax/features/external-parameter-entities ”,false);

SAXReader依靠

要从XXE保护Java org.dom4j.io.SAXReader,请执行以下操作:

saxReader.setFeature(“ http://apache.org/xml/features/disallow-doctype-decl ”,true);
saxReader.setFeature(“ http://xml.org/sax/features/external-general-entities ”,false);
saxReader.setFeature(“ http://xml.org/sax/features/external-parameter-entities ”,false);

根据测试,如果您缺少其中一个,您仍然可能容易受到XXE攻击。

SAXBuilder的

要从XXE保护Java org.jdom2.input.SAXBuilder,请执行以下操作:

SAXBuilder builder = new SAXBuilder();
builder.setFeature(“ http://apache.org/xml/features/disallow-doctype-decl ”,true);
builder.setFeature(“ http://xml.org/sax/features/external-general-entities ”,false);
builder.setFeature(“ http://xml.org/sax/features/external-parameter-entities ”,false);
Document doc = builder.build(new File(fileName));

JAXB Unmarshaller

由于javax.xml.bind.Unmarshaller解析XML并且不支持禁用XXE的任何标志,因此必须首先通过可配置的安全解析器解析不受信任的XML,生成源对象作为结果,并将源对象传递给解组。例如:

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature(“ http://xml.org/sax/features/external-general-entities ”,false);
spf.setFeature(“ http://xml.org/sax/features/external-parameter-entities ”,false);
spf.setFeature(“ http://apache.org/xml/features/nonvalidating/load-external-dtd ”,false);
Source xmlSource = new SAXSource(spf.newSAXParser()。getXMLReader(),new InputSource(new StringReader(xml)));
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(xmlSource);

XPathExpression

javax.xml.xpath.XPathExpression类似于Unmarshaller,它无法自行安全地配置,因此必须首先通过另一个安全的XML解析器解析不受信任的数据。例如:

DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();			
df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,“”); 
df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA,“”); 	
DocumentBuilder builder = df.newDocumentBuilder();
String result = new XPathExpression()。evaluate(builder.parse(new ByteArrayInputStream(xml.getBytes())));

java.beans.XMLDecoder中

此类中的readObject()方法从根本上说是不安全的。它解析的XML不仅受XXE的约束,而且该方法可用于构造任何Java对象,并执行此处所述的任意代码。除了信任或正确验证传入其中的输入之外,没有办法使用此类安全。因此,我们强烈建议完全避免使用此类,并将其替换为安全或正确配置的XML解析器,如本备忘单中的其他部分所述。

其他XML解析器

有许多第三方库直接或通过使用其他库来解析XML。请默认情况下测试并验证其XML解析器是否对XXE是安全的。如果默认情况下解析器不安全,请查找解析器支持的标志,以禁用所有可能的外部资源包含,如上面给出的示例。如果没有外部控件,请确保不受信任的内容首先通过安全解析器传递,然后传递给不安全的第三方解析器,类似于Unmarshaller的安全性。

Spring Framework MVC / OXM XXE漏洞

例如,在Spring OXMSpring MVC中发现了一些XXE漏洞。以下版本的Spring Framework容易受到XXE的攻击:

  • 3.0.0到3.2.3(Spring OXM和Spring MVC)
  • 4.0.0.M1(Spring OXM)
  • 4.0.0.M1-4.0.0.M2(Spring MVC)

还有其他问题稍后修复,因此为了完全解决这些问题,Spring建议您升级到Spring Framework 3.2.8+或4.0.2+。

对于Spring OXM,这指的是org.springframework.oxm.jaxb.Jaxb2Marshaller的使用。请注意,Spring OXM的CVE特别指出2个XML解析情况由开发人员决定是否正确,2是Spring的责任,并且已修复以解决此CVE问题。这是他们所说的:

开发人员必须处理两种情况
对于DOMSource,XML已经被用户代码解析,并且该代码负责防止XXE。
对于StAXSource,XMLStreamReader已经由用户代码创建,并且该代码负责防止XXE。
Spring修正的问题:

对于SAXSource和StreamSource实例,Spring默认处理外部实体,从而创建此漏洞。
以下是使用易受攻击的StreamSource的示例,但如果您使用的是固定版本的Spring OXM或Spring MVC,则现在是安全的:

 org.springframework.oxm.Jaxb2Marshaller marshaller = new org.springframework.oxm.jaxb.Jaxb2Marshaller();
 marshaller.unmarshal(new StreamSource(new StringReader(some_string_containing_XML)); //必须将返回Object强制转换为您要解组的任何类型

因此,根据Spring OXM CVE的说明,上面的内容现在是安全的。但是,如果您要使用DOMSource或StAXSource,那么您可以将这些源配置为从XXE安全。

.NET

以下有关.NET中XXE注入的信息直接来自Dean Fleming的单元测试Web应用程序:https//github.com/deanf1/dotnet-security-unit-tests。此Web应用程序涵盖了所有当前支持的.NET XML解析器,并为每个Web应用程序提供了测试用例,以证明它们何时不受XXE注入的影响。以前,这些信息是基于James Jardine出色的.NET XXE文章:https://www.jardinesoftware.net/2016/05/26/xxe-and-net/ 。它最初提供了比微软关于如何防止.NET中的XXE和XML拒绝服务的旧文章更新近和更详细的信息:http//msdn.microsoft.com/en-us/magazine/ee335713.aspx但是,它有一些Web应用程序涵盖的不准确之处。

下表列出了所有受支持的.NET XML解析器及其默认安全级别:

XML解析器安全默认?
LINQ to XML
XmlDictionaryReader
的XmlDocument
…在4.5.2之前没有
……版本4.5.2 +
XmlNodeReader对象
的XmlReader
XmlTextReader的
…在4.5.2之前没有
……版本4.5.2 +
的XPathNavigator
…在4.5.2之前没有
……版本4.5.2 +
XslCompiledTransform

LINQ to XML

默认情况下,System.Xml.Linq库中的XElement和XDocument对象都不受XXE注入的影响。XElement仅解析XML文件中的元素,因此DTD将被完全忽略。默认情况下,XDocument已禁用 DTD ,并且仅在使用不同的不安全XML解析器构造时才是不安全的。

XmlDictionaryReader

System.Xml.XmlDictionaryReader默认是安全的,因为当它尝试解析DTD时,编译器抛出一个异常,说“CData元素在XML文档的顶层无效”。如果使用不同的不安全XML解析器构造它会变得不安全。

的XmlDocument

在.NET Framework 4.5.2版之前,默认情况下System.Xml.XmlDocument是不安全的。XmlDocument对象中有一个XmlResolver对象,需要在4.5.2之前的版本中设置为null。在4.5.2及更高版本中,默认情况下此XmlResolver设置为null。以下示例显示了如何使其安全:

static void LoadXML()
{
  string xml =“<?xml version = \”1.0 \“?> <!DOCTYPE doc 
	[<!ENTITY win SYSTEM \“file:/// C:/Users/user/Documents/testdata2.txt \”>]
	> <DOC>&取胜; </ DOC>“;

  XmlDocument xmlDoc = new XmlDocument();
  xmlDoc.XmlResolver = null; //将此值设置为NULL会禁用DTD  - 默认情况下,它不为null。
  xmlDoc.LoadXml(XML);
  Console.WriteLine(xmlDoc.InnerText);
  到Console.ReadLine();
}

如果您使用默认或不安全设置创建自己的非空XmlResolver,XmlDocument可能会变得不安全。如果需要启用DTD处理,则在引用的MSDN文章中将详细介绍如何安全地执行此操作。

XmlNodeReader对象

System.Xml.XmlNodeReader对象默认是安全的,即使用不安全的解析器构造或包装在另一个不安全的解析器中,它也会忽略DTD。

的XmlReader

默认情况下,System.Xml.XmlReader对象是安全的。默认情况下,它们在.NET Framework 4.0及更早版本中将其ProhibitDtd属性设置为false,或者在.NET 4.0及更高版本中将其DtdProcessing属性设置为Prohibit。此外,在.NET 4.5.2及更高版本中,默认情况下,属于XmlReader的XmlReaderSettings的XmlResolver设置为null,这提供了额外的安全层。因此,如果DtdProcessing属性设置为Parse并且XmlReaderSetting的XmlResolver设置为具有默认或不安全设置的非空XmlResolver,则XmlReader对象仅在版本4.5.2及更高版本中变得不安全。如果需要启用DTD处理,则在引用的MSDN文章中将详细介绍如何安全地执行此操作。

XmlTextReader的

默认情况下,System.Xml.XmlTextReader 在4.5.2之前的.NET Framework版本中是不安全的。以下是如何在各种.NET版本中使其安全:

在.NET 4.0之前

在4.0之前的.NET Framework版本中,XmlReader对象(如XmlTextReader)的DTD解析行为由System.Xml.XmlReaderSettings和System.Xml.XmlTextReader类中的Boolean ProhibitDtd属性控制。将这些值设置为true可完全禁用内联DTD。

XmlTextReader reader = new XmlTextReader(stream);
reader.ProhibitDtd = true; //需要因为默认值为FALSE !!

.NET 4.0 – .NET 4.5.2

在.NET Framework 4.0版中,DTD解析行为已更改。不推荐使用ProhibitDtd属性,而是使用新的DtdProcessing属性。但是,它们没有更改默认设置,因此默认情况下XmlTextReader仍然容易受到XXE的攻击。如果XML中存在<!DOCTYPE>元素,则将DtdProcessing设置为Prohibit会导致运行时抛出异常。要自己设置此值,它看起来像这样:

XmlTextReader reader = new XmlTextReader(stream);
reader.DtdProcessing = DtdProcessing.Prohibit; //需要因为默认是Parse !!

或者,您可以将DtdProcessing属性设置为Ignore,这不会在遇到<!DOCTYPE>元素时引发异常,但只是跳过它而不处理它。最后,如果您想要允许和处理内联DTD,可以将DtdProcessing设置为Parse。

.NET 4.5.2及更高版本

在.NET Framework 4.5.2及更高版本中,默认情况下XmlTextReader的内部XmlResolver设置为null,这使得XmlTextReader默认忽略DTD。如果您使用默认或不安全设置创建自己的非空XmlResolver,则XmlTextReader可能会变得不安全。

的XPathNavigator

默认情况下, System.Xml.XPath.XPathNavigator 在4.5.2之前的.NET Framework版本中是不安全的。这是因为它实现了像XmlDocument这样的IXPathNavigable对象,这些对象在4.5.2之前的版本中默认也是不安全的。您可以通过在XPathDocument的构造函数中为XmlReader(默认情况下是安全的)提供安全的解析器来使XPathNavigator安全。这是一个例子:

XmlReader  reader  =  XmlReader 。Create (“example.xml” ); 
XPathDocument  doc  =  new  XPathDocument (reader ); 
XPathNavigator  nav  =  doc 。CreateNavigator ();  
string  xml  =  nav 。InnerXml 。ToString ();

XslCompiledTransform

System.Xml.Xsl.XslCompiledTransform(XML转换器)默认是安全的,只要它给出的解析器是安全的。默认情况下它是安全的,因为Transform()方法的默认解析器是XmlReader,默认情况下是安全的(如上所述)。这个方法的源代码在这里。一些Transform()方法接受XmlReader或IXPathNavigable(例如,XmlDocument)作为输入,如果传入不安全的XML Parser,则Transform也将是不安全的。

iOS版

libxml2的

iOS包含上面描述的C / C ++ libxml2库,因此如果您直接使用libxml2,则适用该指南。但是,通过iOS6提供的libxml2版本早于libxml2的2.9版本(默认情况下它可以防止XXE)。

NSXMLDocument

iOS还提供了一个NSXMLDocument类型,它建立在libxml2之上。但是,NSXMLDocument提供了一些针对XXE的额外保护,这些保护直接在libxml2中不可用。根据’NSXMLDocument外部实体限制API’部分:http//developer.apple.com/library/ios/#releasenotes/Foundation/RN-Foundation-iOS/Foundation_iOS5.html

  • iOS4及更早版本:默认情况下会加载所有外部实体。
  • iOS5及更高版本:仅加载不需要网络访问权限的实体。(更安全)

但是,要在任何版本的iOS中完全禁用NSXMLDocument中的XXE,您只需在创建NSXMLDocument时指定NSXMLNodeLoadExternalEntitiesNever。

PHP

根据PHP文档,在使用默认的PHP XML解析器时应设置以下内容以防止XXE:

libxml_disable_entity_loader(真);

有关如何在PHP中滥用此功能的说明,请参阅一篇很好的SensePost文章,该文章描述了在Facebook中修复的基于PHP的基于PHP的漏洞。

为您推荐

发表评论

电子邮件地址不会被公开。 必填项已用*标注

17 − 1 =