We had a security audit on our code, and it mentioned that our code is vulnerable to XML EXternal Entity (XXE) attacks.
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.Reader
or
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);
The code below is where the audit found the XXE attack:
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?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…