|
0 |
From: Markus Koschany <apo@debian.org>
|
|
1 |
Date: Sun, 29 Nov 2020 17:04:10 +0100
|
|
2 |
Subject: CVE-2020-26217
|
|
3 |
|
|
4 |
Origin: https://github.com/x-stream/xstream/commit/0fec095d534126931c99fd38e9c6d41f5c685c1a
|
|
5 |
---
|
|
6 |
.../src/java/com/thoughtworks/xstream/XStream.java | 4 +
|
|
7 |
.../acceptance/SecurityVulnerabilityTest.java | 86 +++++++++++++++++++---
|
|
8 |
2 files changed, 80 insertions(+), 10 deletions(-)
|
|
9 |
|
|
10 |
diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
11 |
index a2b7feb..a1fd703 100644
|
|
12 |
--- a/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
13 |
+++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
14 |
@@ -676,6 +676,10 @@ public class XStream {
|
|
15 |
}
|
|
16 |
|
|
17 |
addPermission(AnyTypePermission.ANY);
|
|
18 |
+ denyTypes(new String[]{"java.beans.EventHandler", "javax.imageio.ImageIO$ContainsFilter"});
|
|
19 |
+ denyTypes(new Class[]{ java.lang.ProcessBuilder.class,
|
|
20 |
+ java.beans.EventHandler.class, java.lang.ProcessBuilder.class,
|
|
21 |
+ java.lang.Void.class, void.class });
|
|
22 |
}
|
|
23 |
|
|
24 |
protected void setupAliases() {
|
|
25 |
diff --git a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
26 |
index 9f1cef2..1ceb450 100644
|
|
27 |
--- a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
28 |
+++ b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
29 |
@@ -11,10 +11,11 @@
|
|
30 |
package com.thoughtworks.acceptance;
|
|
31 |
|
|
32 |
import java.beans.EventHandler;
|
|
33 |
+import java.util.Iterator;
|
|
34 |
|
|
35 |
import com.thoughtworks.xstream.XStreamException;
|
|
36 |
import com.thoughtworks.xstream.converters.ConversionException;
|
|
37 |
-import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
|
|
38 |
+import com.thoughtworks.xstream.core.JVM;
|
|
39 |
import com.thoughtworks.xstream.security.ForbiddenClassException;
|
|
40 |
import com.thoughtworks.xstream.security.ProxyTypePermission;
|
|
41 |
|
|
42 |
@@ -37,15 +38,15 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest {
|
|
43 |
|
|
44 |
public void testCannotInjectEventHandler() {
|
|
45 |
final String xml = ""
|
|
46 |
- + "<string class='runnable-array'>\n"
|
|
47 |
- + " <dynamic-proxy>\n"
|
|
48 |
- + " <interface>java.lang.Runnable</interface>\n"
|
|
49 |
- + " <handler class='java.beans.EventHandler'>\n"
|
|
50 |
- + " <target class='com.thoughtworks.acceptance.SecurityVulnerabilityTest$Exec'/>\n"
|
|
51 |
- + " <action>exec</action>\n"
|
|
52 |
- + " </handler>\n"
|
|
53 |
- + " </dynamic-proxy>\n"
|
|
54 |
- + "</string>";
|
|
55 |
+ + "<string class='runnable-array'>\n"
|
|
56 |
+ + " <dynamic-proxy>\n"
|
|
57 |
+ + " <interface>java.lang.Runnable</interface>\n"
|
|
58 |
+ + " <handler class='java.beans.EventHandler'>\n"
|
|
59 |
+ + " <target class='com.thoughtworks.acceptance.SecurityVulnerabilityTest$Exec'/>\n"
|
|
60 |
+ + " <action>exec</action>\n"
|
|
61 |
+ + " </handler>\n"
|
|
62 |
+ + " </dynamic-proxy>\n"
|
|
63 |
+ + "</string>";
|
|
64 |
|
|
65 |
try {
|
|
66 |
xstream.fromXML(xml);
|
|
67 |
@@ -77,6 +78,71 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest {
|
|
68 |
assertEquals("Executed!", BUFFER.toString());
|
|
69 |
}
|
|
70 |
|
|
71 |
+ public void testCannotInjectConvertImageIOContainsFilterWithUnconfiguredSecurityFramework() {
|
|
72 |
+ if (JVM.isVersion(7)) {
|
|
73 |
+ final String xml = ""
|
|
74 |
+ + "<string class='javax.imageio.spi.FilterIterator'>\n"
|
|
75 |
+ + " <iter class='java.util.ArrayList$Itr'>\n"
|
|
76 |
+ + " <cursor>0</cursor>\n"
|
|
77 |
+ + " <lastRet>1</lastRet>\n"
|
|
78 |
+ + " <expectedModCount>1</expectedModCount>\n"
|
|
79 |
+ + " <outer-class>\n"
|
|
80 |
+ + " <com.thoughtworks.acceptance.SecurityVulnerabilityTest_-Exec/>\n"
|
|
81 |
+ + " </outer-class>\n"
|
|
82 |
+ + " </iter>\n"
|
|
83 |
+ + " <filter class='javax.imageio.ImageIO$ContainsFilter'>\n"
|
|
84 |
+ + " <method>\n"
|
|
85 |
+ + " <class>com.thoughtworks.acceptance.SecurityVulnerabilityTest$Exec</class>\n"
|
|
86 |
+ + " <name>exec</name>\n"
|
|
87 |
+ + " <parameter-types/>\n"
|
|
88 |
+ + " </method>\n"
|
|
89 |
+ + " <name>exec</name>\n"
|
|
90 |
+ + " </filter>\n"
|
|
91 |
+ + " <next/>\n"
|
|
92 |
+ + "</string>";
|
|
93 |
+
|
|
94 |
+ try {
|
|
95 |
+ xstream.fromXML(xml);
|
|
96 |
+ fail("Thrown " + XStreamException.class.getName() + " expected");
|
|
97 |
+ } catch (final XStreamException e) {
|
|
98 |
+ assertTrue(e.getMessage().indexOf("javax.imageio.ImageIO$ContainsFilter") >= 0);
|
|
99 |
+ }
|
|
100 |
+ assertEquals(0, BUFFER.length());
|
|
101 |
+ }
|
|
102 |
+ }
|
|
103 |
+
|
|
104 |
+ public void testExplicitlyConvertImageIOContainsFilter() {
|
|
105 |
+ if (JVM.isVersion(7)) {
|
|
106 |
+ final String xml = ""
|
|
107 |
+ + "<string class='javax.imageio.spi.FilterIterator'>\n"
|
|
108 |
+ + " <iter class='java.util.ArrayList$Itr'>\n"
|
|
109 |
+ + " <cursor>0</cursor>\n"
|
|
110 |
+ + " <lastRet>1</lastRet>\n"
|
|
111 |
+ + " <expectedModCount>1</expectedModCount>\n"
|
|
112 |
+ + " <outer-class>\n"
|
|
113 |
+ + " <com.thoughtworks.acceptance.SecurityVulnerabilityTest_-Exec/>\n"
|
|
114 |
+ + " </outer-class>\n"
|
|
115 |
+ + " </iter>\n"
|
|
116 |
+ + " <filter class='javax.imageio.ImageIO$ContainsFilter'>\n"
|
|
117 |
+ + " <method>\n"
|
|
118 |
+ + " <class>com.thoughtworks.acceptance.SecurityVulnerabilityTest$Exec</class>\n"
|
|
119 |
+ + " <name>exec</name>\n"
|
|
120 |
+ + " <parameter-types/>\n"
|
|
121 |
+ + " </method>\n"
|
|
122 |
+ + " <name>exec</name>\n"
|
|
123 |
+ + " </filter>\n"
|
|
124 |
+ + " <next/>\n"
|
|
125 |
+ + "</string>";
|
|
126 |
+
|
|
127 |
+ xstream.allowTypes(new String[]{"javax.imageio.ImageIO$ContainsFilter"});
|
|
128 |
+
|
|
129 |
+ final Iterator iterator = (Iterator)xstream.fromXML(xml);
|
|
130 |
+ assertEquals(0, BUFFER.length());
|
|
131 |
+ iterator.next();
|
|
132 |
+ assertEquals("Executed!", BUFFER.toString());
|
|
133 |
+ }
|
|
134 |
+ }
|
|
135 |
+
|
|
136 |
public static class Exec {
|
|
137 |
|
|
138 |
public void exec() {
|