https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXBuilder
使用XML库的Java应用程序特别容易受到XXE的攻击,因为大多数Java XML解析器的默认设置是启用XXE。要安全地使用这些解析器,您必须在您使用的解析器中显式禁用XXE。下面介绍如何在最常用的Java XML解析器中禁用XXE。
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 特点:
false
。false
。false
。Xerces 2 特点:
true
。false
。false
。false
。注意:上述防御需要Java 7更新67,Java 8更新20或更高版本,因为DocumentBuilderFactory和SAXParserFactory的上述对策在早期Java版本中被破坏,符合:CVE-2014-6517。
诸如XMLInputFactory之类的StAX解析器允许设置各种属性和功能。
要从XXE保护Java XMLInputFactory,请执行以下操作:
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD,false); //这将完全禁用该工厂的DTD
xmlInputFactory.setProperty(“javax.xml.stream.isSupportingExternalEntities”,false); //禁用外部实体
要从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,“”);
要保护来自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);
要从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:
要从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);
要从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攻击。
要从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));
由于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);
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())));
此类中的readObject()方法从根本上说是不安全的。它解析的XML不仅受XXE的约束,而且该方法可用于构造任何Java对象,并执行此处所述的任意代码。除了信任或正确验证传入其中的输入之外,没有办法使用此类安全。因此,我们强烈建议完全避免使用此类,并将其替换为安全或正确配置的XML解析器,如本备忘单中的其他部分所述。
有许多第三方库直接或通过使用其他库来解析XML。请默认情况下测试并验证其XML解析器是否对XXE是安全的。如果默认情况下解析器不安全,请查找解析器支持的标志,以禁用所有可能的外部资源包含,如上面给出的示例。如果没有外部控件,请确保不受信任的内容首先通过安全解析器传递,然后传递给不安全的第三方解析器,类似于Unmarshaller的安全性。
Spring Framework MVC / OXM XXE漏洞
例如,在Spring OXM和Spring MVC中发现了一些XXE漏洞。以下版本的Spring Framework容易受到XXE的攻击:
还有其他问题稍后修复,因此为了完全解决这些问题,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中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 | 是 |
默认情况下,System.Xml.Linq库中的XElement和XDocument对象都不受XXE注入的影响。XElement仅解析XML文件中的元素,因此DTD将被完全忽略。默认情况下,XDocument已禁用 DTD ,并且仅在使用不同的不安全XML解析器构造时才是不安全的。
System.Xml.XmlDictionaryReader默认是安全的,因为当它尝试解析DTD时,编译器抛出一个异常,说“CData元素在XML文档的顶层无效”。如果使用不同的不安全XML解析器构造它会变得不安全。
在.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>“;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null; //将此值设置为NULL会禁用DTD - 默认情况下,它不为null。
xmlDoc.LoadXml(XML);
Console.WriteLine(xmlDoc.InnerText);
到Console.ReadLine();
}
如果您使用默认或不安全设置创建自己的非空XmlResolver,XmlDocument可能会变得不安全。如果需要启用DTD处理,则在引用的MSDN文章中将详细介绍如何安全地执行此操作。
System.Xml.XmlNodeReader对象默认是安全的,即使用不安全的解析器构造或包装在另一个不安全的解析器中,它也会忽略DTD。
默认情况下,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文章中将详细介绍如何安全地执行此操作。
默认情况下,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可能会变得不安全。
默认情况下, 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 ();
System.Xml.Xsl.XslCompiledTransform(XML转换器)默认是安全的,只要它给出的解析器是安全的。默认情况下它是安全的,因为Transform()方法的默认解析器是XmlReader,默认情况下是安全的(如上所述)。这个方法的源代码在这里。一些Transform()方法接受XmlReader或IXPathNavigable(例如,XmlDocument)作为输入,如果传入不安全的XML Parser,则Transform也将是不安全的。
iOS包含上面描述的C / C ++ libxml2库,因此如果您直接使用libxml2,则适用该指南。但是,通过iOS6提供的libxml2版本早于libxml2的2.9版本(默认情况下它可以防止XXE)。
iOS还提供了一个NSXMLDocument类型,它建立在libxml2之上。但是,NSXMLDocument提供了一些针对XXE的额外保护,这些保护直接在libxml2中不可用。根据'NSXMLDocument外部实体限制API'部分:http://developer.apple.com/library/ios/#releasenotes/Foundation/RN-Foundation-iOS/Foundation_iOS5.html:
但是,要在任何版本的iOS中完全禁用NSXMLDocument中的XXE,您只需在创建NSXMLDocument时指定NSXMLNodeLoadExternalEntitiesNever。
根据PHP文档,在使用默认的PHP XML解析器时应设置以下内容以防止XXE:
libxml_disable_entity_loader(真);
有关如何在PHP中滥用此功能的说明,请参阅一篇很好的SensePost文章,该文章描述了在Facebook中修复的基于PHP的基于PHP的漏洞。