Adding an "allow-xml-external-entity-expansion" property to the serialization config.
diff --git a/modules/core/src/flex/messaging/endpoints/AbstractEndpoint.java b/modules/core/src/flex/messaging/endpoints/AbstractEndpoint.java
index 27784fb..d773f1c 100644
--- a/modules/core/src/flex/messaging/endpoints/AbstractEndpoint.java
+++ b/modules/core/src/flex/messaging/endpoints/AbstractEndpoint.java
@@ -109,6 +109,8 @@
private static final String LEGACY_THROWABLE = "legacy-throwable";
private static final String LEGACY_BIG_NUMBERS = "legacy-big-numbers";
private static final String LEGACY_EXTERNALIZABLE = "legacy-externalizable";
+ private static final String ALLOW_XML_EXTERNAL_ENTITY_EXPANSION = "allow-xml-external-entity-expansion";
+
private static final String LOG_PROPERTY_ERRORS = "log-property-errors";
private static final String IGNORE_PROPERTY_ERRORS = "ignore-property-errors";
private static final String INCLUDE_READ_ONLY = "include-read-only";
@@ -276,6 +278,7 @@
serializationContext.legacyThrowable = serialization.getPropertyAsBoolean(LEGACY_THROWABLE, false);
serializationContext.legacyBigNumbers = serialization.getPropertyAsBoolean(LEGACY_BIG_NUMBERS, false);
serializationContext.legacyExternalizable = serialization.getPropertyAsBoolean(LEGACY_EXTERNALIZABLE, false);
+ serializationContext.allowXmlExternalEntityExpansion = serialization.getPropertyAsBoolean(ALLOW_XML_EXTERNAL_ENTITY_EXPANSION, false);
serializationContext.maxObjectNestLevel = (int)serialization.getPropertyAsLong(MAX_OBJECT_NEST_LEVEL, 512);
serializationContext.maxCollectionNestLevel = (int)serialization.getPropertyAsLong(MAX_COLLECTION_NEST_LEVEL, 15);
serializationContext.preferVectors = serialization.getPropertyAsBoolean(PREFER_VECTORS, false);
diff --git a/modules/core/src/flex/messaging/io/SerializationContext.java b/modules/core/src/flex/messaging/io/SerializationContext.java
index 7245160..24f5d78 100644
--- a/modules/core/src/flex/messaging/io/SerializationContext.java
+++ b/modules/core/src/flex/messaging/io/SerializationContext.java
@@ -41,7 +41,7 @@
public boolean restoreReferences;
public boolean supportRemoteClass;
public boolean supportDatesByReference; // Typically used by AMF Version 3 requests
-
+
/**
* Determines whether an ASObject is created by default for a type that is
* missing on the server, instead of throwing a server resource not found
@@ -76,10 +76,12 @@
// How deep level of nest object in the object graph that we support
public int maxObjectNestLevel = 512;
- // How deep levle of nest collection objects in the object graph that we support
+ // How deep level of nest collection objects in the object graph that we support
// Similarly like how many dimensional matrix that we support for serialization.
public int maxCollectionNestLevel = 15;
+ public boolean allowXmlExternalEntityExpansion = false;
+
/**
* In server-to-client serialization, determines whether Java Arrays and Lists
* should be serialized as Flash Vectors, rather than Flash Array, and Flex
@@ -225,6 +227,7 @@
context.deserializationValidator = deserializationValidator;
context.maxObjectNestLevel = maxObjectNestLevel;
context.maxCollectionNestLevel = maxCollectionNestLevel;
+ context.allowXmlExternalEntityExpansion = allowXmlExternalEntityExpansion;
context.preferVectors = preferVectors;
return context;
}
diff --git a/modules/core/src/flex/messaging/io/amf/AbstractAmfInput.java b/modules/core/src/flex/messaging/io/amf/AbstractAmfInput.java
index f6124b9..1ee3d12 100644
--- a/modules/core/src/flex/messaging/io/amf/AbstractAmfInput.java
+++ b/modules/core/src/flex/messaging/io/amf/AbstractAmfInput.java
@@ -82,7 +82,8 @@
return xml;
// Validation performed in XMLUtil#stringToDocument.
- return XMLUtil.stringToDocument(xml, !(context.legacyXMLNamespaces));
+ return XMLUtil.stringToDocument(xml, !(context.legacyXMLNamespaces),
+ context.allowXmlExternalEntityExpansion);
}
/**
diff --git a/modules/core/src/flex/messaging/io/amfx/AmfxInput.java b/modules/core/src/flex/messaging/io/amfx/AmfxInput.java
index 82a1fe5..9bb7caa 100644
--- a/modules/core/src/flex/messaging/io/amfx/AmfxInput.java
+++ b/modules/core/src/flex/messaging/io/amfx/AmfxInput.java
@@ -1049,7 +1049,8 @@
xml = unescapeCloseCDATA(xml);
// Validation performed in XMLUtil#stringToDocument.
- Object value = XMLUtil.stringToDocument(xml, !(context.legacyXMLNamespaces));
+ Object value = XMLUtil.stringToDocument(xml, !(context.legacyXMLNamespaces),
+ context.allowXmlExternalEntityExpansion);
setValue(value);
}
diff --git a/modules/core/src/flex/messaging/util/XMLUtil.java b/modules/core/src/flex/messaging/util/XMLUtil.java
index da3349e..9674a48 100644
--- a/modules/core/src/flex/messaging/util/XMLUtil.java
+++ b/modules/core/src/flex/messaging/util/XMLUtil.java
@@ -16,9 +16,9 @@
*/
package flex.messaging.util;
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
+import flex.messaging.MessageException;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -28,11 +28,9 @@
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
-
-import org.w3c.dom.Document;
-import org.xml.sax.InputSource;
-
-import flex.messaging.MessageException;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
/**
* Utility class for converting strings to XML documents and
@@ -59,7 +57,7 @@
*/
public static String documentToString(Document document) throws IOException
{
- String xml = null;
+ String xml;
try
{
@@ -99,7 +97,7 @@
*/
public static Document stringToDocument(String xml)
{
- return stringToDocument(xml, true);
+ return stringToDocument(xml, true, false);
}
/**
@@ -111,7 +109,7 @@
* is name-space aware
* @return Document
*/
- public static Document stringToDocument(String xml, boolean nameSpaceAware)
+ public static Document stringToDocument(String xml, boolean nameSpaceAware, boolean allowXmlExternalEntityExpansion)
{
ClassUtil.validateCreation(Document.class);
@@ -124,12 +122,15 @@
InputSource input = new InputSource(reader);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- // Disable local resolution of entities due to security issues
- // See: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
- factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
- factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
- factory.setXIncludeAware(false);
- factory.setExpandEntityReferences(false);
+ if(!allowXmlExternalEntityExpansion)
+ {
+ // Disable local resolution of entities due to security issues
+ // See: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
+ factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+ factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+ factory.setXIncludeAware(false);
+ factory.setExpandEntityReferences(false);
+ }
factory.setNamespaceAware(nameSpaceAware);
factory.setValidating(false);
diff --git a/resources/config/services-config.xml b/resources/config/services-config.xml
index fb87328..4d3a54b 100755
--- a/resources/config/services-config.xml
+++ b/resources/config/services-config.xml
@@ -282,6 +282,13 @@
max object nest limit can prevent a recursion stack overflow. By default, it is set to 512.
-->
<max-object-nest-level>512</max-object-nest-level>
+ <!--
+ Per default the expansion of external entities in xml is disabled for
+ security reasons. If you require them to be expanded, turn this option
+ to true. See also:
+ https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
+ -->
+ <allow-xml-external-entity-expansion>true</allow-xml-external-entity-expansion>
</serialization>
<!-- Optional. Use this to limit the client channel's connect attempt
to the specified time interval.