[apache-log4j2] 01/01: Fixed CVE-2017-5645: Remote code execution with the TCP/UDP socket server (Closes: #860489)
Emmanuel Bourg
ebourg-guest at moszumanska.debian.org
Tue Apr 18 12:46:10 UTC 2017
This is an automated email from the git hooks/post-receive script.
ebourg-guest pushed a commit to branch master
in repository apache-log4j2.
commit 799b96337bcf909193aa76c6090ba511c05b64f6
Author: Emmanuel Bourg <ebourg at apache.org>
Date: Tue Apr 18 14:44:43 2017 +0200
Fixed CVE-2017-5645: Remote code execution with the TCP/UDP socket server (Closes: #860489)
---
debian/changelog | 10 ++
debian/patches/CVE-2017-5645.patch | 253 +++++++++++++++++++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 264 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 5ad7abc..4fb99f5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+apache-log4j2 (2.7-2) unstable; urgency=medium
+
+ * Team upload.
+ * Fixed CVE-2017-5645: When using the TCP socket server or UDP socket server
+ to receive serialized log events from another application, a specially
+ crafted binary payload can be sent that, when deserialized, can execute
+ arbitrary code (Closes: #860489)
+
+ -- Emmanuel Bourg <ebourg at apache.org> Tue, 18 Apr 2017 14:30:00 +0200
+
apache-log4j2 (2.7-1) unstable; urgency=medium
* Team upload.
diff --git a/debian/patches/CVE-2017-5645.patch b/debian/patches/CVE-2017-5645.patch
new file mode 100644
index 0000000..d5e8327
--- /dev/null
+++ b/debian/patches/CVE-2017-5645.patch
@@ -0,0 +1,253 @@
+Description: CVE-2017-5645: When using the TCP socket server or UDP socket
+ server to receive serialized log events from another application,
+ a specially crafted binary payload can be sent that, when deserialized,
+ can execute arbitrary code.
+ .
+ This patch adds class filtering to AbstractSocketServer. This allows
+ a whitelist of class names to be specified to configure which classes
+ are allowed to be deserialized in both TcpSocketServer and UdpSocketServer.
+Origin: backport, https://github.com/apache/logging-log4j2/commit/5dcc192
+Bug: https://issues.apache.org/jira/browse/LOG4J2-1863
+Bug-Debian: https://bugs.debian.org/860489
+--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/AbstractSocketServer.java
++++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/AbstractSocketServer.java
+@@ -25,6 +25,8 @@
+ import java.net.MalformedURLException;
+ import java.net.URI;
+ import java.net.URL;
++import java.util.Collections;
++import java.util.List;
+ import java.util.Objects;
+
+ import org.apache.logging.log4j.LogManager;
+@@ -71,6 +73,9 @@
+ "-a" }, converter = InetAddressConverter.class, description = "Server socket local bind address.")
+ private InetAddress localBindAddress;
+
++ @Parameter(names = {"--classes", "-C"}, description = "Additional classes to allow deserialization")
++ private List<String> allowedClasses;
++
+ String getConfigLocation() {
+ return configLocation;
+ }
+@@ -102,6 +107,14 @@
+ void setLocalBindAddress(InetAddress localBindAddress) {
+ this.localBindAddress = localBindAddress;
+ }
++
++ List<String> getAllowedClasses() {
++ return allowedClasses == null ? Collections.<String>emptyList() : allowedClasses;
++ }
++
++ void setAllowedClasses(final List<String> allowedClasses) {
++ this.allowedClasses = allowedClasses;
++ }
+ }
+
+ /**
+--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/ObjectInputStreamLogEventBridge.java
++++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/ObjectInputStreamLogEventBridge.java
+@@ -19,15 +19,34 @@
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.ObjectInputStream;
++import java.util.Collections;
++import java.util.List;
+
+ import org.apache.logging.log4j.core.LogEvent;
+ import org.apache.logging.log4j.core.LogEventListener;
++import org.apache.logging.log4j.core.util.FilteredObjectInputStream;
+
+ /**
+ * Reads and logs serialized {@link LogEvent} objects from an {@link ObjectInputStream}.
+ */
+ public class ObjectInputStreamLogEventBridge extends AbstractLogEventBridge<ObjectInputStream> {
+
++ private final List<String> allowedClasses;
++
++ public ObjectInputStreamLogEventBridge() {
++ this(Collections.<String>emptyList());
++ }
++
++ /**
++ * Constructs an ObjectInputStreamLogEventBridge with additional allowed classes to deserialize.
++ *
++ * @param allowedClasses class names to also allow for deserialization
++ * @since 2.8.2
++ */
++ public ObjectInputStreamLogEventBridge(final List<String> allowedClasses) {
++ this.allowedClasses = allowedClasses;
++ }
++
+ @Override
+ public void logEvents(final ObjectInputStream inputStream, final LogEventListener logEventListener)
+ throws IOException {
+@@ -40,6 +59,6 @@
+
+ @Override
+ public ObjectInputStream wrapStream(final InputStream inputStream) throws IOException {
+- return new ObjectInputStream(inputStream);
++ return new FilteredObjectInputStream(inputStream, allowedClasses);
+ }
+ }
+--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/TcpSocketServer.java
++++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/TcpSocketServer.java
+@@ -26,6 +26,8 @@
+ import java.net.InetAddress;
+ import java.net.ServerSocket;
+ import java.net.Socket;
++import java.util.Collections;
++import java.util.List;
+ import java.nio.charset.Charset;
+ import java.util.Map;
+ import java.util.concurrent.ConcurrentHashMap;
+@@ -154,9 +156,26 @@
+ */
+ public static TcpSocketServer<ObjectInputStream> createSerializedSocketServer(final int port, final int backlog,
+ InetAddress localBindAddress) throws IOException {
++ return createSerializedSocketServer(port, backlog, localBindAddress, Collections.<String>emptyList());
++ }
++
++ /**
++ * Creates a socket server that reads serialized log events.
++ *
++ * @param port the port to listen
++ * @param localBindAddress The server socket's local bin address
++ * @param allowedClasses additional class names to allow for deserialization
++ * @return a new a socket server
++ * @throws IOException
++ * if an I/O error occurs when opening the socket.
++ * @since 2.8.2
++ */
++ public static TcpSocketServer<ObjectInputStream> createSerializedSocketServer(
++ final int port, final int backlog, final InetAddress localBindAddress, final List<String> allowedClasses
++ ) throws IOException {
+ LOGGER.entry(port);
+ final TcpSocketServer<ObjectInputStream> socketServer = new TcpSocketServer<>(port, backlog, localBindAddress,
+- new ObjectInputStreamLogEventBridge());
++ new ObjectInputStreamLogEventBridge(allowedClasses));
+ return LOGGER.exit(socketServer);
+ }
+
+@@ -191,8 +210,8 @@
+ if (cla.getConfigLocation() != null) {
+ ConfigurationFactory.setConfigurationFactory(new ServerConfigurationFactory(cla.getConfigLocation()));
+ }
+- final TcpSocketServer<ObjectInputStream> socketServer = TcpSocketServer
+- .createSerializedSocketServer(cla.getPort(), cla.getBacklog(), cla.getLocalBindAddress());
++ final TcpSocketServer<ObjectInputStream> socketServer = TcpSocketServer.createSerializedSocketServer(
++ cla.getPort(), cla.getBacklog(), cla.getLocalBindAddress(), cla.getAllowedClasses());
+ final Thread serverThread = new Log4jThread(socketServer);
+ serverThread.start();
+ if (cla.isInteractive()) {
+--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/UdpSocketServer.java
++++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/UdpSocketServer.java
+@@ -26,6 +26,7 @@
+ import java.io.OptionalDataException;
+ import java.net.DatagramPacket;
+ import java.net.DatagramSocket;
++import java.util.List;
+
+ import org.apache.logging.log4j.core.config.ConfigurationFactory;
+ import org.apache.logging.log4j.core.util.Log4jThread;
+@@ -66,6 +67,21 @@
+ }
+
+ /**
++ * Creates a socket server that reads serialized log events.
++ *
++ * @param port the port to listen
++ * @param allowedClasses additional classes to allow for deserialization
++ * @return a new a socket server
++ * @throws IOException if an I/O error occurs when opening the socket.
++ * @since 2.8.2
++ */
++ public static UdpSocketServer<ObjectInputStream> createSerializedSocketServer(final int port,
++ final List<String> allowedClasses)
++ throws IOException {
++ return new UdpSocketServer<>(port, new ObjectInputStreamLogEventBridge(allowedClasses));
++ }
++
++ /**
+ * Creates a socket server that reads XML log events.
+ *
+ * @param port
+@@ -95,7 +111,7 @@
+ ConfigurationFactory.setConfigurationFactory(new ServerConfigurationFactory(cla.getConfigLocation()));
+ }
+ final UdpSocketServer<ObjectInputStream> socketServer = UdpSocketServer
+- .createSerializedSocketServer(cla.getPort());
++ .createSerializedSocketServer(cla.getPort(), cla.getAllowedClasses());
+ final Thread serverThread = new Log4jThread(socketServer);
+ serverThread.start();
+ if (cla.isInteractive()) {
+--- /dev/null
++++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FilteredObjectInputStream.java
+@@ -0,0 +1,67 @@
++/*
++ * 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.core.util;
++
++import java.io.IOException;
++import java.io.InputStream;
++import java.io.InvalidObjectException;
++import java.io.ObjectInputStream;
++import java.io.ObjectStreamClass;
++import java.util.Arrays;
++import java.util.Collection;
++import java.util.List;
++
++/**
++ * Extended ObjectInputStream that only allows certain classes to be deserialized.
++ *
++ * @since 2.8.2
++ */
++public class FilteredObjectInputStream extends ObjectInputStream {
++
++ private static final List<String> REQUIRED_JAVA_CLASSES = Arrays.asList(
++ // for StandardLevel
++ "java.lang.Enum",
++ // for location information
++ "java.lang.StackTraceElement",
++ // for Message delegate
++ "java.rmi.MarshalledObject",
++ "[B"
++ );
++
++ private final Collection<String> allowedClasses;
++
++ public FilteredObjectInputStream(final InputStream in, final Collection<String> allowedClasses) throws IOException {
++ super(in);
++ this.allowedClasses = allowedClasses;
++ }
++
++ @Override
++ protected Class<?> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
++ String name = desc.getName();
++ if (!(isAllowedByDefault(name) || allowedClasses.contains(name))) {
++ throw new InvalidObjectException("Class is not allowed for deserialization: " + name);
++ }
++ return super.resolveClass(desc);
++ }
++
++ private static boolean isAllowedByDefault(final String name) {
++ return name.startsWith("org.apache.logging.log4j.") ||
++ name.startsWith("[Lorg.apache.logging.log4j.") ||
++ REQUIRED_JAVA_CLASSES.contains(name);
++ }
++
++}
diff --git a/debian/patches/series b/debian/patches/series
index a5195ad..257f7b6 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,4 @@
01-disable-kafka-appender.patch
02-jackson-compatibility.patch
03-mongodb-compatibility.patch
+CVE-2017-5645.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/apache-log4j2.git
More information about the pkg-java-commits
mailing list