From f6c93fa6daa52ccc117099f53acfc9e9f9710719 Mon Sep 17 00:00:00 2001 From: wangxiao65 <287608437@qq.com> Date: Sat, 19 Sep 2020 16:22:54 +0800 Subject: [PATCH] fix CVE-2017-5929 --- CVE-2017-5929.patch | 303 ++++++++++++++++++++++++++++++++++++++++++++ logback.spec | 11 +- 2 files changed, 310 insertions(+), 4 deletions(-) create mode 100644 CVE-2017-5929.patch diff --git a/CVE-2017-5929.patch b/CVE-2017-5929.patch new file mode 100644 index 0000000..74756ac --- /dev/null +++ b/CVE-2017-5929.patch @@ -0,0 +1,303 @@ +From f46044b805bca91efe5fd6afe52257cd02f775f8 Mon Sep 17 00:00:00 2001 +From: Ceki Gulcu +Date: Tue, 7 Feb 2017 23:12:51 +0100 +Subject: [PATCH] harden serialization + +--- + .../classic/net/SimpleSocketServer.java | 1 - + .../LogbackClassicSerializationHelper.java | 28 ++++++++ + .../classic/LoggerSerializationTest.java | 10 ++- + .../core/net/HardenedObjectInputStream.java | 48 +++++++++++++ + .../net/HardenedObjectInputStreamTest.java | 61 ++++++++++++++++ + .../ch/qos/logback/core/net/Innocent.java | 69 +++++++++++++++++++ + 6 files changed, 214 insertions(+), 3 deletions(-) + create mode 100755 logback-classic/src/main/java/ch/qos/logback/classic/net/server/LogbackClassicSerializationHelper.java + create mode 100755 logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java + create mode 100755 logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java + create mode 100755 logback-core/src/test/java/ch/qos/logback/core/net/Innocent.java + +diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java +index 6d39a2473..3083f45ce 100755 +--- a/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java ++++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java +@@ -14,7 +14,6 @@ + package ch.qos.logback.classic.net; + + import java.io.IOException; +-import java.lang.reflect.Constructor; + import java.net.ServerSocket; + import java.net.Socket; + import java.util.ArrayList; +diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/server/LogbackClassicSerializationHelper.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/server/LogbackClassicSerializationHelper.java +new file mode 100755 +index 000000000..00a974f81 +--- /dev/null ++++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/server/LogbackClassicSerializationHelper.java +@@ -0,0 +1,28 @@ ++package ch.qos.logback.classic.net.server; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++import org.slf4j.helpers.BasicMarker; ++ ++import ch.qos.logback.classic.Logger; ++import ch.qos.logback.classic.spi.LoggerContextVO; ++import ch.qos.logback.classic.spi.LoggingEventVO; ++import ch.qos.logback.classic.spi.ThrowableProxyVO; ++ ++public class LogbackClassicSerializationHelper { ++ ++ ++ ++ static public List getWhilelist() { ++ List whitelist = new ArrayList(); ++ whitelist.add(LoggingEventVO.class.getName()); ++ whitelist.add(LoggerContextVO.class.getName()); ++ whitelist.add(ThrowableProxyVO.class.getName()); ++ whitelist.add(StackTraceElement.class.getName()); ++ whitelist.add(BasicMarker.class.getName()); ++ whitelist.add(BasicMarker.class.getName()); ++ whitelist.add(Logger.class.getName()); ++ return whitelist; ++ } ++} +diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java +index ec6cb01d7..618d1756e 100644 +--- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java ++++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java +@@ -14,7 +14,10 @@ + package ch.qos.logback.classic; + + import java.io.*; ++import java.util.List; + ++import ch.qos.logback.classic.net.server.LogbackClassicSerializationHelper; ++import ch.qos.logback.core.net.HardenedObjectInputStream; + import ch.qos.logback.core.util.CoreTestConstants; + import org.junit.After; + import org.junit.Before; +@@ -36,7 +39,8 @@ + ByteArrayOutputStream bos; + ObjectOutputStream oos; + ObjectInputStream inputStream; +- ++ List whitelist ; ++ + @Before + public void setUp() throws Exception { + lc = new LoggerContext(); +@@ -45,6 +49,8 @@ public void setUp() throws Exception { + // create the byte output stream + bos = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(bos); ++ whitelist = LogbackClassicSerializationHelper.getWhilelist(); ++ whitelist.add(Foo.class.getName()); + } + + @After +@@ -110,7 +116,7 @@ public void deepTreeSerialization() throws IOException { + private Foo writeAndRead(Foo foo) throws IOException, ClassNotFoundException { + writeObject(oos, foo); + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); +- inputStream = new ObjectInputStream(bis); ++ inputStream = new HardenedObjectInputStream(bis, whitelist); + Foo fooBack = readFooObject(inputStream); + inputStream.close(); + return fooBack; +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 +new file mode 100755 +index 000000000..439e2bde5 +--- /dev/null ++++ b/logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java +@@ -0,0 +1,48 @@ ++package ch.qos.logback.core.net; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.InvalidClassException; ++import java.io.ObjectInputStream; ++import java.io.ObjectStreamClass; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++ ++/** ++ * ++ * @author Ceki Gülcü ++ * @since 1.2.0 ++ */ ++public class HardenedObjectInputStream extends ObjectInputStream { ++ ++ List whitelistedClassNames; ++ String[] javaPackages = new String[] {"java.lang", "java.util"}; ++ ++ public HardenedObjectInputStream(InputStream in, List whilelist) throws IOException { ++ super(in); ++ this.whitelistedClassNames = Collections.synchronizedList(new ArrayList(whilelist)); ++ } ++ ++ @Override ++ protected Class resolveClass(ObjectStreamClass anObjectStreamClass) throws IOException, ClassNotFoundException { ++ String incomingClassName = anObjectStreamClass.getName(); ++ if(!isWhitelisted(incomingClassName)) { ++ throw new InvalidClassException("Unauthorized deserialization attempt", anObjectStreamClass.getName()); ++ } ++ ++ return super.resolveClass(anObjectStreamClass); ++ } ++ ++ private boolean isWhitelisted(String incomingClassName) { ++ for(int i = 0; i < javaPackages.length; i++) { ++ if(incomingClassName.startsWith(javaPackages[i])) ++ return true; ++ } ++ for(String className: whitelistedClassNames) { ++ if(incomingClassName.equals(className)) ++ return true; ++ } ++ return false; ++ } ++} +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 +new file mode 100755 +index 000000000..6a3489755 +--- /dev/null ++++ b/logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java +@@ -0,0 +1,61 @@ ++package ch.qos.logback.core.net; ++ ++import static org.junit.Assert.*; ++ ++import java.io.ByteArrayInputStream; ++import java.io.ByteArrayOutputStream; ++import java.io.IOException; ++import java.io.ObjectOutputStream; ++import java.util.ArrayList; ++import java.util.List; ++ ++import org.junit.After; ++import org.junit.Before; ++import org.junit.Test; ++ ++public class HardenedObjectInputStreamTest { ++ ++ ByteArrayOutputStream bos; ++ ObjectOutputStream oos; ++ HardenedObjectInputStream inputStream; ++ List whitelist = new ArrayList(); ++ ++ @Before ++ public void setUp() throws Exception { ++ whitelist.add(Innocent.class.getName()); ++ bos = new ByteArrayOutputStream(); ++ oos = new ObjectOutputStream(bos); ++ } ++ ++ @After ++ public void tearDown() throws Exception { ++ } ++ ++ @Test ++ public void smoke() throws ClassNotFoundException, IOException { ++ Innocent innocent = new Innocent(); ++ innocent.setAnInt(1); ++ innocent.setAnInteger(2); ++ innocent.setaString("smoke"); ++ Innocent back = writeAndRead(innocent); ++ assertEquals(innocent, back); ++ } ++ ++ ++ ++ private Innocent writeAndRead(Innocent innocent) throws IOException, ClassNotFoundException { ++ writeObject(oos, innocent); ++ ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ++ inputStream = new HardenedObjectInputStream(bis, whitelist); ++ Innocent fooBack = (Innocent) inputStream.readObject(); ++ inputStream.close(); ++ return fooBack; ++ } ++ ++ private void writeObject(ObjectOutputStream oos, Object o) throws IOException { ++ oos.writeObject(o); ++ oos.flush(); ++ oos.close(); ++ } ++ ++} +diff --git a/logback-core/src/test/java/ch/qos/logback/core/net/Innocent.java b/logback-core/src/test/java/ch/qos/logback/core/net/Innocent.java +new file mode 100755 +index 000000000..2cef5a08e +--- /dev/null ++++ b/logback-core/src/test/java/ch/qos/logback/core/net/Innocent.java +@@ -0,0 +1,69 @@ ++package ch.qos.logback.core.net; ++ ++public class Innocent implements java.io.Serializable { ++ ++ private static final long serialVersionUID = -1227008349289885025L; ++ ++ int anInt; ++ Integer anInteger; ++ String aString; ++ ++ public int getAnInt() { ++ return anInt; ++ } ++ ++ public void setAnInt(int anInt) { ++ this.anInt = anInt; ++ } ++ ++ public Integer getAnInteger() { ++ return anInteger; ++ } ++ ++ public void setAnInteger(Integer anInteger) { ++ this.anInteger = anInteger; ++ } ++ ++ public String getaString() { ++ return aString; ++ } ++ ++ public void setaString(String aString) { ++ this.aString = aString; ++ } ++ ++ @Override ++ public int hashCode() { ++ final int prime = 31; ++ int result = 1; ++ result = prime * result + ((aString == null) ? 0 : aString.hashCode()); ++ result = prime * result + anInt; ++ result = prime * result + ((anInteger == null) ? 0 : anInteger.hashCode()); ++ return result; ++ } ++ ++ @Override ++ public boolean equals(Object obj) { ++ if (this == obj) ++ return true; ++ if (obj == null) ++ return false; ++ if (getClass() != obj.getClass()) ++ return false; ++ Innocent other = (Innocent) obj; ++ if (aString == null) { ++ if (other.aString != null) ++ return false; ++ } else if (!aString.equals(other.aString)) ++ return false; ++ if (anInt != other.anInt) ++ return false; ++ if (anInteger == null) { ++ if (other.anInteger != null) ++ return false; ++ } else if (!anInteger.equals(other.anInteger)) ++ return false; ++ return true; ++ } ++ ++} diff --git a/logback.spec b/logback.spec index 33edb28..834ca50 100644 --- a/logback.spec +++ b/logback.spec @@ -1,16 +1,17 @@ Name: logback Version: 1.1.7 -Release: 6 +Release: 7 Summary: A Java logging library License: LGPLv2 or EPL URL: http://logback.qos.ch/ Source0: https://github.com/qos-ch/logback/archive/v_%{version}.tar.gz # servlet 3.1 support -Patch0001: %{name}-1.1.7-servlet.patch +Patch0001: %{name}-1.1.7-servlet.patch # Remove deprecate methods,otherwise it will cause compilation to fail -Patch0002: %{name}-1.1.7-jetty.patch -Patch0003: %{name}-1.1.7-tomcat.patch +Patch0002: %{name}-1.1.7-jetty.patch +Patch0003: %{name}-1.1.7-tomcat.patch +Patch0004: CVE-2017-5929.patch BuildRequires: java-devel >= 1:1.6.0 maven-local mvn(javax.mail:mail) BuildRequires: mvn(javax.servlet:javax.servlet-api) mvn(junit:junit) mvn(log4j:log4j:1.2.17) @@ -139,5 +140,7 @@ cp -r %{name}-examples/pom.xml %{name}-examples/src %{buildroot}%{_datadir}/%{na %files help -f .mfiles-javadoc %changelog +* Sat Sep 19 2020 wangxiao - 1.1.7-7 +- fix CVE-2017-5929 * Wed Mar 4 2020 dingyiming - 1.1.7-6 - Package init