From ba5a39259a89b15347db404ed832fe90093e5fd0 Mon Sep 17 00:00:00 2001 From: Marian Koncek Date: Mon, 12 Apr 2021 17:32:28 +0200 Subject: [PATCH] Fix CVEs from 2021 --- .../com/thoughtworks/xstream/XStream.java | 43 ++++++++++++++++++- .../com/thoughtworks/xstream/core/JVM.java | 17 +++++++- .../security/TypeHierarchyPermission.java | 32 ++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java index 3ca31cc..cdc4673 100644 --- a/xstream/src/java/com/thoughtworks/xstream/XStream.java +++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java @@ -142,6 +142,7 @@ import java.util.TreeSet; import java.util.Vector; import java.util.regex.Pattern; +import com.thoughtworks.xstream.security.TypeHierarchyPermission; /** * Simple facade to XStream library, a Java-XML serialization tool.

@@ -322,6 +323,15 @@ public class XStream { public static final int PRIORITY_VERY_LOW = -20; private static final String ANNOTATION_MAPPER_TYPE = "com.thoughtworks.xstream.mapper.AnnotationMapper"; + + private static final Pattern GETTER_SETTER_REFLECTION = Pattern.compile(".*\\$GetterSetterReflection"); + private static final Pattern PRIVILEGED_GETTER = Pattern.compile(".*\\$PrivilegedGetter"); + private static final Pattern LAZY_ITERATORS = Pattern.compile(".*\\$LazyIterator"); + private static final Pattern JAXWS_ITERATORS = Pattern.compile(".*\\$ServiceNameIterator"); + private static final Pattern JAVAFX_OBSERVABLE_LIST__ = Pattern.compile( + "javafx\\.collections\\.ObservableList\\$.*"); + private static final Pattern JAVAX_CRYPTO = Pattern.compile("javax\\.crypto\\..*"); + private static final Pattern BCEL_CL = Pattern.compile(".*\\.bcel\\..*\\.util\\.ClassLoader"); /** * Constructs a default XStream. The instance will use the {@link XppDriver} as default and tries to determine the best @@ -545,7 +555,38 @@ public class XStream { } addPermission(AnyTypePermission.ANY); - denyTypes(new String[]{"javax.imageio.ImageIO$ContainsFilter"}); + denyTypes(new String[]{ + "java.beans.EventHandler", // + "java.lang.ProcessBuilder", // + "javax.imageio.ImageIO$ContainsFilter", // + "jdk.nashorn.internal.objects.NativeString", // + "com.sun.corba.se.impl.activation.ServerTableEntry", // + "com.sun.tools.javac.processing.JavacProcessingEnvironment$NameProcessIterator", // + "sun.awt.datatransfer.DataTransferer$IndexOrderComparator", // + "sun.swing.SwingLazyValue"}); + denyTypesByRegExp(new Pattern[]{ + LAZY_ITERATORS, GETTER_SETTER_REFLECTION, PRIVILEGED_GETTER, JAVAX_CRYPTO, JAXWS_ITERATORS, + JAVAFX_OBSERVABLE_LIST__, BCEL_CL}); + denyTypeHierarchy(InputStream.class); + denyTypeHierarchyDynamically("java.nio.channels.Channel"); + denyTypeHierarchyDynamically("javax.activation.DataSource"); + denyTypeHierarchyDynamically("javax.sql.rowset.BaseRowSet"); + allowTypeHierarchy(Exception.class); + } + + private void denyTypeHierarchyDynamically(String className) { + Class type = JVM.loadClassForName(className); + if (type != null) { + denyTypeHierarchy(type); + } + } + + public void denyTypeHierarchy(Class type) { + denyPermission(new TypeHierarchyPermission(type)); + } + + public void allowTypeHierarchy(Class type) { + addPermission(new TypeHierarchyPermission(type)); } protected void setupAliases() { diff --git a/xstream/src/java/com/thoughtworks/xstream/core/JVM.java b/xstream/src/java/com/thoughtworks/xstream/core/JVM.java index 3538523..9e6ad73 100644 --- a/xstream/src/java/com/thoughtworks/xstream/core/JVM.java +++ b/xstream/src/java/com/thoughtworks/xstream/core/JVM.java @@ -228,7 +228,22 @@ public class JVM { loaderCache = new HashMap(); return this; } - + + public static Class loadClassForName(String name) { + return loadClassForName(name, true); + } + + public static Class loadClassForName(String name, boolean initialize) { + try { + Class clazz = Class.forName(name, initialize, JVM.class.getClassLoader()); + return clazz; + } catch (LinkageError e) { + return null; + } catch (ClassNotFoundException e) { + return null; + } + } + public static void main(String[] args) { boolean reverse = false; Field[] fields = AttributedString.class.getDeclaredFields(); diff --git a/xstream/src/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java b/xstream/src/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java new file mode 100644 index 0000000..d476ddf --- /dev/null +++ b/xstream/src/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 23. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * Permission for a type hierarchy with a name matching one in the provided list. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class TypeHierarchyPermission implements TypePermission { + + private Class type; + + /** + * @since 1.4.7 + */ + public TypeHierarchyPermission(Class type) { + this.type = type; + } + + public boolean allows(Class type) { + if (type == null) + return false; + return this.type.isAssignableFrom(type); + } + +} -- 2.30.2