Java 如何防止XXE攻击

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40649152/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:50:20  来源:igfitidea点击:

How to prevent XXE attack

javaxmlxml-parsingtransform

提问by SANNO

We had a security audit on our code, and it mentioned that our code is vulnerable to XML EXternal Entity (XXE) attacks.

我们对我们的代码进行了安全审计,它提到我们的代码容易受到 XML 外部实体 (XXE) 攻击。

Explanation

XML External Entities attacks benefit from an XML feature to build documents dynamically at the time of processing. An XML entity allows inclusion of data dynamically from a given resource. External entities allow an XML document to include data from an external URI. Unless configured to do otherwise, external entities force the XML parser to access the resource specified by the URI, e.g., a file on the local machine or on a remote system. This behavior exposes the application to XML External Entity (XXE) attacks, which can be used to perform denial of service of the local system, gain unauthorized access to files on the local machine, scan remote machines, and perform denial of service of remote systems.

The following XML document shows an example of an XXE attack.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>

This example could crash the server (on a UNIX system), if the XML parser attempts to substitute the entity with the contents of the /dev/random file.

Recommendation

The XML unmarshaller should be configured securely so that it does not allow external entities as part of an incoming XML document.

To avoid XXE injection do not use unmarshal methods that process an XML source directly as java.io.File, java.io.Readeror java.io.InputStream. Parse the document with a securely configured parser and use an unmarshal method that takes the secure parser as the XML source as shown in the following example:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(<XML Source>);
Model model = (Model) u.unmarshal(document);

解释

XML 外部实体攻击受益于在处理时动态构建文档的 XML 特性。XML 实体允许动态地包含来自给定资源的数据。外部实体允许 XML 文档包含来自外部 URI 的数据。除非另外配置,否则外部实体会强制 XML 解析器访问由 URI 指定的资源,例如本地机器或远程系统上的文件。此行为将应用程序暴露给 XML 外部实体 (XXE) 攻击,可用于执行本地系统拒绝服务、未经授权访问本地计算机上的文件、扫描远程计算机以及执行远程系统拒绝服务.

以下 XML 文档显示了 XXE 攻击的示例。

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>

如果 XML 解析器尝试用 /dev/random 文件的内容替换实体,则此示例可能会使服务器崩溃(在 UNIX 系统上)。

推荐

应该安全地配置 XML 解组器,以便它不允许外部实体作为传入 XML 文档的一部分。

为避免 XXE 注入,请勿使用将 XML 源直接处理为java.io.File,java.io.Reader或 的 解组方法java.io.InputStream。使用安全配置的解析器解析文档,并使用将安全解析器作为 XML 源的解组方法,如以下示例所示:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(<XML Source>);
Model model = (Model) u.unmarshal(document);

The code below is where the audit found the XXE attack:

下面的代码是审计发现 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);

How can I implement the above recommendation in my code? Where am I missing things?

如何在我的代码中实现上述建议?我在哪里错过了东西?

回答by Kayaman

You'll want to turn on the secure processing feature on the TransformerFactory. It will limit certain possibly malicious things from happening (DOS attacks etc.)

您需要在TransformerFactory. 它将限制某些可能的恶意事件的发生(DOS 攻击等)

TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = tf.newTransformer();

回答by Aaron Digulla

You can use the same approach with DocumentBuilderFactory:

您可以使用相同的方法DocumentBuilderFactory

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
...

To make everyone use this automatically, you need to create your own implementation (by extending the one which you're currenly using; use your debugger to find out). Set the feature in the constructor.

为了让每个人都自动使用它,您需要创建自己的实现(通过扩展您当前使用的实现;使用调试器找出答案)。在构造函数中设置特征。

Then you can pass the new factory to use in the System property javax.xml.parsers.DocumentBuilderFactoryto the Java VM and everyone will use it.

然后,您可以将要在 System 属性中使用的新工厂传递javax.xml.parsers.DocumentBuilderFactory给 Java VM,每个人都会使用它。

回答by Keerthikanth Chowdary

Because of large number of xml parsing engines in the market, the way to prevent XXE attacks differ from engine to engine. please refer to you engine documentation. The funda here is to prevent the external DOCTYPE declaration. If the external DOCTYPE declaration is needed then disabling external general entities and external parameter entities will prevent XXE attacks on your code. Below is the sample code to prevent XXE when using a SAX parser.

由于市场上的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;
 }
}

回答by beat

Note that using FEATURE_SECURE_PROCESSING alone seems not to be secure enough (from blackhat-pdf):

请注意,单独使用 FEATURE_SECURE_PROCESSING 似乎不够安全(来自blackhat-pdf):

... despite Oracle's recommendation XML parsers do not actually restrict external connections when FEATURE _SECURE_PROCESSING is enabled.

...尽管 Oracle 建议 XML 解析器在启用 FEATURE _SECURE_PROCESSING 时实际上并不限制外部连接。

OWASPrecommends ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_STYLESHEET.

OWASP推荐使用 ACCESS_EXTERNAL_DTD 和 ACCESS_EXTERNAL_STYLESHEET。

Together this would make:

这将使:

TransformerFactory trfactory = TransformerFactory.newInstance();
trfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");

Actually this question is a duplicate of: How to Prevent XML External Entity Injection on TransformerFactory

实际上这个问题是重复的:How to prevent XML External Entity Injection on TransformerFactory

回答by awsome

I did try with Java 8

我确实尝试过 Java 8

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>

And got the below exception:

并得到以下异常:

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.