This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch mvn-site-simplified
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit b6087e3b2ec6dd3802298c1e30bbc24e23397d84
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Thu Nov 24 09:15:11 2022 +0100

    LOG4J2-3628 Protect `DocumentBuilderFactory` against XXE.
---
 .../logging/log4j/internal/util/XmlReader.java     |  7 +--
 .../logging/log4j/internal/util/XmlUtils.java      | 71 ++++++++++++++++++++++
 .../logging/log4j/internal/util/XmlWriter.java     |  2 +-
 3 files changed, 74 insertions(+), 6 deletions(-)

diff --git 
a/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlReader.java
 
b/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlReader.java
index 64f994d55d..df1b2442a1 100644
--- 
a/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlReader.java
+++ 
b/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlReader.java
@@ -23,10 +23,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.*;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -61,7 +58,7 @@ public final class XmlReader {
     private static Document readXml(final InputStream inputStream) throws 
Exception {
         final SAXParserFactory parserFactory = SAXParserFactory.newInstance();
         final SAXParser parser = parserFactory.newSAXParser();
-        final DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory.newInstance();
+        final DocumentBuilderFactory documentBuilderFactory = 
XmlUtils.createDocumentBuilderFactory();
         final DocumentBuilder documentBuilder = 
documentBuilderFactory.newDocumentBuilder();
         final Document document = documentBuilder.newDocument();
         PositionalSaxEventHandler handler = new 
PositionalSaxEventHandler(document);
diff --git 
a/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlUtils.java
 
b/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlUtils.java
new file mode 100644
index 0000000000..1b48f9d316
--- /dev/null
+++ 
b/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlUtils.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.internal.util;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+final class XmlUtils {
+
+    private XmlUtils() {}
+
+    /**
+     * @return a {@link DocumentBuilderFactory} instance configured with 
certain XXE protection measures
+     * @see <a 
href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxp-documentbuilderfactory-saxparserfactory-and-dom4j";>XML
 External Entity Prevention Cheat Sheet</a>
+     */
+    static DocumentBuilderFactory createDocumentBuilderFactory() {
+        final DocumentBuilderFactory dbf = 
DocumentBuilderFactory.newInstance();
+        String feature = null;
+        try {
+
+            // This is the PRIMARY defense.
+            // If DTDs (doctypes) are disallowed, almost all XML entity 
attacks are prevented.
+            // Xerces 2 only - 
http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
+            feature = "http://apache.org/xml/features/disallow-doctype-decl";;
+            dbf.setFeature(feature, true);
+
+            // If you can't completely disable DTDs, then at least do the 
following:
+            // Xerces 1 - 
http://xerces.apache.org/xerces-j/features.html#external-general-entities
+            // Xerces 2 - 
http://xerces.apache.org/xerces2-j/features.html#external-general-entities
+            // JDK7+ - http://xml.org/sax/features/external-general-entities
+            // This feature has to be used together with the following one, 
otherwise it will not protect you from XXE for sure.
+            feature = "http://xml.org/sax/features/external-general-entities";;
+            dbf.setFeature(feature, false);
+
+            // Xerces 1 - 
http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
+            // Xerces 2 - 
http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
+            // JDK7+ - http://xml.org/sax/features/external-parameter-entities
+            // This feature has to be used together with the previous one, 
otherwise it will not protect you from XXE for sure.
+            feature = 
"http://xml.org/sax/features/external-parameter-entities";;
+            dbf.setFeature(feature, false);
+
+            // Disable external DTDs as well
+            feature = 
"http://apache.org/xml/features/nonvalidating/load-external-dtd";;
+            dbf.setFeature(feature, false);
+
+            // and these as well, per Timothy Morgan's 2014 paper: "XML 
Schema, DTD, and Entity Attacks"
+            dbf.setXIncludeAware(false);
+            dbf.setExpandEntityReferences(false);
+
+        } catch (final ParserConfigurationException error) {
+            final String message = String.format("`%s` is probably not 
supported by your XML processor", feature);
+            throw new RuntimeException(message, error);
+        }
+        return dbf;
+    }
+
+}
diff --git 
a/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlWriter.java
 
b/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlWriter.java
index efc713dbaf..ed1765d199 100644
--- 
a/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlWriter.java
+++ 
b/log4j-internal-util/src/main/java/org/apache/logging/log4j/internal/util/XmlWriter.java
@@ -56,7 +56,7 @@ public final class XmlWriter {
         try {
 
             // Create the document.
-            final DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory.newInstance();
+            final DocumentBuilderFactory documentBuilderFactory = 
XmlUtils.createDocumentBuilderFactory();
             final DocumentBuilder documentBuilder = 
documentBuilderFactory.newDocumentBuilder();
 
             // Append the license comment.

Reply via email to