[Git][java-team/logback][master] 2 commits: Add patch for CVE-2023-6378 (Closes: #1057423)

Tony Mancill (@tmancill) gitlab at salsa.debian.org
Tue Dec 5 07:09:51 GMT 2023



Tony Mancill pushed to branch master at Debian Java Maintainers / logback


Commits:
0fd3b246 by tony mancill at 2023-12-04T22:42:05-08:00
Add patch for CVE-2023-6378 (Closes: #1057423)

- - - - -
6f3d9836 by tony mancill at 2023-12-04T22:47:12-08:00
Prepare changelog for upload

- - - - -


3 changed files:

- debian/changelog
- + debian/patches/07-CVE-2023-6378.patch
- debian/patches/series


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,9 @@
+logback (1:1.2.11-5) unstable; urgency=medium
+
+  * Add patch for CVE-2023-6378 (Closes: #1057423)
+
+ -- tony mancill <tmancill at debian.org>  Mon, 04 Dec 2023 22:42:09 -0800
+
 logback (1:1.2.11-4) unstable; urgency=medium
 
   * Add clean target for back-to-back builds (Closes: #1048763)


=====================================
debian/patches/07-CVE-2023-6378.patch
=====================================
@@ -0,0 +1,456 @@
+From bb095154be011267b64e37a1d401546e7cc2b7c3 Mon Sep 17 00:00:00 2001
+From: Ceki Gulcu <ceki at qos.ch>
+Date: Fri, 1 Dec 2023 15:12:22 +0100
+Subject: [PATCH] fix CVE-2023-6378
+
+Signed-off-by: Ceki Gulcu <ceki at qos.ch>
+---
+ .../logback/classic/spi/LoggingEventVO.java   |  7 ++
+ .../src/test/input/issue/logback-1754.xml     | 30 +++++++
+ .../issue/logback_1754/LogbackTest.java       | 78 +++++++++++++++++++
+ .../core/net/HardenedObjectInputStream.java   | 55 ++++++++++++-
+ .../ch/qos/logback/core/util/EnvUtil.java     | 39 ++++++----
+ .../net/HardenedObjectInputStreamTest.java    | 49 +++++++++++-
+ .../rolling/ScaffoldingForRollingTests.java   |  2 +-
+ .../ch/qos/logback/core/util/EnvUtilTest.java | 34 ++++++++
+ 8 files changed, 275 insertions(+), 19 deletions(-)
+ create mode 100644 logback-classic/src/test/input/issue/logback-1754.xml
+ create mode 100644 logback-classic/src/test/java/ch/qos/logback/classic/issue/logback_1754/LogbackTest.java
+ create mode 100644 logback-core/src/test/java/ch/qos/logback/core/util/EnvUtilTest.java
+
+diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEventVO.java b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEventVO.java
+index e21350b2cc..ea2c6ac128 100644
+--- a/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEventVO.java
++++ b/logback-classic/src/main/java/ch/qos/logback/classic/spi/LoggingEventVO.java
+@@ -14,6 +14,7 @@
+ package ch.qos.logback.classic.spi;
+ 
+ import java.io.IOException;
++import java.io.InvalidObjectException;
+ import java.io.ObjectInputStream;
+ import java.io.ObjectOutputStream;
+ import java.io.Serializable;
+@@ -38,6 +39,7 @@ public class LoggingEventVO implements ILoggingEvent, Serializable {
+ 
+     private static final int NULL_ARGUMENT_ARRAY = -1;
+     private static final String NULL_ARGUMENT_ARRAY_ELEMENT = "NULL_ARGUMENT_ARRAY_ELEMENT";
++    private static final int ARGUMENT_ARRAY_DESERIALIZATION_LIMIT = 128;
+ 
+     private String threadName;
+     private String loggerName;
+@@ -181,6 +183,11 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
+         level = Level.toLevel(levelInt);
+ 
+         int argArrayLen = in.readInt();
++        // Prevent DOS attacks via large or negative arrays
++        if (argArrayLen < NULL_ARGUMENT_ARRAY || argArrayLen > ARGUMENT_ARRAY_DESERIALIZATION_LIMIT) {
++            throw new InvalidObjectException("Argument array length is invalid: " + argArrayLen);
++        }
++
+         if (argArrayLen != NULL_ARGUMENT_ARRAY) {
+             argumentArray = new String[argArrayLen];
+             for (int i = 0; i < argArrayLen; i++) {
+diff --git a/logback-classic/src/test/input/issue/logback-1754.xml b/logback-classic/src/test/input/issue/logback-1754.xml
+new file mode 100644
+index 0000000000..ab41185a34
+--- /dev/null
++++ b/logback-classic/src/test/input/issue/logback-1754.xml
+@@ -0,0 +1,30 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!--
++  ~ Logback: the reliable, generic, fast and flexible logging framework.
++  ~ Copyright (C) 1999-2023, QOS.ch. All rights reserved.
++  ~
++  ~ This program and the accompanying materials are dual-licensed under
++  ~ either the terms of the Eclipse Public License v1.0 as published by
++  ~ the Eclipse Foundation
++  ~
++  ~   or (per the licensee's choosing)
++  ~
++  ~ under the terms of the GNU Lesser General Public License version 2.1
++  ~ as published by the Free Software Foundation.
++  -->
++
++<configuration debug="true">
++    <appender name="GENERAL" class="ch.qos.logback.core.rolling.RollingFileAppender">
++        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
++            <fileNamePattern>${logback_1754_targetDirectory}/test-%d{yyyy-MM-dd}.log</fileNamePattern>
++            <maxHistory>120</maxHistory>
++        </rollingPolicy>
++        <encoder>
++            <pattern>%date{HH:mm:ss.SSS} [%level] %logger{0} [%thread] [%class{3}:%line] : %msg%n</pattern>
++        </encoder>
++        <prudent>true</prudent>
++    </appender>
++    <root level="debug">
++        <appender-ref ref="GENERAL" />
++    </root>
++</configuration>
+\ No newline at end of file
+diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/logback_1754/LogbackTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/logback_1754/LogbackTest.java
+new file mode 100644
+index 0000000000..3001c00a66
+--- /dev/null
++++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/logback_1754/LogbackTest.java
+@@ -0,0 +1,78 @@
++/*
++ * Logback: the reliable, generic, fast and flexible logging framework.
++ * Copyright (C) 1999-2023, QOS.ch. All rights reserved.
++ *
++ * This program and the accompanying materials are dual-licensed under
++ * either the terms of the Eclipse Public License v1.0 as published by
++ * the Eclipse Foundation
++ *
++ *   or (per the licensee's choosing)
++ *
++ * under the terms of the GNU Lesser General Public License version 2.1
++ * as published by the Free Software Foundation.
++ */
++
++package ch.qos.logback.classic.issue.logback_1754;
++
++import ch.qos.logback.classic.ClassicConstants;
++import ch.qos.logback.classic.ClassicTestConstants;
++import ch.qos.logback.core.testUtil.RandomUtil;
++import org.slf4j.Logger;
++import org.slf4j.LoggerFactory;
++
++import java.util.ArrayList;
++import java.util.List;
++import java.util.concurrent.CountDownLatch;
++
++import static ch.qos.logback.classic.util.ContextInitializer.CONFIG_FILE_PROPERTY;
++
++public class LogbackTest {
++
++    private static final int THREADS = 16;
++
++    private void runTest() {
++
++        int diff = RandomUtil.getPositiveInt();
++        //System.setProperty("logback.statusListenerClass", "sysout");
++        System.setProperty(CONFIG_FILE_PROPERTY, ClassicTestConstants.INPUT_PREFIX+"issue/logback-1754.xml");
++        System.setProperty("logback_1754_targetDirectory", ClassicTestConstants.OUTPUT_DIR_PREFIX+"safeWrite_"+diff);
++
++        CountDownLatch latch = new CountDownLatch(THREADS);
++        List<Thread> threads = new ArrayList<Thread>(THREADS);
++        for (int i = 0; i < THREADS; i++) {
++            LoggerThread thread = new LoggerThread(latch, "message from thread " + i);
++            thread.start();
++            threads.add(thread);
++        }
++        for (Thread thread : threads) {
++            try {
++                thread.join();
++            } catch (InterruptedException e) {
++                Thread.currentThread().interrupt();
++                throw new RuntimeException(e);
++            }
++        }
++    }
++
++    public static void main(String... args) {
++        new LogbackTest().runTest();
++    }
++
++    private static final class LoggerThread extends Thread {
++        private static final Logger LOG = LoggerFactory.getLogger(LoggerThread.class);
++        private final CountDownLatch latch;
++        private final String message;
++
++        LoggerThread(CountDownLatch latch, String message) {
++            setDaemon(false);
++            this.latch = latch;
++            this.message = message;
++        }
++
++        @Override
++        public void run() {
++            latch.countDown();
++            LOG.info(message);
++        }
++    }
++}
+diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java b/logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java
+index d1b7301ea4..0674aaf3ea 100755
+--- a/logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java
++++ b/logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java
+@@ -1,10 +1,27 @@
++/**
++ * Logback: the reliable, generic, fast and flexible logging framework.
++ * Copyright (C) 1999-2023, QOS.ch. All rights reserved.
++ *
++ * This program and the accompanying materials are dual-licensed under
++ * either the terms of the Eclipse Public License v1.0 as published by
++ * the Eclipse Foundation
++ *
++ *   or (per the licensee's choosing)
++ *
++ * under the terms of the GNU Lesser General Public License version 2.1
++ * as published by the Free Software Foundation.
++ */
+ package ch.qos.logback.core.net;
+ 
++import ch.qos.logback.core.util.EnvUtil;
++
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.InvalidClassException;
+ import java.io.ObjectInputStream;
+ import java.io.ObjectStreamClass;
++import java.lang.reflect.InvocationTargetException;
++import java.lang.reflect.Method;
+ import java.util.ArrayList;
+ import java.util.List;
+ 
+@@ -22,10 +39,12 @@ public class HardenedObjectInputStream extends ObjectInputStream {
+ 
+     final List<String> whitelistedClassNames;
+     final static String[] JAVA_PACKAGES = new String[] { "java.lang", "java.util" };
++    final private static int DEPTH_LIMIT = 16;
++    final private static int ARRAY_LIMIT = 10000;
+ 
+     public HardenedObjectInputStream(InputStream in, String[] whilelist) throws IOException {
+         super(in);
+-
++        initObjectFilter();
+         this.whitelistedClassNames = new ArrayList<String>();
+         if (whilelist != null) {
+             for (int i = 0; i < whilelist.length; i++) {
+@@ -36,11 +55,43 @@ public HardenedObjectInputStream(InputStream in, String[] whilelist) throws IOEx
+ 
+     public HardenedObjectInputStream(InputStream in, List<String> whitelist) throws IOException {
+         super(in);
+-
++        initObjectFilter();
+         this.whitelistedClassNames = new ArrayList<String>();
+         this.whitelistedClassNames.addAll(whitelist);
+     }
+ 
++    private void initObjectFilter() {
++
++        // invoke the following code by reflection
++        //  this.setObjectInputFilter(ObjectInputFilter.Config.createFilter(
++        //                "maxarray=" + ARRAY_LIMIT + ";maxdepth=" + DEPTH_LIMIT + ";"
++        //        ));
++        if(EnvUtil.isJDK9OrHigher()) {
++            try {
++                ClassLoader classLoader = this.getClass().getClassLoader();
++
++                Class oifClass = classLoader.loadClass("java.io.ObjectInputFilter");
++                Class oifConfigClass = classLoader.loadClass("java.io.ObjectInputFilter$Config");
++                Method setObjectInputFilterMethod = this.getClass().getMethod("setObjectInputFilter", oifClass);
++
++                Method createFilterMethod = oifConfigClass.getMethod("createFilter", String.class);
++                Object filter = createFilterMethod.invoke(null, "maxarray=" + ARRAY_LIMIT + ";maxdepth=" + DEPTH_LIMIT + ";");
++                setObjectInputFilterMethod.invoke(this, filter);
++            } catch (ClassNotFoundException e) {
++                // this code should be unreachable
++                throw new RuntimeException("Failed to initialize object filter", e);
++            } catch (InvocationTargetException e) {
++                // this code should be unreachable
++                throw new RuntimeException("Failed to initialize object filter", e);
++            } catch (NoSuchMethodException e) {
++                // this code should be unreachable
++                throw new RuntimeException("Failed to initialize object filter", e);
++            } catch (IllegalAccessException e) {
++                // this code should be unreachable
++                throw new RuntimeException("Failed to initialize object filter", e);
++            }
++        }
++    }
+     @Override
+     protected Class<?> resolveClass(ObjectStreamClass anObjectStreamClass) throws IOException, ClassNotFoundException {
+         
+diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/EnvUtil.java b/logback-core/src/main/java/ch/qos/logback/core/util/EnvUtil.java
+index c200a1c984..f3dcd0cfe3 100644
+--- a/logback-core/src/main/java/ch/qos/logback/core/util/EnvUtil.java
++++ b/logback-core/src/main/java/ch/qos/logback/core/util/EnvUtil.java
+@@ -1,6 +1,6 @@
+ /**
+  * Logback: the reliable, generic, fast and flexible logging framework.
+- * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
++ * Copyright (C) 1999-2023, QOS.ch. All rights reserved.
+  *
+  * This program and the accompanying materials are dual-licensed under
+  * either the terms of the Eclipse Public License v1.0 as published by
+@@ -22,22 +22,27 @@
+ public class EnvUtil {
+ 
+     static private boolean isJDK_N_OrHigher(int n) {
+-        List<String> versionList = new ArrayList<String>();
+-        // this code should work at least until JDK 10 (assuming n parameter is
+-        // always 6 or more)
+-        for (int i = 0; i < 5; i++) {
+-            versionList.add("1." + (n + i));
+-        }
+-
+-        String javaVersion = System.getProperty("java.version");
+-        if (javaVersion == null) {
++        String javaVersionStr = System.getProperty("java.version", "");
++        if (javaVersionStr.isEmpty())
+             return false;
++
++        int version = getJDKVersion(javaVersionStr);
++        return version > 0 && n <= version;
++    }
++
++    static public int getJDKVersion(String javaVersionStr) {
++        int version = 0;
++
++        for (char ch : javaVersionStr.toCharArray()) {
++            if (Character.isDigit(ch)) {
++                version = (version * 10) + (ch - 48);
++            } else if (version == 1) {
++                version = 0;
++            } else {
++                break;
++            }
+         }
+-        for (String v : versionList) {
+-            if (javaVersion.startsWith(v))
+-                return true;
+-        }
+-        return false;
++        return version;
+     }
+ 
+     static public boolean isJDK5() {
+@@ -52,6 +57,10 @@ static public boolean isJDK7OrHigher() {
+         return isJDK_N_OrHigher(7);
+     }
+ 
++    static public boolean isJDK9OrHigher() {
++        return isJDK_N_OrHigher(9);
++    }
++
+     static public boolean isJaninoAvailable() {
+         ClassLoader classLoader = EnvUtil.class.getClassLoader();
+         try {
+diff --git a/logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java b/logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java
+index ff4ddc599f..36f7f11b59 100755
+--- a/logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java
++++ b/logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java
+@@ -1,12 +1,17 @@
+ package ch.qos.logback.core.net;
+ 
+ import static org.junit.Assert.assertEquals;
++import static org.junit.Assert.fail;
+ 
+ import java.io.ByteArrayInputStream;
+ import java.io.ByteArrayOutputStream;
+ import java.io.IOException;
++import java.io.InvalidClassException;
+ import java.io.ObjectOutputStream;
++import java.util.HashSet;
++import java.util.Set;
+ 
++import ch.qos.logback.core.util.EnvUtil;
+ import org.junit.After;
+ import org.junit.Before;
+ import org.junit.Test;
+@@ -54,5 +59,47 @@ private void writeObject(ObjectOutputStream oos, Object o) throws IOException {
+         oos.flush();
+         oos.close();
+     }
+-    
++
++    @Test
++    public void denialOfService() throws ClassNotFoundException, IOException {
++
++        if(!EnvUtil.isJDK9OrHigher()) {
++            return;
++        }
++
++        ByteArrayInputStream bis = new ByteArrayInputStream(payload());
++        inputStream = new HardenedObjectInputStream(bis, whitelist);
++        try {
++            inputStream.readObject();
++            fail("InvalidClassException expected");
++        } catch(InvalidClassException e) {
++        }
++        finally {
++            inputStream.close();
++        }
++    }
++
++    private byte[] payload() throws IOException {
++        Set root = buildEvilHashset();
++        writeObject(oos, root);
++        return bos.toByteArray();
++    }
++
++    private Set buildEvilHashset() {
++        Set root = new HashSet();
++        Set s1 = root;
++        Set s2 = new HashSet();
++        for (int i = 0; i < 100; i++) {
++            Set t1 = new HashSet();
++            Set t2 = new HashSet();
++            t1.add("foo"); // make it not equal to t2
++            s1.add(t1);
++            s1.add(t2);
++            s2.add(t1);
++            s2.add(t2);
++            s1 = t1;
++            s2 = t2;
++        }
++        return root;
++    }
+ }
+diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/ScaffoldingForRollingTests.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/ScaffoldingForRollingTests.java
+index 57389be3f7..504b52adc2 100755
+--- a/logback-core/src/test/java/ch/qos/logback/core/rolling/ScaffoldingForRollingTests.java
++++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/ScaffoldingForRollingTests.java
+@@ -24,10 +24,10 @@
+ 
+ import java.io.File;
+ import java.io.IOException;
+-import java.sql.Date;
+ import java.text.SimpleDateFormat;
+ import java.util.ArrayList;
+ import java.util.Calendar;
++import java.util.Date;
+ import java.util.Enumeration;
+ import java.util.List;
+ import java.util.concurrent.Future;
+diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/EnvUtilTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/EnvUtilTest.java
+new file mode 100644
+index 0000000000..2ee4abd42e
+--- /dev/null
++++ b/logback-core/src/test/java/ch/qos/logback/core/util/EnvUtilTest.java
+@@ -0,0 +1,34 @@
++/**
++ * Logback: the reliable, generic, fast and flexible logging framework.
++ * Copyright (C) 1999-2023, QOS.ch. All rights reserved.
++ *
++ * This program and the accompanying materials are dual-licensed under
++ * either the terms of the Eclipse Public License v1.0 as published by
++ * the Eclipse Foundation
++ *
++ *   or (per the licensee's choosing)
++ *
++ * under the terms of the GNU Lesser General Public License version 2.1
++ * as published by the Free Software Foundation.
++ */
++package ch.qos.logback.core.util;
++
++import org.junit.Test;
++
++import static org.junit.Assert.assertEquals;
++
++public class EnvUtilTest {
++
++
++    @Test
++    public void jdkVersion() {
++        assertEquals(4, EnvUtil.getJDKVersion("1.4.xx"));
++        assertEquals(5, EnvUtil.getJDKVersion("1.5"));
++        assertEquals(5, EnvUtil.getJDKVersion("1.5.xx"));
++        assertEquals(5, EnvUtil.getJDKVersion("1.5AA"));
++        assertEquals(9, EnvUtil.getJDKVersion("9EA"));
++        assertEquals(9, EnvUtil.getJDKVersion("9.0.1"));
++        assertEquals(18, EnvUtil.getJDKVersion("18.3+xx"));
++        assertEquals(21, EnvUtil.getJDKVersion("21.0.1"));
++    }
++}


=====================================
debian/patches/series
=====================================
@@ -2,3 +2,4 @@
 04-privacy-breach.patch
 05-java11-compatibility.patch
 06-jetty-compatibility.patch
+07-CVE-2023-6378.patch



View it on GitLab: https://salsa.debian.org/java-team/logback/-/compare/90c336375304ccd1fbc32ab557dfa640b088982c...6f3d98365d1343265e6213179de7e17fd9becf28

-- 
View it on GitLab: https://salsa.debian.org/java-team/logback/-/compare/90c336375304ccd1fbc32ab557dfa640b088982c...6f3d98365d1343265e6213179de7e17fd9becf28
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20231205/69483193/attachment.htm>


More information about the pkg-java-commits mailing list