Rebase CVE-2021-21341-to-CVE-2021-21351.patch
Markus Koschany
3 years ago
0 | From: Markus Koschany <apo@debian.org> | |
1 | Date: Sat, 3 Apr 2021 21:15:39 +0200 | |
2 | Subject: CVE-2021-21341-to-CVE-2021-21351 | |
3 | ||
4 | Bug-Debian: https://bugs.debian.org/985843 | |
5 | Origin: https://github.com/x-stream/xstream/commit/d5e51177634afea7213b9dc2d21f101d2e258db9 | |
6 | --- | |
7 | .../src/java/com/thoughtworks/xstream/XStream.java | 32 +++++++++++++--- | |
8 | .../acceptance/SecurityVulnerabilityTest.java | 43 ++++++++++++++++++++++ | |
9 | 2 files changed, 70 insertions(+), 5 deletions(-) | |
10 | ||
11 | diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java | |
12 | index 8415da2..b5e43af 100644 | |
13 | --- a/xstream/src/java/com/thoughtworks/xstream/XStream.java | |
14 | +++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java | |
15 | @@ -1,6 +1,6 @@ | |
16 | /* | |
17 | * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes. | |
18 | - * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2020 XStream Committers. | |
19 | + * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2020, 2021 XStream Committers. | |
20 | * All rights reserved. | |
21 | * | |
22 | * The software in this package is published under the terms of the BSD | |
23 | @@ -36,7 +36,6 @@ import java.net.URL; | |
24 | import java.nio.charset.Charset; | |
25 | import java.text.DecimalFormatSymbols; | |
26 | import java.util.ArrayList; | |
27 | -import java.util.Arrays; | |
28 | import java.util.BitSet; | |
29 | import java.util.Calendar; | |
30 | import java.util.Collection; | |
31 | @@ -335,9 +334,14 @@ public class XStream { | |
32 | ||
33 | private static final String ANNOTATION_MAPPER_TYPE = "com.thoughtworks.xstream.mapper.AnnotationMapper"; | |
34 | private static final Pattern IGNORE_ALL = Pattern.compile(".*"); | |
35 | + private static final Pattern GETTER_SETTER_REFLECTION = Pattern.compile(".*\\$GetterSetterReflection"); | |
36 | + private static final Pattern PRIVILEGED_GETTER = Pattern.compile(".*\\$PrivilegedGetter"); | |
37 | private static final Pattern LAZY_ITERATORS = Pattern.compile(".*\\$LazyIterator"); | |
38 | + private static final Pattern JAXWS_ITERATORS = Pattern.compile(".*\\$ServiceNameIterator"); | |
39 | + private static final Pattern JAVAFX_OBSERVABLE_LIST__ = Pattern.compile( | |
40 | + "javafx\\.collections\\.ObservableList\\$.*"); | |
41 | private static final Pattern JAVAX_CRYPTO = Pattern.compile("javax\\.crypto\\..*"); | |
42 | - private static final Pattern JAXWS_FILE_STREAM = Pattern.compile(".*\\.ReadAllStream\\$FileStream"); | |
43 | + private static final Pattern BCEL_CL = Pattern.compile(".*\\.bcel\\..*\\.util\\.ClassLoader"); | |
44 | ||
45 | /** | |
46 | * Constructs a default XStream. | |
47 | @@ -647,12 +651,30 @@ public class XStream { | |
48 | "java.beans.EventHandler", // | |
49 | "java.lang.ProcessBuilder", // | |
50 | "javax.imageio.ImageIO$ContainsFilter", // | |
51 | - "jdk.nashorn.internal.objects.NativeString" }); | |
52 | - denyTypesByRegExp(new Pattern[]{LAZY_ITERATORS, JAVAX_CRYPTO, JAXWS_FILE_STREAM}); | |
53 | + "jdk.nashorn.internal.objects.NativeString", // | |
54 | + "com.sun.corba.se.impl.activation.ServerTableEntry", // | |
55 | + "com.sun.tools.javac.processing.JavacProcessingEnvironment$NameProcessIterator", // | |
56 | + "sun.awt.datatransfer.DataTransferer$IndexOrderComparator", // | |
57 | + "sun.swing.SwingLazyValue"}); | |
58 | + denyTypesByRegExp(new Pattern[]{ | |
59 | + LAZY_ITERATORS, GETTER_SETTER_REFLECTION, PRIVILEGED_GETTER, JAVAX_CRYPTO, JAXWS_ITERATORS, | |
60 | + JAVAFX_OBSERVABLE_LIST__, BCEL_CL}); | |
61 | + denyTypeHierarchy(InputStream.class); | |
62 | + denyTypeHierarchyDynamically("java.nio.channels.Channel"); | |
63 | + denyTypeHierarchyDynamically("javax.activation.DataSource"); | |
64 | + denyTypeHierarchyDynamically("javax.sql.rowset.BaseRowSet"); | |
65 | + | |
66 | allowTypeHierarchy(Exception.class); | |
67 | securityInitialized = false; | |
68 | } | |
69 | ||
70 | + private void denyTypeHierarchyDynamically(String className) { | |
71 | + Class type = JVM.loadClassForName(className); | |
72 | + if (type != null) { | |
73 | + denyTypeHierarchy(type); | |
74 | + } | |
75 | + } | |
76 | + | |
77 | /** | |
78 | * Setup the security framework of a XStream instance. | |
79 | * <p> | |
80 | diff --git a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java | |
81 | index da5f861..9da221c 100644 | |
82 | --- a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java | |
83 | +++ b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java | |
84 | @@ -11,6 +11,7 @@ | |
85 | package com.thoughtworks.acceptance; | |
86 | ||
87 | import java.beans.EventHandler; | |
88 | +import java.io.ByteArrayInputStream; | |
89 | import java.io.File; | |
90 | import java.io.FileOutputStream; | |
91 | import java.io.IOException; | |
92 | @@ -282,4 +283,46 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest { | |
93 | } | |
94 | } | |
95 | } | |
96 | + | |
97 | + public void testCannotInjectManipulatedByteArryInputStream() { | |
98 | + xstream.alias("bais", ByteArrayInputStream.class); | |
99 | + System.out.println(Integer.MAX_VALUE); | |
100 | + final String xml = "" | |
101 | + + "<bais>\n" | |
102 | + + " <buf></buf>\n" | |
103 | + + " <pos>-2147483648</pos>\n" | |
104 | + + " <mark>0</mark>\n" | |
105 | + + " <count>0</count>\n" | |
106 | + + "</bais>"; | |
107 | + | |
108 | + try { | |
109 | + xstream.fromXML(xml); | |
110 | + fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); | |
111 | + } catch (final ForbiddenClassException e) { | |
112 | + assertEquals(e.getMessage(),ByteArrayInputStream.class.getName()); | |
113 | + } | |
114 | + } | |
115 | + | |
116 | + public void testExplicitlyUnmarshalEndlessByteArryInputStream() { | |
117 | + xstream.alias("bais", ByteArrayInputStream.class); | |
118 | + xstream.allowTypes(new Class[]{ByteArrayInputStream.class}); | |
119 | + | |
120 | + final String xml = "" | |
121 | + + "<bais>\n" | |
122 | + + " <buf></buf>\n" | |
123 | + + " <pos>-2147483648</pos>\n" | |
124 | + + " <mark>0</mark>\n" | |
125 | + + " <count>0</count>\n" | |
126 | + + "</bais>"; | |
127 | + | |
128 | + final byte[] data = new byte[10]; | |
129 | + final ByteArrayInputStream bais = (ByteArrayInputStream)xstream.fromXML(xml); | |
130 | + int i = 5; | |
131 | + while(bais.read(data, 0, 10) == 0) { | |
132 | + if (--i == 0) { | |
133 | + break; | |
134 | + } | |
135 | + } | |
136 | + assertEquals("Unlimited reads of ByteArrayInputStream returning 0 bytes expected", 0, i); | |
137 | + } | |
138 | } |