|
0 |
From: Markus Koschany <apo@debian.org>
|
|
1 |
Date: Sun, 27 Dec 2020 11:05:05 +0100
|
|
2 |
Subject: CVE-2020-26259
|
|
3 |
|
|
4 |
Origin: https://github.com/x-stream/xstream/commit/0bcbf50126a62dfcd65f93a0da0c6d1ae92aa738
|
|
5 |
---
|
|
6 |
pom.xml | 6 ++
|
|
7 |
xstream/pom.xml | 48 ++++++++++++++++
|
|
8 |
.../src/java/com/thoughtworks/xstream/XStream.java | 10 +++-
|
|
9 |
.../acceptance/SecurityVulnerabilityTest.java | 65 ++++++++++++++++++++++
|
|
10 |
4 files changed, 126 insertions(+), 3 deletions(-)
|
|
11 |
|
|
12 |
diff --git a/pom.xml b/pom.xml
|
|
13 |
index 5d52a8f..3e47500 100644
|
|
14 |
--- a/pom.xml
|
|
15 |
+++ b/pom.xml
|
|
16 |
@@ -552,6 +552,11 @@
|
|
17 |
<artifactId>jaxb-api</artifactId>
|
|
18 |
<version>${version.javax.xml.bind.api}</version>
|
|
19 |
</dependency>
|
|
20 |
+ <dependency>
|
|
21 |
+ <groupId>com.sun.xml.ws</groupId>
|
|
22 |
+ <artifactId>jaxws-rt</artifactId>
|
|
23 |
+ <version>${version.javax.xml.ws.jaxws.rt}</version>
|
|
24 |
+ </dependency>
|
|
25 |
|
|
26 |
<dependency>
|
|
27 |
<groupId>org.hibernate</groupId>
|
|
28 |
@@ -984,6 +989,7 @@
|
|
29 |
<version.javax.activation>1.1.1</version.javax.activation>
|
|
30 |
<version.javax.annotation.api>1.3.2</version.javax.annotation.api>
|
|
31 |
<version.javax.xml.bind.api>2.3.1</version.javax.xml.bind.api>
|
|
32 |
+ <version.javax.xml.ws.jaxws.rt>2.2</version.javax.xml.ws.jaxws.rt><!-- Java 5 -->
|
|
33 |
<version.jmock>1.0.1</version.jmock>
|
|
34 |
<version.joda-time>1.6</version.joda-time>
|
|
35 |
<version.junit>3.8.1</version.junit>
|
|
36 |
diff --git a/xstream/pom.xml b/xstream/pom.xml
|
|
37 |
index 566b619..8b9dc22 100644
|
|
38 |
--- a/xstream/pom.xml
|
|
39 |
+++ b/xstream/pom.xml
|
|
40 |
@@ -149,6 +149,54 @@
|
|
41 |
<artifactId>commons-lang</artifactId>
|
|
42 |
<scope>test</scope>
|
|
43 |
</dependency>
|
|
44 |
+
|
|
45 |
+ <dependency>
|
|
46 |
+ <groupId>com.sun.xml.ws</groupId>
|
|
47 |
+ <artifactId>jaxws-rt</artifactId>
|
|
48 |
+ <scope>test</scope>
|
|
49 |
+ <exclusions>
|
|
50 |
+ <exclusion>
|
|
51 |
+ <groupId>javax.xml.ws</groupId>
|
|
52 |
+ <artifactId>jaxws-api</artifactId>
|
|
53 |
+ </exclusion>
|
|
54 |
+ <exclusion>
|
|
55 |
+ <groupId>com.sun.istack</groupId>
|
|
56 |
+ <artifactId>istack-commons-runtime</artifactId>
|
|
57 |
+ </exclusion>
|
|
58 |
+ <exclusion>
|
|
59 |
+ <groupId>com.sun.xml.bind</groupId>
|
|
60 |
+ <artifactId>jaxb-impl</artifactId>
|
|
61 |
+ </exclusion>
|
|
62 |
+ <exclusion>
|
|
63 |
+ <groupId>com.sun.xml.messaging.saaj</groupId>
|
|
64 |
+ <artifactId>saaj-impl</artifactId>
|
|
65 |
+ </exclusion>
|
|
66 |
+ <exclusion>
|
|
67 |
+ <groupId>com.sun.xml.stream.buffer</groupId>
|
|
68 |
+ <artifactId>streambuffer</artifactId>
|
|
69 |
+ </exclusion>
|
|
70 |
+ <exclusion>
|
|
71 |
+ <groupId>com.sun.xml.ws</groupId>
|
|
72 |
+ <artifactId>policy</artifactId>
|
|
73 |
+ </exclusion>
|
|
74 |
+ <exclusion>
|
|
75 |
+ <groupId>com.sun.org.apache.xml.internal</groupId>
|
|
76 |
+ <artifactId>resolver</artifactId>
|
|
77 |
+ </exclusion>
|
|
78 |
+ <exclusion>
|
|
79 |
+ <groupId>org.glassfish.gmbal</groupId>
|
|
80 |
+ <artifactId>gmbal-api-only</artifactId>
|
|
81 |
+ </exclusion>
|
|
82 |
+ <exclusion>
|
|
83 |
+ <groupId>org.jvnet</groupId>
|
|
84 |
+ <artifactId>mimepull</artifactId>
|
|
85 |
+ </exclusion>
|
|
86 |
+ <exclusion>
|
|
87 |
+ <groupId>org.jvnet.staxex</groupId>
|
|
88 |
+ <artifactId>stax-ex</artifactId>
|
|
89 |
+ </exclusion>
|
|
90 |
+ </exclusions>
|
|
91 |
+ </dependency>
|
|
92 |
</dependencies>
|
|
93 |
|
|
94 |
<build>
|
|
95 |
diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
96 |
index 65670f1..1d28088 100644
|
|
97 |
--- a/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
98 |
+++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
99 |
@@ -356,6 +356,7 @@ public class XStream {
|
|
100 |
private static final Pattern IGNORE_ALL = Pattern.compile(".*");
|
|
101 |
private static final Pattern LAZY_ITERATORS = Pattern.compile(".*\\$LazyIterator");
|
|
102 |
private static final Pattern JAVAX_CRYPTO = Pattern.compile("javax\\.crypto\\..*");
|
|
103 |
+ private static final Pattern JAXWS_FILE_STREAM = Pattern.compile(".*\\.ReadAllStream\\$FileStream");
|
|
104 |
|
|
105 |
/**
|
|
106 |
* Constructs a default XStream.
|
|
107 |
@@ -703,10 +704,13 @@ public class XStream {
|
|
108 |
"java.lang.ProcessBuilder",
|
|
109 |
"javax.imageio.ImageIO$ContainsFilter",
|
|
110 |
"jdk.nashorn.internal.objects.NativeString"});
|
|
111 |
- denyTypes(new Class[]{ java.lang.ProcessBuilder.class,
|
|
112 |
- java.beans.EventHandler.class, java.lang.ProcessBuilder.class,
|
|
113 |
+ denyTypes(new Class[]{
|
|
114 |
+ java.lang.ProcessBuilder.class,
|
|
115 |
+ jdk.nashorn.internal.objects.NativeString.class,
|
|
116 |
+ java.beans.EventHandler.class,
|
|
117 |
+ java.lang.ProcessBuilder.class,
|
|
118 |
java.lang.Void.class, void.class });
|
|
119 |
- denyTypesByRegExp(new Pattern[] {LAZY_ITERATORS, JAVAX_CRYPTO});
|
|
120 |
+ denyTypesByRegExp(new Pattern[] {LAZY_ITERATORS, JAVAX_CRYPTO, JAXWS_FILE_STREAM});
|
|
121 |
allowTypeHierarchy(Exception.class);
|
|
122 |
securityInitialized = false;
|
|
123 |
}
|
|
124 |
diff --git a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
125 |
index 44b0015..36b61a1 100644
|
|
126 |
--- a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
127 |
+++ b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
128 |
@@ -11,6 +11,11 @@
|
|
129 |
package com.thoughtworks.acceptance;
|
|
130 |
|
|
131 |
import java.beans.EventHandler;
|
|
132 |
+import java.io.File;
|
|
133 |
+import java.io.FileOutputStream;
|
|
134 |
+import java.io.IOException;
|
|
135 |
+import java.io.InputStream;
|
|
136 |
+import java.io.OutputStream;
|
|
137 |
import java.util.Iterator;
|
|
138 |
|
|
139 |
import com.thoughtworks.xstream.XStream;
|
|
140 |
@@ -206,4 +211,64 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest {
|
|
141 |
// OK
|
|
142 |
}
|
|
143 |
}
|
|
144 |
+
|
|
145 |
+ public void testCannotUseJaxwsInputStreamToDeleteFile() {
|
|
146 |
+ final String xml = ""
|
|
147 |
+ + "<is class='com.sun.xml.ws.util.ReadAllStream$FileStream'>\n"
|
|
148 |
+ + " <tempFile>target/junit/test.txt</tempFile>\n"
|
|
149 |
+ + "</is>";
|
|
150 |
+
|
|
151 |
+ xstream.aliasType("is", InputStream.class);
|
|
152 |
+ try {
|
|
153 |
+ xstream.fromXML(xml);
|
|
154 |
+ fail("Thrown " + ConversionException.class.getName() + " expected");
|
|
155 |
+ } catch (final ForbiddenClassException e) {
|
|
156 |
+ // OK
|
|
157 |
+ }
|
|
158 |
+ }
|
|
159 |
+
|
|
160 |
+ public void testExplicitlyUseJaxwsInputStreamToDeleteFile() throws IOException {
|
|
161 |
+ final File testDir = new File("target/junit");
|
|
162 |
+ final File testFile = new File(testDir, "test.txt");
|
|
163 |
+ try {
|
|
164 |
+ testDir.mkdirs();
|
|
165 |
+
|
|
166 |
+ final OutputStream out = new FileOutputStream(testFile);
|
|
167 |
+ out.write("JUnit".getBytes());
|
|
168 |
+ out.flush();
|
|
169 |
+ out.close();
|
|
170 |
+
|
|
171 |
+ assertTrue("Test file " + testFile.getPath() + " does not exist.", testFile.exists());
|
|
172 |
+
|
|
173 |
+ final String xml = ""
|
|
174 |
+ + "<is class='com.sun.xml.ws.util.ReadAllStream$FileStream'>\n"
|
|
175 |
+ + " <tempFile>target/junit/test.txt</tempFile>\n"
|
|
176 |
+ + "</is>";
|
|
177 |
+
|
|
178 |
+ xstream.addPermission(AnyTypePermission.ANY); // clear out defaults
|
|
179 |
+ xstream.aliasType("is", InputStream.class);
|
|
180 |
+
|
|
181 |
+ InputStream is = null;
|
|
182 |
+ try {
|
|
183 |
+ is = (InputStream)xstream.fromXML(xml);
|
|
184 |
+ } catch (final ForbiddenClassException e) {
|
|
185 |
+ // OK
|
|
186 |
+ }
|
|
187 |
+
|
|
188 |
+ assertTrue("Test file " + testFile.getPath() + " no longer exists.", testFile.exists());
|
|
189 |
+
|
|
190 |
+ byte[] data = new byte[10];
|
|
191 |
+ is.read(data);
|
|
192 |
+ is.close();
|
|
193 |
+
|
|
194 |
+ assertFalse("Test file " + testFile.getPath() + " still exists exist.", testFile.exists());
|
|
195 |
+ } finally {
|
|
196 |
+ if (testFile.exists()) {
|
|
197 |
+ testFile.delete();
|
|
198 |
+ }
|
|
199 |
+ if (testDir.exists()) {
|
|
200 |
+ testDir.delete();
|
|
201 |
+ }
|
|
202 |
+ }
|
|
203 |
+ }
|
|
204 |
}
|