0 | |
Description: Fixes CVE-2017-7957: When a certain denyTypes workaround is not
|
1 | |
used, XStream mishandles attempts to create an instance of the primitive type
|
2 | |
'void' during unmarshalling, leading to a remote application crash, as
|
3 | |
demonstrated by an xstream.fromXML("<void/>") call.
|
4 | |
Origin: backport, https://github.com/x-stream/xstream/commit/b3570be
|
5 | |
Bug-Debian: https://bugs.debian.org/861521
|
6 | |
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java
|
7 | |
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java
|
8 | |
@@ -78,14 +78,18 @@
|
9 | |
throw ex;
|
10 | |
}
|
11 | |
ErrorWritingException ex = null;
|
12 | |
- try {
|
13 | |
- return unsafe.allocateInstance(type);
|
14 | |
- } catch (SecurityException e) {
|
15 | |
- ex = new ObjectAccessException("Cannot construct type", e);
|
16 | |
- } catch (InstantiationException e) {
|
17 | |
- ex = new ConversionException("Cannot construct type", e);
|
18 | |
- } catch (IllegalArgumentException e) {
|
19 | |
- ex = new ObjectAccessException("Cannot construct type", e);
|
20 | |
+ if (type == void.class || type == Void.class) {
|
21 | |
+ ex = new ConversionException("Type void cannot have an instance");
|
22 | |
+ } else {
|
23 | |
+ try {
|
24 | |
+ return unsafe.allocateInstance(type);
|
25 | |
+ } catch (final SecurityException e) {
|
26 | |
+ ex = new ObjectAccessException("Cannot construct type", e);
|
27 | |
+ } catch (final InstantiationException e) {
|
28 | |
+ ex = new ConversionException("Cannot construct type", e);
|
29 | |
+ } catch (final IllegalArgumentException e) {
|
30 | |
+ ex = new ObjectAccessException("Cannot construct type", e);
|
31 | |
+ }
|
32 | |
}
|
33 | |
ex.add("construction-type", type.getName());
|
34 | |
throw ex;
|
35 | |
--- a/xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java
|
36 | |
+++ b/xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java
|
37 | |
@@ -8,8 +8,9 @@
|
38 | |
|
39 | |
import com.thoughtworks.xstream.core.util.Primitives;
|
40 | |
|
41 | |
+
|
42 | |
/**
|
43 | |
- * Permission for any primitive type and its boxed counterpart (incl. void).
|
44 | |
+ * Permission for any primitive type and its boxed counterpart (excl. void).
|
45 | |
*
|
46 | |
* @author Jörg Schaible
|
47 | |
* @since 1.4.7
|
48 | |
@@ -21,7 +22,8 @@
|
49 | |
public static final TypePermission PRIMITIVES = new PrimitiveTypePermission();
|
50 | |
|
51 | |
public boolean allows(Class type) {
|
52 | |
- return type != null && type.isPrimitive() || Primitives.isBoxed(type);
|
53 | |
+ return type != null && type != void.class && type != Void.class && type.isPrimitive()
|
54 | |
+ || Primitives.isBoxed(type);
|
55 | |
}
|
56 | |
|
57 | |
public int hashCode() {
|
58 | |
--- a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
59 | |
+++ b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
60 | |
@@ -13,9 +13,12 @@
|
61 | |
import java.beans.EventHandler;
|
62 | |
|
63 | |
import com.thoughtworks.xstream.XStreamException;
|
64 | |
+import com.thoughtworks.xstream.converters.ConversionException;
|
65 | |
import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
|
66 | |
+import com.thoughtworks.xstream.security.ForbiddenClassException;
|
67 | |
import com.thoughtworks.xstream.security.ProxyTypePermission;
|
68 | |
|
69 | |
+
|
70 | |
/**
|
71 | |
* @author Jörg Schaible
|
72 | |
*/
|
73 | |
@@ -80,4 +83,23 @@
|
74 | |
BUFFER.append("Executed!");
|
75 | |
}
|
76 | |
}
|
77 | |
+
|
78 | |
+ public void testDeniedInstanceOfVoid() {
|
79 | |
+ try {
|
80 | |
+ xstream.fromXML("<void/>");
|
81 | |
+ fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
|
82 | |
+ } catch (final ForbiddenClassException e) {
|
83 | |
+ // OK
|
84 | |
+ }
|
85 | |
+ }
|
86 | |
+
|
87 | |
+ public void testAllowedInstanceOfVoid() {
|
88 | |
+ xstream.allowTypes(void.class, Void.class);
|
89 | |
+ try {
|
90 | |
+ xstream.fromXML("<void/>");
|
91 | |
+ fail("Thrown " + ConversionException.class.getName() + " expected");
|
92 | |
+ } catch (final ConversionException e) {
|
93 | |
+ assertEquals("void", e.get("construction-type"));
|
94 | |
+ }
|
95 | |
+ }
|
96 | |
}
|