Java 如何防止XXE攻击
我们对代码进行了安全审计,它提到我们的代码容易受到XML外部实体(XXE)攻击 解释 XML外部实体攻击利用XML功能在处理时动态构建文档。XML 实体允许动态包含来自给定资源的数据。外部实体允许XML文档包含数据 来自外部URI。除非配置为其他方式,否则外部实体将强制XML解析器访问指定的资源 通过URI,例如,本地计算机或远程系统上的文件。此行为将应用程序公开给外部XML 可用于对本地系统执行拒绝服务的实体(XXE)攻击会获得对本地系统上文件的未经授权访问 本地计算机、扫描远程计算机和执行远程系统的拒绝服务 以下XML文档显示了XXE攻击的示例Java 如何防止XXE攻击,java,xml,xml-parsing,transform,Java,Xml,Xml Parsing,Transform,我们对代码进行了安全审计,它提到我们的代码容易受到XML外部实体(XXE)攻击 解释 XML外部实体攻击利用XML功能在处理时动态构建文档。XML 实体允许动态包含来自给定资源的数据。外部实体允许XML文档包含数据 来自外部URI。除非配置为其他方式,否则外部实体将强制XML解析器访问指定的资源 通过URI,例如,本地计算机或远程系统上的文件。此行为将应用程序公开给外部XML 可用于对本地系统执行拒绝服务的实体(XXE)攻击会获得对本地系统上文件的未经授权访问 本地计算机、扫描远程计算机和执行远
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
以下代码是审计发现XXE攻击的地方:
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
System.out.println("outputing to : " + outputLocation);
File outputFile = new File(outputLocation);
StreamResult result = new StreamResult(outputFile);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
如何在代码中实现上述建议?我在哪里丢失了东西?您需要打开
TransformerFactory
上的安全处理功能。它将限制某些可能的恶意事件的发生(DOS攻击等)
您可以对
DocumentBuilderFactory
使用相同的方法:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
...
要让每个人都自动使用它,您需要创建自己的实现(通过扩展当前使用的实现;使用调试器来发现)。在构造函数中设置特性
然后,您可以将系统属性中使用的新工厂
javax.xml.parsers.DocumentBuilderFactory
传递给Java VM,每个人都会使用它。由于市场上有大量xml解析引擎,防止XXE攻击的方法因引擎而异。请参阅您的发动机文档。这里的基础是防止外部DOCTYPE声明。如果需要外部DOCTYPE声明,则禁用外部常规实体和外部参数实体将防止对代码的XXE攻击。下面是使用SAX解析器时防止XXE的示例代码
public class MyDocumentBuilderFactory{
public static DocumentBuilderFactory newDocumentBuilderFactory(){
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
try{
documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities",false);
documentBuilderFactory.setfeature("http://xml.org/sax/features/external-parameter-entities",false)
}catch(ParserConfigurationException exp){
exp.printStackTrace();
}
return documentBuilderFactory;
}
}
请注意,仅使用功能\u安全\u处理似乎不够安全(从: 。。。尽管Oracle推荐使用XML 当发生以下情况时,解析器实际上不会限制外部连接 特征 _安全处理 已启用 建议访问\u外部\u DTD和访问\u外部\u样式表 这将使:
TransformerFactory trfactory = TransformerFactory.newInstance();
trfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
实际上,这个问题是重复的:我确实尝试过Java8
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
感谢您的回复,是的,但我需要在现有逻辑中实现DocumentBuilderFactory。。。。顺便说一句,我使用了您给出的建议,但出现错误“类型转换器的方法setFeature(String,boolean)未定义”。呃,对不起,您需要在TransformerFactory中进行设置。谢谢Kayaman!它工作正常,但是您可以帮助用DocumentBuilderFactory概念替换TransformerFactory概念吗。真的会很可观。有人能帮忙吗?感谢任何人的帮助!OWASP提供了更多建议,并提供了良好的说明,不仅适用于Java:
TransformerFactory trfactory = TransformerFactory.newInstance();
trfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
Caused by: org.xml.sax.SAXParseException: External Entity: Failed to read external document 'logs', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.