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.
