12 Java API for XML Processing (JAXP) Security Guide
The JDK and Java XML APIs have been improved over the years with various measures and tools that can help prevent applications from being exploited by XML-related attacks. This guide shows you how to use the secure processing features of Java API for XML Processing (JAXP) to safeguard your applications and systems.
See the java.xml module summary for more information.
Security Issues in XML Processing
XML processing can expose applications to certain vulnerabilities. Among the most prominent and well-known attacks are the XML External Entity (XXE) injection attack and the exponential entity expansion attack, also know as the XML bomb or billion laughs attack. These attacks can potentially cause serious damage to a system by denying its services or worse, lead to the loss of sensitive data.
You should evaluate your applications' requirements and operating environment to assess the level of potential threat, for example, whether or to what extent the applications are exposed to untrusted XML sources.
XML External Entity Injection Attack
The XML, XML Schema, and XSLT standards define a number of structures that enable the embedding of external content in XML documents through system identifiers that reference external resources. In general, XML processors resolve and retrieve almost all of these external resources; see External Resources Supported by XML, Schema, and XSLT Standards for a list of constructs that support the inclusion of external resources. In addition, some constructs enable the execution of applications through external functions. XML External Entity (XXE) injection attacks exploit XML processors that have not been secured by restricting the external resources that it may resolve, retrieve, or execute. This can result in disclosing sensitive data such as passwords or enabling arbitrary execution of code.
External Resources Supported by XML, Schema, and XSLT Standards
XML, Schema, and XSLT standards support the following constructs that require external resources. The default behavior of the JDK XML processors is to make a connection and fetch the external resources as specified.
-
External DTD: references an external Document Type Definition (DTD), for example:
<!DOCTYPE root_element SYSTEM "url">
-
External Entity Reference: Refers to external data, the following is the syntax:
<!ENTITY name SYSTEM "url">
-
General entity reference, for example:
<?xml version="1.0" standalone="no" ?> <!DOCTYPE doc [<!ENTITY otherFile SYSTEM "otherFile.xml">]> <doc> <a> <b>&otherFile;</b> </a> </doc>
-
External Parameter Entities: The following is the syntax:
<!ENTITY % name SYSTEM uri>
The following is an example:
<?xml version="1.0" standalone="no"?> <!DOCTYPE doc [ <!ENTITY % ent1 SYSTEM "http://www.example.com/student.dtd"> %ent1; ]>
- XInclude: Includes an external infoset in an XML document, for
example:
<Book xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href=toc.xml"/> <xi:include href=part1.xml"/> <xi:include href=part2.xml"/> <xi:include href=index.xml"/> </Book>
-
References to XML Schema components using the
schemaLocation
attribute andimport
andinclude
elements, for example:<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:include schemaLocation="http://www.example.com/schema/schema1.xsd"/> <!-- ... --> </xs:schema>
- Combining style sheets using import or include elements, the following
is the
syntax:
<xsl:include href="include.xsl"/>
xml-stylesheet
processing instruction: Used to include a stylesheet in an XML document, for example:<?xml-stylesheet href="include.xsl" type="text/xsl"?>
- XSLT
document()
function: Used to access nodes in an external XML document, for example:<xsl:variable name="dummy" select="document('DocumentFunc2.xml')"/>
Exponential Entity Expansion Attack
The exponential entity expansion attack, also know as the XML bomb or billion laughs attack, is a denial-of-service attack that involves XML parsers. The basic exploit is to have several layers of nested entities, each referring to a number of entities of the next layer. The following is a sample SOAP document that contains deeply nested entity references:
<?xml version="1.0" encoding ="UTF-8"?>
<!DOCTYPE bbb[
<!ENTITY x100 "bbb">
<!ENTITY x99 "&x100;&x100;">
<!ENTITY x98 "&x99;&x99;">
...
<!ENTITY x2 "&x3;&x3;">
<!ENTITY x1 "&x2;&x2;">
]>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=...>
<SOAP-ENV:Body>
<ns1:aaa xmlns:ns1="urn:aaa" SOAP-ENV:encodingStyle="...">
<foobar xsi:type="xsd:string">&x1;</foobar>
</ns1:aaa>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
When an XML parser encounters such a document, it will attempt to resolve the entity declaration by expanding the references. Because the references are nested, the expansion becomes exponential by the number of entities each refers to. Such a process can lead the XML parser to consume 100% of CPU time and a large amount of memory, and eventually the system runs out of memory.
Configuring JAXP for Secure XML Processing
JAXP consists of a set of APIs for parsing, serializing, transforming, querying, and traversing XML documents. See JAXP APIs.
JAXP adds a layer of security through factories and processors. You access APIs from JAXP through factories, which ensure that they are configured according to JAXP properties that you've set based on your security requirements. You configure and instantiate factories with their respective processors. See Factories and Processors.
You configure JAXP processors through JAXP properties. You can set JAXP properties through JAXP factories, as System properties, or in a JAXP configuration file. See Configuring with JAXP Properties.
The section Security-Related Properties describes properties you can set to configure JAXP for secure XML processing.
In addition, JAXP enables you to register custom resolvers and catalogs, which intercept references to external resources and resolve them with local ones. This eliminates the need to read and access external resources, which helps remove a source of potential risk. See Using Resolvers and Catalogs.
JAXP APIs
JAXP consists of a set of APIs built XML technologies and standards that are essential for XML processing. These include APIs for the following:
- Parsing: JAXP Parsing API (javax.xml.parsers package, which is based on the Document Object Model (DOM) (org.w3c.dom package) and Simple API for XML Parsing (SAX) (org.xml.sax package)
- Streaming API for XML (StAX) (javax.xml.stream package)
- Serializing: StAX and Extensible Stylesheet Language Transformations (XSLT) (javax.xml.transform package)
- Transformation: JAXP Transformation API (javax.xml.transform package) and XSLT (Extensible Stylesheet Language Transformations)
- Querying and traversing XML documents: XML Path Language (XPath) API (javax.xml.xpath package)
- Resolving external resources: XML Catalog API (javax.xml.catalog package)
Factories and Processors
Factories are the entry points of each JAXP API. They provide methods that enable applications to set JAXP properties programmatically before creating processors. Factories also support the JAXP lookup mechanism, which enable you to deploy applications with third-party implementations instead of JDK implementations.
Processors are aggregates of parsers (or readers), serializers (or writers), validators, and transformers that control and perform the processing in their respective areas. Factories configure and instantiate their corresponding factories. For example, you configure and instantiate the DocumentBuilder and SAXParser processors with the DocumentBuilderFactory and SAXParserFactory factories, respectively.
Configuring with JAXP Properties
You configure JAXP processors through JAXP properties. The following lists the ways you can set JAXP properties in order of precedence from highest to lowest. For example, if you set a JAXP property's value through a factory, then it will override any other value set in a different way.
- Setting JAXP Properties Through JAXP Factories: You can set a JAXP property through a JAXP factory in your code.
- Setting JAXP Properties as System Properties You can set a JAXP property like a System property by setting its
value on the command line with the following
syntax:
-D<property name>=<property value>
You can also set a System property's value with the method System.setProperty(String key, String name) or System.setProperties(Properties).
- Setting JAXP Properties in a JAXP Configuration File: You can set a JAXP property in a user-defined JAXP configuration
file or in the default JAXP configuration file,
<java-home>/conf/jaxp.properties
.
Not all JAXP properties can be set by all of these ways. See the java.xml module summary to determine which method you can set a specific JAXP property.
If you haven't set a particular JAXP property with one of these ways, then the Java runtime uses the value specified in the default JAXP properties file. If a property doesn't exist in this file, then the Java runtime uses its default value. However, if Feature for Secure Processing (FSP) is turned on, then the Java runtime uses a more restrictive value, if applicable. See the table Implementation Specific Properties in the java.xml module summary for more information.
See the default JAXP configuration file <java-home>/conf/jaxp.properties
for information
about additional JAXP properties.
Setting JAXP Properties Through JAXP Factories
If you can modify your application's code, or you're creating a new application, then you can set JAXP properties through JAXP factories or a parser. Set these properties through the following interfaces:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setAttribute(name, value);
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.setProperty(name, value);
SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
schemaFactory.setProperty(name, value);
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(name, value);
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(name, value);
XPathFactory xf = XPathFactory.newInstance();
xf.setProperty(name, value);
The following is an example of setting processing limits:
dbf.setAttribute("jdk.xml.entityExpansionLimit", "2000");
dbf.setAttribute("jdk.xml.totalEntitySizeLimit", "100000");
dbf.setAttribute("jdk.xml.maxParameterEntitySizeLimit", "10000");
dbf.setAttribute("jdk.xml.maxElementDepth", "100");
factory.setAttribute("jdk.xml.xpathTotalOpLimit", "1000");
xf.setProperty("jdk.xml.xpathExprGrpLimit", "20");
The following is an example of limiting a DOM parser to only local connections for external DTDs:
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "file, jar:file");
If a parser module within the application handles untrusted sources, it may further restrict access. The following code overrides those in the JAXP configuration file and those specified by System properties and enables the XML processor to read local files only:
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "file");
// ...
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "file");
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file");
As described in Configuring JAXP for Secure XML Processing, JAXP properties specified through JAXP factories have the narrowest scope, affecting only the processors created by the factories, and therefore override any default settings, System properties, and those in the JAXP configuration file. By setting JAXP properties through JAXP factories, you can ensure that your applications behave the same way regardless of which JDK release you're using or whether JAXP properties are set through other means.
Setting JAXP Properties as System Properties
System properties may be useful if you can't modify your application's code.
To set JAXP properties for an entire JDK invocation, set their corresponding
System properties on the command line. For example, if your application,
MyApp
requires access to external DTDs and schemas, then set the
System properties javax.xml.accessExternalDTD
and
javax.xml.accessExternalSchema
as follows:
java -Djavax.xml.accessExternalDTD="file,http"
-Djavax.xml.accessExternalSchema="file, http" MyApp
To set JAXP properties for only a portion of the application, set their corresponding System properties before the portion, and then clear them afterward. For example, if your application requires access to external DTDs and schemas, then add these lines to your application's initialization code block:
System.setProperty("javax.xml.accessExternalDTD", "file, http");
System.setProperty("javax.xml.accessExternalSchema", "file, http");
Then, once your application is done processing XML documents or before it exits, clear out the properties as follows:
System.clearProperty("javax.xml.accessExternalDTD");
System.clearProperty("javax.xml.accessExternalSchema");
Note:
JAXP properties related to processing limits are specific to the JDK implementation while those related to external access restrictions are standard properties.Setting JAXP Properties in a JAXP Configuration File
You can set JAXP properties in a JAXP configuration file, which is a java.util.Properties file. (See Properties in The Java Tutorials for more information about Java properties.)
Format of a JAXP Configuration File
A JAXP configuration file is a text file that contains names and values of
JAXP properties, one name-value pair on each line. For example, the following JAXP
configuration file sets the maxGeneralEntitySizeLimit
processing limit
property to 2000 and restricts access to the file and HTTP protocols for external references
set by the stylesheet
processing instruction, document
function, and the import
and include
elements.
jdk.xml.maxGeneralEntitySizeLimit=2000
javax.xml.accessExternalStylesheet=file, http
If you don't want to allow any external connection by XML processors, you
can set all access external restrictions to file
only:
javax.xml.accessExternalDTD=file
javax.xml.accessExternalSchema=file
javax.xml.accessExternalStylesheet=file
If you want to prevent applications from accidentally reading external files through an XML processor, set the external access restrictions as in the following JAXP configuration file:
javax.xml.accessExternalDTD=""
javax.xml.accessExternalSchema=""
javax.xml.accessExternalStylesheet=""
Tip:
If you can specify a JAXP property as a System property, then you can specify the same JAXP property in a JAXP configuration file. See the java.xml module summary to determine where to set the value of a specific JAXP property.Specifying a User-Defined JAXP Configuration File
To use your own JAXP configuration file, specify its name and location with
the java.xml.config.file
System property. If you specify a file path that's
not absolute, then it's relative to the current working directory. If the value of this
System property hasn't been specified when a JAXP factory is instantiated, then no further
attempt will be made to check its value.
A user-defined JAXP configuration file is read only once when the JAXP implementation is initialized. This means that it won't work if you modify it after a JAXP factory has been instantiated.
Default JAXP Configuration File
The JDK contains a default JAXP configuration file <java_home>/conf/jaxp.properties
. However,
it's recommended that you create your own user-defined JAXP configuration file
instead.
If you have specified a user-defined JAXP configuration file with the System
property java.xml.config.file
and that file exists, then any settings
in it override those in the default JAXP configuration file.
JAXP Configuration Template with Strict Settings
The JAXP configuration template can help you validate that your applications are prepared for future JDK releases. You can use the template, which specifies more restrictive XML processing settings, to identify issues such as a processor unknowingly making outbound network connections to fetch DTDs or an XML processor that relies on extension functions.
Follow these steps to test the readiness of your application with the JAXP configuration template:
-
Copy the JAXP configuration template,
<java_home>/conf/jaxp-strict.properties.template
, to a new file with the.properties
extension. For example, the following command copies the template to a file named/path/to/jaxp-strict.properties
:cp <java_home>/conf/jaxp-strict.properties.template /path/to/jaxp-strict.properties
-
Run your application, specifying the system property
java.xml.config.file
with the path where you copied the JAXP configuration file template to override the default configuration. For example:java -Djava.xml.config.file=/path/to/jaxp-strict.properties myApp
If you decide that your applications are ready for a more secure configuration, then you can use the configuration template as your JAXP configuration file.
See the section Configuration File in the java.xml module JavaDoc API documentation for more information.
Security-Related Properties
The following sections describe the properties you can set to configure JAXP for secure XML processing:
JAXP Properties for Processing Limits
XML processing can sometimes be a memory intensive operation. Applications, especially those that accept XML, XSD and XSL from untrusted sources, should take steps to guard against excessive memory consumption by using JAXP properties for processing limits.
Evaluate your application's requirements and operating environment to
determine the acceptable processing limits for your system configurations and set these
limits accordingly. For example, use size-related limits to prevent malformed XML
sources from consuming large amounts of memory. Use the
jdk.xml.entityExpansionLimit
property to enable an application to
control memory consumption under an acceptable level.
The JDK XML parsers observe processing limits by default. Both DOM and SAX parsers have Feature for Secure Processing (FSP) turned on by default and therefore turn on the limits. The StAX parser also observes processing limits by default even though it doesn't support FSP.
The following table describes the JAXP properties for processing limits
supported in the JDK. The value for each of these processing limits is a positive
integer. A value less than or equal to 0 indicates no limit. If the value is not an
integer, a NumericFormatException
is thrown. You can specify the values
of these properties through its factory, as a System property, or in a JAXP
configuration file.
See the table Implementation Specific Properties in the java.xml module summary for more information.
Table 12-1 JAXP Processing Limit Properties
Property Name | Description | Default Value | Supported Factories |
---|---|---|---|
jdk.xml.elementAttributeLimit |
Limits the number of attributes an element can have. | 200 |
DocumentBuilderFactory |
jdk.xml.entityExpansionLimit |
Limits the number of entity expansions. | 2500 |
DocumentBuilderFactory |
jdk.xml.entityReplacementLimit |
Limits the total number of nodes in all entity references. | 100000 |
DocumentBuilderFactory |
jdk.xml.maxElementDepth |
Limits the maximum element depth. | 100 |
DocumentBuilderFactory |
jdk.xml.maxGeneralEntitySizeLimit |
Limits the maximum size of any general entities. | 100000 |
DocumentBuilderFactory |
jdk.xml.maxOccurLimit |
Limits the number of content model nodes that may be
created when building a grammar for a W3C XML Schema that contains
maxOccurs attributes with values other than
"unbounded".
|
5000 |
DocumentBuilderFactory |
jdk.xml.maxParameterEntitySizeLimit |
Limits the maximum size of any parameter entities, including the result of nesting multiple parameter entities. | 15000 |
DocumentBuilderFactory |
jdk.xml.maxXMLNameLimit |
Limits the maximum size of XML names, including element name, attribute name and namespace prefix and URI. | 1000 |
DocumentBuilderFactory |
jdk.xml.totalEntitySizeLimit |
Limits the total size of all entities that include general and parameter entities. The size is calculated as an aggregation of all entities. | 100000 |
DocumentBuilderFactory |
jdk.xml.xpathExprGrpLimit |
Limits the number of groups an XPath expression can contain. | 10 |
TransformerFactory |
jdk.xml.xpathExprOpLimit |
Limits the number of operators an XPath expression can contain. | 100 |
TransformerFactory |
jdk.xml.xpathTotalOpLimit |
Limits the total number of XPath operators in an XSL Stylesheet. | 100000 | TransformerFactory |
When to Use Processing Limits
When determining which processing limits to apply and what values to use, at the system level, consider the amount of memory available for applications and whether XML, XSD, or XSL sources from untrusted sources are accepted and processed. At the application level, consider whether certain constructs such as DTDs are used.
Memory Setting and Limits
XML processing can be very memory intensive. The amount of memory that should be allowed to be consumed depends on the requirements of the applications in a specific environment. Processing of malformed XML data must be prevented from consuming excessive memory.
The default limits are generally set to allow legitimate XML inputs for most applications with memory usage allowed for a small hardware system, such as a PC. It is recommended that the limits are set to the smallest possible values, so that any malformed input can be caught before it consumes large amounts of memory.
The limits are correlated, but not entirely redundant. You should set appropriate values for all of the limits: usually the limits should be set to a much smaller value than the default.
For example, ENTITY_EXPANSION_LIMIT
and
GENERAL_ENTITY_SIZE_LIMIT
can be set to prevent excessive
entity references. But when the exact combination of the expansion and entity sizes
are unknown, TOTAL_ENTITY_SIZE_LIMIT
can serve as a overall
control. Similarly, while TOTAL_ENTITY_SIZE_LIMIT
controls the
total size of a replacement text, if the text is a very large chunk of XML,
ENTITY_REPLACEMENT_LIMIT
sets a restriction on the total number
of nodes that can appear in the text and prevents overloading the system.
Estimating the Limits Using the getEntityCountInfo Property
To help you analyze what values you should set for the limits, a special
property called
http://www.oracle.com/xml/jaxp/properties/getEntityCountInfo
is
available. The following code snippet, from Processing Limit Samples in
The Java Tutorials, shows an example of using the
property:
public static final String ORACLE_JAXP_PROPERTY_PREFIX =
"http://www.oracle.com/xml/jaxp/properties/";
// ...
public static final String JDK_ENTITY_COUNT_INFO =
ORACLE_JAXP_PROPERTY_PREFIX + "getEntityCountInfo";
// ...
parser.setProperty(JDK_ENTITY_COUNT_INFO, "yes");
When you run the processing limit sample with the DTD in W3C MathML 3.0, it prints the following table:
Sample: parsing W3C MathML
Property Limit Total size Size Entity Name
ENTITY_EXPANSION_LIMIT 64000 1417 0 null
MAX_OCCUR_NODE_LIMIT 5000 0 0 null
ELEMENT_ATTRIBUTE_LIMIT 10000 0 0 null
TOTAL_ENTITY_SIZE_LIMIT 50000000 59259 0 null
GENERAL_ENTITY_SIZE_LIMIT 0 0 10 nvlt
PARAMETER_ENTITY_SIZE_LIMIT 1000000 0 7304 %MultiScriptExpression
MAX_ELEMENT_DEPTH_LIMIT 100 2 2 null
MAX_NAME_LIMIT 1000 13 13 null
ENTITY_REPLACEMENT_LIMIT 3000000 0 0 null
XPATH_GROUP_LIMIT 10 0 0 null
XPATH_OP_LIMIT 100 0 0 null
XPATH_TOTALOP_LIMIT 10000 0 0 null
DTD 0 0 0 null
XERCES_DISALLOW_DTD 0 0 0 null
STAX_SUPPORT_DTD 1 0 0 null
JDKCATALOG_RESOLVE 0 0 0 null
The "Limits" column suggests values you should set for the limits. In
this example, it suggests 64000 for ENTITY_EXPANSION_LIMIT
.
However, there was a total of 1417 entity expansions.
If the DTD in W3C MathML 3.0 is the largest file that the application is
expected to process, it is recommended that the limits be set to smaller numbers.
For example, 2000 for ENTITY_EXPANSION_LIMIT
, 100000 for
TOTAL_ENTITY_SIZE_LIMIT
, and 10000 for
PARAMETER_ENTITY_SIZE_LIMIT
.
Feature Security Processing
Feature security processing instructs JAXP components such as parsers, transformers, and so on to behave in a secure fashion. Feature security processing is disabled by default.
Feature Security Processing Default Limitations
The following table describes which XML-related factory classes are disabled and which processing limits are set if feature security processing is enabled.
Table 12-2 Default Limitations Set by Feature Security Processing on XML-Related Factory Classes
XML-Related Factory Class | Enabled? | Processing Limits |
---|---|---|
DocumentBuilderFactory | true | jdk.xml.entityExpansionLimit = 64000
|
SAXParserFactory | true | jdk.xml.entityExpansionLimit =
64000
|
SchemaFactory | true | jdk.xml.maxOccurLimit = 5000
|
TransformerFactory | false | Extension functions disabled |
XPathFactory | false | Extension functions disabled |
The following sections describes the processing limits in this table in detail and how you can change them.
Limiting Entity Expansion
Limit the the number of entity expansions by either setting the system
property jdk.xml.entityExpansionLimit
or the parser property
http://apache.org/xml/properties/entity-expansion-limit
. Both
properties accept java.lang.Integer
values. The parser throws a
fatal error once it has reached the entity expansion limit. By default,
entityExpansionLimit
is set to 64,000.
The following command-line example sets the entity expansion limit to 10,000:
java -DentityExpansionLimit=10000 MyApp
The following code example sets the entity expansion limit to 10,000:
System.setProperty("jdk.xml.entityExpansionLimit","10000");
The following code example sets the parser property
http://apache.org/xml/properties/entity-expansion-limit
to
10,000:
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
dfactory.setAttribute(
"http://apache.org/xml/properties/entity-expansion-limit",
new Integer("10000"));
DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
Limiting Number of Element Attributes
Limit the number of attributes in an element by either setting the
system property jdk.xml.elementAttributeLimit
or by setting the
parser property
http://apache.org/xml/properties/elementAttributeLimit
. Both
properties accept Integer values. By default,
jdk.xml.elementAttributeLimit
is set to 10,000. When the parser
property http://apache.org/xml/properties/elementAttributeLimit
is
set, it overrides the system property. The parser throws a fatal error if the number
of attributes in a element exceeds the limit.
The following command-line example sets the element attribute limit to 20:
java -Djdk.xml.elementAttributeLimit=20 MyApp
The following code example sets the element attribute limit to 20:
System.setProperty("jdk.xml.elementAttributeLimit","20");
The following code example sets the parser property
http://apache.org/xml/properties/entity-expansion-limit
to
20:
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
dfactory.setAttribute(
"http://apache.org/xml/properties/elementAttributeLimit",
new Integer(20));
DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
Limit Number of Nodes Created by Constructs That Contain maxOccurs
In constructs like xsd:sequence
, the validating parser
may use space (memory) proportional to the value of the maxOccurs
occurrence indicator. This may cause the VM to run out of memory, or simply run for
a very long time. To prevent potential attacks that exploit this behavior, enable
secure processing on a factory as follows:
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
Note that for xsd:element
and xsd:any
,
the validating parser uses a constant amount of space, which is independent of the
value of the maxOccurs
occurrence indicator.
The default value of jdk.xml.maxOccurLimit
is 5000. This
system property limits the number of content model nodes that may be created when
building a grammar for a W3C XML Schema that contains maxOccurs
occurrence indicators with values other than "unbounded".
Disabling XPath and XSLT Extension Functions
By default, XPath and XSLT extension functions are disabled when feature secure processing is enabled. The following code enables feature secure processing and disables XPath and XSLT extension functions for XPathFactory:
XPathFactory xpf = xPathFactory.newInstance();
xpf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
The following code enables feature secure processing and disables XSLT extension functions for TransformerFactory:
TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Security Issue Posed by Nested Entity Definitions
While XML does not allow recursive entity definitions, it does permit nested entity definitions, which produces the potential for Denial of Service attacks on a server which accepts XML data from external sources. For example, a SOAP document like the following that has very deeply nested entity definitions can consume 100% of CPU time and large amounts of memory in entity expansions:
<?xml version="1.0" encoding ="UTF-8"?>
<!DOCTYPE foobar[
<!ENTITY x100 "foobar">
<!ENTITY x99 "&x100;&x100;">
<!ENTITY x98 "&x99;&x99;">
...
<!ENTITY x2 "&x3;&x3;">
<!ENTITY x1 "&x2;&x2;">
]>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=...>
<SOAP-ENV:Body>
<ns1:aaa xmlns:ns1="urn:aaa" SOAP-ENV:encodingStyle="...">
<foobar xsi:type="xsd:string">&x1;</foobar>
</ns1:aaa>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
You don't have worry about this issue if your system doesn't take in external XML data, but a system that does should turn on the secure processing feature and reset the limits as described in Limiting Entity Expansion and Limiting Number of Element Attributes.
Disallowing DTDs
When you set the
http://apache.org/xml/features/disallow-doctype-decl
parser
property to true, a fatal error is then thrown if the incoming XML document contains
a DOCTYPE declaration. (The default value for this property is false.) This property
is typically useful for SOAP based applications where a SOAP message must not
contain a Document Type Declaration.
Secure Processing Using StAX
The class XMLInputFactory
includes the property javax.xml.stream.supportDTD
that requests
processors that do not support DTDs. StAX includes a similar property,
XMLInputFactory.SUPPORT_DTD
, that you can use to disable DTD
processing:
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
Resolving External Resources
The following system properties restrict how XML parsers resolve external resources:
javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD
javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA
javax.xml.XMLConstants.ACCESS_EXTERNAL_STYLESHEET
See JAXP 1.5 and New Properties in The Java Tutorials for more information about these properties.
Turning off Feature Secure Processing
Turn off feature secure processing by calling the
setFeature
method on factories. The following code example
turns off feature secure processing for the SAX parser:
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,false);
When you turn off feature secure processing for the DOM or SAX parser,
you remove the default limiations specified by
jdk.xml.entityExpansionLimit
,
jdk.xml.elementAttributeLimit
, and
jdk.xml.maxOccurLimit
.
JAXP Properties for External Access Restrictions
JAXP properties for external access restrictions, along with their corresponding System properties, enable you to regulate external connections.
External access restrictions enable you to specify the type of external connections that can or cannot be permitted. The property values are a list of protocols. The JAXP processors check if a given external connection is permitted by matching the protocol with those in the list. Processors will attempt to establish the connection if it is on the list, or reject it if not. Use these JAXP properties along with custom resolvers and the Catalog API (see Using Resolvers and Catalogs) to reduce the risk of external connections by rejecting and resolving them with local resources.
Note:
Explicitly turning on Feature for Secure Processing (FSP) through the API, for example,factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true)
,
disables all external connections.
The external access restrictions JAXP properties are defined in javax.xml.XMLConstants as follows:
- javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD
- javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA
- javax.xml.XMLConstants.ACCESS_EXTERNAL_STYLESHEET
You can specify the values of these properties as a System property or in a JAXP configuration file.
Table 12-3 External Access Restrictions JAXP Properties
Property | Description | Default Value |
---|---|---|
javax.xml.accessExternalDTD | Restricts access to external DTDs and external entity references to the protocols specified | all , connection permitted to all protocols
|
javax.xml.accessExternalSchema |
Restricts access to the protocols specified for external references
set by the schemaLocation attribute,
import element, and include
element
|
all , connection permitted to all protocols
|
javax.xml.accessExternalStylesheet |
Restricts access to the protocols specified for external references
set by the stylesheet processing instruction,
document function, and import and
include elements.
|
all , connection permitted to all protocols
|
Values of External Access Restrictions JAXP Properties
All JAXP properties for external access restrictions have values of the same format:
-
Value: A list of protocols separated by comma. A protocol is the scheme portion of an URI, or in the case of the JAR protocol,
jar
plus the scheme portion separated by colon. A scheme is defined as:scheme = alpha *( alpha | digit | "+" | "-" | "." )
where
The JAR protocol is defined as:alpha
=a-z
andA-Z
.jar[:scheme]
Protocols are case-insensitive. Any whitespace characters as defined by Character.isSpaceChar in the value are ignored. Examples of protocols are
file
,http
, andjar:file
. -
Default value: The default value is implementation specific. For the JDK, the default value is
all
, which grants permissions to all protocols. -
Granting all access: The keyword
all
grants permission to all protocols. For example, specifyingjavax.xml.accessExternalDTD=all
in the JAXP configuration file enables a system to work as before with no restrictions on accessing external DTDs and entity references. -
Denying any access: An empty string (
""
) means that no permission is granted to any protocol. For example, specifyingjavax.xml.accessExternalDTD=""
in the JAXP configuration file instructs JAXP processors to deny any external connections.
When to Use External Access Restrictions
The XML processors, by default, attempt to connect and read external resources that are referenced in XML sources. Note that this may potentially expose applications and systems to risks posed by external connections. It's therefore recommended that applications consider limiting external connections with external access restriction properties.
Internal applications and systems that handle only trusted XML documents may not need these restrictions. However, keep in mind that external access restrictions are specific to the XML processors and are at the top layer of the process, which means that the processors check these restrictions before any connections are made. They may therefore serve as an additional and more direct protection against external connection risks.
You can use external access restriction properties along with custom resolvers and catalogs (see Using Resolvers and Catalogs) to effectively manage external connections and reduce risks.
Even in a trusted environment with trusted sources, it's recommended that you use both external access restrictions and resolvers to minimize dependencies on external sources.
JAXP Property Precedence and External Access Restrictions
External access restrictions have no effect on the relevant constructs that they attempt to restrict in the following situations:
-
When there is a resolver and the source returned by the resolver is not null: This applies to entity resolvers that may be set on SAX and DOM parsers, XML resolvers on StAX parsers, LSResourceResolver on SchemaFactory, a Validator or ValidatorHandler, or URIResolver on a transformer.
-
When a schema is created explicitly by calling the newSchema method from SchemaFactory.
-
When external resources are not required: For example, the following features and properties are supported by the JDK and may be used to instruct the processor to not load the external DTD or resolve external entities:
http://apache.org/xml/features/disallow-doctype-decl true http://apache.org/xml/features/nonvalidating/load-external-dtd false http://xml.org/sax/features/external-general-entities false http://xml.org/sax/features/external-parameter-entities false
JAXP Property for Extension Functions
The default value of the property for
jdk.xml.enableExtensionFunctions
is false
, which
disables XSLT and XPath external functions. External functions enable you to invoke your own
or third-party code from a stylesheet.
If an application handles XML transformation with a stylesheet that uses extension functions, it may encounter a processing error, for example:
Use of the extension function <function name> is not
allowed when extension functions are disabled by the secure processing feature or
the property jdk.xml.enableExtensionFunctions. To enable extension functions, set
jdk.xml.enableExtensionFunctions to true.
You can set the property jdk.xml.enableExtensionFunctions
to
true
as follows:
-
Through the JAXP Transformation API (javax.xml.transform package):
TransformerFactory tf = TransformerFactory.newInstance(); tf.setFeature("jdk.xml.enableExtensionFunctions", true);
-
Through the XPath API (javax.xml.xpath package):
XPathFactory xf = XPathFactory.newInstance(); xf.setFeature("jdk.xml.enableExtensionFunctions", true);
-
In the JAXP configuration file; see Setting JAXP Properties in a JAXP Configuration File
-
On the command line:
java -Djdk.xml.enableExtensionFunctions=true myApp
JAXP Property for Third-Party Parsers
The JDK will always use its system-default parser even when there's a
third-party parser on the classpath. To override the JDK system-default parser, set the
jdk.xml.overrideDefaultParser
property to true through TransformerFactory, SchemaFactory, or XPathFactory,
as a System property, or in a JAXP configuration file.
Table 12-4 The jdk.xml.enableExtensionFunctions Property
Property | Description | Default Value | Supported Factories |
---|---|---|---|
jdk.xml.overrideDefaultParser |
If true , then it enables the use of a
third-party's parser implementation to override the system-default
parser for the JDK's Transformer,
Validator, and XPath implementations. If false , then it
disables the use of third-party parser implementations.
|
false |
TransformerFactory |
DTD Properties
If your applications don't require DTDs, then consider disabling DTD processing to safeguard against many common DTD-related attacks, including denial-of-service, XML external entity (XXE), and server-side request forgery (SSRF).
You can use the jdk.xml.dtd.support
system property to disable
DTD processing. It can have one of the following values:
allow
: The parser continues to process DTDs. This is the default value.ignore
: The parser skips DTDs.deny
: The parser rejects DTDs as an error. The parser reports the error in accordiance with its specification.
Note:
Setting the value of thejdk.xml.dtd.support
system property is the
recommended way to disable DTD processing. This system property enables you
to disable DTD processing for all parsers and processors. In addition, you
can use this property in a JAXP configuration file.
There are two other ways you can disable DTD processing, but they apply to specific parsers:
-
To disable DTD processing for SAX and DOM parsers, set the feature
http://apache.org/xml/features/disallow-doctype-decl
totrue
through a factory. The following code snippet disables DTDs for SAX parsers. A fatal error is thrown if the incoming XML document contains a DOCTYPE declaration.final static String DISALLOW_DTD = "http://apache.org/xml/features/disallow-doctype-decl"; // ... SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setFeature(DISALLOW_DTD, true);
-
To disable DTD processing for StAX parsers, set the property
SupportDTD
tofalse
with the XMLInputFactory.setProperty method:XMLInputFactory xif = XMLInputFactory.newInstance(); xif.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
If you use any of these two ways to disable DTD
processing, then the jdk.xml.dtd.support
system
property will have no effect.
Using Resolvers and Catalogs
You can register custom resolvers and catalogs on a JDK XML processor to intercept any references to external resources and resolve them with local ones. This feature eliminates the need to read and access external resources, thus helping to remove a source of potential risk.
Java XML Resolvers
The Java XML API supports various resolvers that you can register on JDK XML processors to resolve external resources. These resolvers includes entity resolvers for SAX and DOM parsers, XML resolvers for StAX parsers, LSResourceResolver for validation, and URIResolver for transformation.
Entity Resolvers for SAX and DOM
SAX defines an interface that DOM also supports, org.xml.sax.EntityResolver. It enables applications to step into the entity resolution process and perform entity resolution on their own terms. The following is the interface's definition:
package org.xml.sax;
public interface EntityResolver {
public InputSource resolveEntity(String publicID, String systemID)
throws SAXException;
}
You can then register an implementation of the interface on a SAX driver:
EntityResolver resolver = ...;
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setEntityResolver(resolver);
Alternatively, you can register it on a DOM builder:
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
docBuilder.setEntityResolver(resolver);
XMLResolver for StAX
StAX defines a javax.xml.stream.XMLResolver interface:
package javax.xml.stream;
public interface XMLResolver {
public Object resolveEntity(
String publicID, String systemID,
String baseURI, String namespace)
throws XMLStreamException;
}
You can register it on a StAX factory:
XMLResolver resolver = ...;
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.RESOLVER, resolver);
URIResolver for javax.xml.transform
The javax.xml.transform API supports custom resolution of external resources through the URIResolver interface:
package javax.xml.transform;
public interface URIResolver {
public Source resolve(String href, String base)
throws TransformerException;
}
You can register an implementation of URIResolver on a Transformer as follows:
URIResolver resolver = ...;
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t =
tf.newTransformer(new StreamSource(
new StringReader("xsl source")));
t.setURIResolver(resolver);
LSResourceResolver for javax.xml.validation
The javax.xml.validation API supports Document Object Model Level 3 Load and Save (DOM LS) DOM through the LSResourceResolver interface:
package org.w3c.dom.ls;
public interface LSResourceResolver {
public LSInput resolveResource(
String type, String namespaceURI, String publicId,
String systemId, String baseURI);
}
You can register an implementation of LSResourceResolver on a SchemaFactory as follows:
SchemaFactory schemaFactory =
SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
LSResourceResolver resolver = ...;
schemaFactory.setResourceResolver(resolver);
The Catalog API
The XML Catalog API supports the Organization for the Advancement of Structured Information Standards (OASIS) XML Catalogs, OASIS Standard V1.1. This API is fully implemented by the JDK XML processors and easy to use. See XML Catalog API in Java Platform, Standard Edition Core Libraries.
Use the XML Catalog API to resolve external resources with the CatalogResolver interface and to enable catalogs on JDK XML processors.
Catalog Resolver
You can use a CatalogResolver as a custom resolver that substitutes external references with local resources configured as Catalog objects. You can register a CatalogResolver on factories or processors in place of EntityResolver, XMLResolver, URIResolver or LSResourceResolver as described in Java XML Resolvers. In the following code snippet, a CatalogResolver is registered as an EntityResolver on a SAXParserFactory:
URI catalogUri = URI.create("file:///users/auser/catalog/catalog.xml")
CatalogResolver cr =
CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogUri);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setEntityResolver(cr);
Enable Catalogs on JDK XML Processors
The JDK XML processors implement the Catalog API as a native function. Therefore, there is no need to instantiate a CatalogResolver outside the processors. All you need to do is register the catalog files on the XML processors through the setProperty or setAttribute methods, through System properties, or in the JAXP configuration file. The XML processors then perform the mappings through the catalogs automatically. The following code snippet demonstrates how to register catalogs on StAX parsers through XMLInputFactory:
String catalog = "file:///users/auser/catalog/catalog.xml";
XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog);
For more examples, see XML Catalog API in Java Platform, Standard Edition Core Libraries.
The Built-In Catalog
The JDK has a built-in catalog that hosts the following DTD and XSD files as defined by the Java platform and the World Wide Web Consortium (W3C):
Table 12-5 DTD and XSD Files in the JDK Built-In Catalog
Source | DTD or XSD File or Files |
---|---|
java.util.prefs.Preferences | preferences.dtd |
java.util.Properties | properties.dtd |
XML Schema Part 1: Structures Second Edition, XML Schema Part 2: Datatypes Second Edition | XMLSchema.dtd ,
datatypes.dtd ,
XMLSchema.xsd ,
datatypes.xsd |
XHTML 1.0 The Extensible HyperText Markup Language | xhtml1-frameset.dtd , xhtml1-strict.dtd
xhtml1-transitional.dtd |
XHTML 1.0 in XML Schema | xhtml1-frameset.xsd ,
xhtml1-strict.xsd
xhtml1-transitional.xsd |
XHTML 1.1 - Module-based XHTML - Second Edition | xhtml11.dtd |
XHTML 1.1 XML Schema Definition | xhtml11.xsd |
XML DTD for W3C specifications | xmlspec.dtd |
The "xml:" Namespace | xml.xsd |
The built-in catalog is loaded when the first JAXP processor factory is created.
The External Resource Resolution Process with the Built-In Catalog
The JDK creates a CatalogResolver with the built-in catalog when required. This CatalogResolver is the default external resource resolver.
XML processors may use resolvers (such as EntityResolver, XMLResolver, and CatalogResolver) to handle external references. In the absence of user-defined resolvers, the JDK XML processors fall back to the default CatalogResolver to attempt to find a resolution before making a connection to fetch the resources. The fallback also takes place if a user-defined resolver exists but allows the process to continue when unable to resolve the resource.
If the default CatalogResolver can't locate a resource, it may
signal the XML processors to continue processing, ignore or skip the resource, or
throw a CatalogException. The behavior is configured with the
jdk.xml.jdkcatalog.resolve
system property. It can have one of
the following values:
continue
: Continue processing despite being unable to locate the resource. This is the default value.ignore
: Skip the resource that can't be located.strict
: Throw a CatalogException if the resource can't be located.
Handling Errors from JAXP Properties
It is recommended that applications catch org.xml.sax.SAXNotRecognizedException when setting JAXP properties so that the applications will work properly on older releases that don't support them.
For example, the following method, isNewPropertySupported
,
from Processing Limit Samples in The Java Tutorials, detects if the sample is run with a version
of the JDK that supports the JDK_GENERAL_ENTITY_SIZE_LIMIT
property:
public boolean isNewPropertySupported() {
try {
SAXParser parser = getSAXParser(false, false, false);
parser.setProperty(JDK_GENERAL_ENTITY_SIZE_LIMIT, "10000");
} catch (ParserConfigurationException ex) {
fail(ex.getMessage());
} catch (SAXException ex) {
String err = ex.getMessage();
if (err.indexOf("Property '" + JDK_GENERAL_ENTITY_SIZE_LIMIT +
"' is not recognized.") > -1) {
// expected before this patch
debugPrint("New limit properties not supported. Samples not run.");
return false;
}
}
return true;
}
When input files contain constructs that cause an over-the-limit exception, applications may check the error code to determine the nature of the failure. The following error codes are defined for processing limits:
EntityExpansionLimit
: JAXP00010001ElementAttributeLimit
: JAXP00010002MaxEntitySizeLimit
: JAXP00010003TotalEntitySizeLimit
: JAXP00010004MaxXMLNameLimit
: JAXP00010005maxElementDepth
: JAXP00010006EntityReplacementLimit
: JAXP00010007
The error code has the following format:
"JAXP" + components (two digits) + error category (two digits) + sequence number
The code JAXP00010001, therefore, represents the JAXP base parser security
limit EntityExpansionLimit
.
If access to external resources is denied due to the restrictions set by external access restrictions, then an exception will be thrown with an error in the following format:
[type of construct]: Failed to read [type of construct]
"[name of the external resource]", because "[type of restriction]"
access is not allowed due to restriction set by the
[property name] property.
For example, suppose the following:
-
The
ACCESS_EXTERNAL_DTD
JAXP property is set as follows:parser.setProperty( "http://javax.xml.XMLConstants/property/accessExternalDTD", "file");
-
Your application tries to fetch an external DTD with the HTTP protocol.
-
The parser parsed an XML file that contains an external reference to
http://www.example.com/dtd/properties.dtd
.
The error message would look like the following:
External DTD: Failed to read external DTD
"http://www.example.com/dtd/properties.dtd", because "http"
access is not allowed due to restriction set by the
accessExternalDTD property.
General Recommendations for JAXP Security
The following are general recommendations for configuring JAXP properties and features to help secure your applications and systems:
- Create and specify a user-defined JAXP configuration file with property settings tailored to your environment; see Setting JAXP Properties in a JAXP Configuration File. Afterward, adjust individual features and properties in accordance with specific requirements of the applications through factory settings or System properties.
- Disable DTDs with the
jdk.xml.dtd.support
system property if the application does not require or process DTD content. See DTD Properties. - For processing limits, adjust them so that they are just large enough to accommodate the maximum amount your applications require.
- For external access restrictions, reduce or eliminate your applications' reliance on external resources, including the use of resolvers, then tighten these restrictions.
- Set up a local catalog and enable the Catalog API on all XML processors to further reduce your applications' reliance on external resources.
- Reject any external references not resolved by a user-defined resolver
or catalog by configuring the built-in catalog's
jdk.xml.jdkcatalog.resolve
system property. See The Built-In Catalog.
Appendix A: Glossary of Java API for XML Processing Terms and Definitions
Table 12-6 JAXP Glossary
Term | Definition |
---|---|
JAXP | Java API for XML Processing |
Java SE XML API | APIs defined in the JAXP JSR and integrated into Java SE |
Java XML API | Equivalent term for Java SE XML API |
Java XML Features and Properties | XML-related features and properties defined by the Java SE specification |
java.xml | The java.xml module |
JDK XML | The JDK implementation of the Java XML API |
JDK XML Parsers | The JDK implementation of the XML parsers |
JDK XML Properties | The JDK Implementation-only properties |
FSP | FEATURE_SECURE_PROCESSING |
Appendix B: Java and JDK XML Features and Properties Naming Convention
Java and JDK XML features and properties are defined in the javax.xml.XMLConstants class. The features have a prefix
http://javax.xml.XMLConstants/feature
; the properties,
http://javax.xml.XMLConstants/property
. If there is a corresponding
System property, its prefix is javax.xml
.
The JDK XML properties are JDK implementation-only properties. The prefix of
the properties is http://www.oracle.com
for JDK 8 and earlier and
jdk.xml
for JDK 9 and later. The following table summarizes this
naming convention:
Table 12-7 Java and JDK XML Features and Properties Naming Convention
Scope | API Property Prefix | System Property Prefix | Java SE and JDK Version |
---|---|---|---|
Java SE |
|
javax.xml |
Since 1.4 |
JDK | http://www.oracle.com/xml/jaxp/properties |
jdk.xml |
Since 7 |
JDK | jdk.xml |
jdk.xml |
Since 9 |