High severityNVD Advisory· Published Apr 29, 2017· Updated Aug 5, 2024
CVE-2017-7957
CVE-2017-7957
Description
XStream through 1.4.9, when a certain denyTypes workaround is not used, mishandles attempts to create an instance of the primitive type 'void' during unmarshalling, leading to a remote application crash, as demonstrated by an xstream.fromXML("") call.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.thoughtworks.xstream:xstreamMaven | < 1.4.10 | 1.4.10 |
Affected products
31- ghsa-coords31 versionspkg:maven/com.thoughtworks.xstream/xstreampkg:rpm/opensuse/xstream&distro=openSUSE%20Tumbleweedpkg:rpm/suse/apache-commons-lang3&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/cobbler&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/drools&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/guava&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/jade4j&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/kie-api&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/kie-soup&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/optaplanner&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/py26-compat-salt&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/reprepro&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/smdba&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/spacecmd&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/spacewalk-admin&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/spacewalk-backend&distro=SUSE%20Manager%20Proxy%203.2pkg:rpm/suse/spacewalk-backend&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/spacewalk-branding&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/spacewalk-certs-tools&distro=SUSE%20Manager%20Proxy%203.2pkg:rpm/suse/spacewalk-certs-tools&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/spacewalk-java&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/spacewalk-web&distro=SUSE%20Manager%20Proxy%203.2pkg:rpm/suse/spacewalk-web&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/subscription-matcher&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/susemanager&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/susemanager-schema&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/susemanager-sls&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/susemanager-sync-data&distro=SUSE%20Manager%20Server%203.2pkg:rpm/suse/xstream&distro=SUSE%20Manager%20Server%203.0pkg:rpm/suse/xstream&distro=SUSE%20Manager%20Server%203.1pkg:rpm/suse/xstream&distro=SUSE%20Manager%20Server%203.2
< 1.4.10+ 30 more
- (no CPE)range: < 1.4.10
- (no CPE)range: < 1.4.18-1.1
- (no CPE)range: < 3.4-3.3.3
- (no CPE)range: < 2.6.6-6.16.3
- (no CPE)range: < 7.17.0-3.3.3
- (no CPE)range: < 27.0.1-3.3.3
- (no CPE)range: < 1.0.7-3.3.3
- (no CPE)range: < 7.17.0-3.3.3
- (no CPE)range: < 7.17.0.Final-2.3.3
- (no CPE)range: < 7.17.0-3.3.3
- (no CPE)range: < 2016.11.10-6.21.3
- (no CPE)range: < 5.3.0-2.3.3
- (no CPE)range: < 1.6.4-0.3.9.3
- (no CPE)range: < 2.8.25.10-3.20.3
- (no CPE)range: < 2.8.4.4-3.6.3
- (no CPE)range: < 2.8.57.14-3.25.3
- (no CPE)range: < 2.8.57.14-3.25.3
- (no CPE)range: < 2.8.5.15-3.19.3
- (no CPE)range: < 2.8.8.7-3.6.3
- (no CPE)range: < 2.8.8.7-3.6.3
- (no CPE)range: < 2.8.78.21-3.29.1
- (no CPE)range: < 2.8.7.15-3.24.3
- (no CPE)range: < 2.8.7.15-3.24.3
- (no CPE)range: < 0.23-4.12.3
- (no CPE)range: < 3.2.17-3.22.4
- (no CPE)range: < 3.2.18-3.22.3
- (no CPE)range: < 3.2.23-3.26.3
- (no CPE)range: < 3.2.14-3.20.3
- (no CPE)range: < 1.4.9-4.3.1
- (no CPE)range: < 1.4.9-3.3.1
- (no CPE)range: < 1.4.10-4.3.3
Patches
68542d02d9ac5Implement black list. Fix security unit test.
2 files changed · +36 −1
xstream/src/java/com/thoughtworks/xstream/XStream.java+34 −0 modified@@ -58,8 +58,10 @@ import com.thoughtworks.xstream.converters.ConverterLookup; import com.thoughtworks.xstream.converters.ConverterRegistry; import com.thoughtworks.xstream.converters.DataHolder; +import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.SingleValueConverter; import com.thoughtworks.xstream.converters.SingleValueConverterWrapper; +import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.converters.basic.BigDecimalConverter; import com.thoughtworks.xstream.converters.basic.BigIntegerConverter; import com.thoughtworks.xstream.converters.basic.BooleanConverter; @@ -325,6 +327,8 @@ public class XStream { private SecurityMapper securityMapper; private AnnotationConfiguration annotationConfiguration; + private transient boolean insecureWarning; + public static final int NO_REFERENCES = 1001; public static final int ID_REFERENCES = 1002; public static final int XPATH_RELATIVE_REFERENCES = 1003; @@ -681,6 +685,7 @@ protected void setupSecurity() { } addPermission(AnyTypePermission.ANY); + insecureWarning = true; } protected void setupAliases() { @@ -847,6 +852,7 @@ protected void setupConverters() { registerConverter( new SerializableConverter(mapper, reflectionProvider, classLoaderReference), PRIORITY_LOW); registerConverter(new ExternalizableConverter(mapper, classLoaderReference), PRIORITY_LOW); + registerConverter(new InternalBlackList(), PRIORITY_LOW); registerConverter(new NullConverter(), PRIORITY_VERY_HIGH); registerConverter(new IntConverter(), PRIORITY_NORMAL); @@ -1364,6 +1370,10 @@ public Object unmarshal(HierarchicalStreamReader reader, Object root) { */ public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) { try { + if (insecureWarning) { + insecureWarning = false; + System.err.println("Security framework of XStream not initialized, XStream is probably vulnerable."); + } return marshallingStrategy.unmarshal( root, reader, dataHolder, converterLookup, mapper); @@ -2240,6 +2250,7 @@ public void autodetectAnnotations(boolean mode) { */ public void addPermission(TypePermission permission) { if (securityMapper != null) { + insecureWarning &= permission != NoTypePermission.NONE; securityMapper.addPermission(permission); } } @@ -2413,4 +2424,27 @@ public InitializationException(String message) { super(message); } } + + private class InternalBlackList implements Converter { + + public boolean canConvert(final Class type) { + return (type == void.class || type == Void.class) + || (insecureWarning + && type != null + && (type.getName().equals("java.beans.EventHandler") + || type.getName().endsWith("$LazyIterator") + || type.getName().startsWith("javax.crypto."))); + } + + @Override + public void marshal(final Object source, final HierarchicalStreamWriter writer, + final MarshallingContext context) { + throw new ConversionException("Security alert. Marshalling rejected."); + } + + @Override + public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) { + throw new ConversionException("Security alert. Unmarshalling rejected."); + } + } }
xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+2 −1 modified@@ -67,6 +67,7 @@ public void testExplicitlyConvertEventHandler() { + " </dynamic-proxy>\n" + "</string>"; + xstream.allowTypes(new Class[]{EventHandler.class}); xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream .getReflectionProvider(), EventHandler.class)); @@ -98,7 +99,7 @@ public void testAllowedInstanceOfVoid() { xstream.fromXML("<void/>"); fail("Thrown " + ConversionException.class.getName() + " expected"); } catch (final ConversionException e) { - assertEquals("void", e.get("construction-type")); + assertEquals("void", e.get("required-type")); } } }
8542d02d9ac5Implement black list. Fix security unit test.
2 files changed · +36 −1
xstream/src/java/com/thoughtworks/xstream/XStream.java+34 −0 modified@@ -58,8 +58,10 @@ import com.thoughtworks.xstream.converters.ConverterLookup; import com.thoughtworks.xstream.converters.ConverterRegistry; import com.thoughtworks.xstream.converters.DataHolder; +import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.SingleValueConverter; import com.thoughtworks.xstream.converters.SingleValueConverterWrapper; +import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.converters.basic.BigDecimalConverter; import com.thoughtworks.xstream.converters.basic.BigIntegerConverter; import com.thoughtworks.xstream.converters.basic.BooleanConverter; @@ -325,6 +327,8 @@ public class XStream { private SecurityMapper securityMapper; private AnnotationConfiguration annotationConfiguration; + private transient boolean insecureWarning; + public static final int NO_REFERENCES = 1001; public static final int ID_REFERENCES = 1002; public static final int XPATH_RELATIVE_REFERENCES = 1003; @@ -681,6 +685,7 @@ protected void setupSecurity() { } addPermission(AnyTypePermission.ANY); + insecureWarning = true; } protected void setupAliases() { @@ -847,6 +852,7 @@ protected void setupConverters() { registerConverter( new SerializableConverter(mapper, reflectionProvider, classLoaderReference), PRIORITY_LOW); registerConverter(new ExternalizableConverter(mapper, classLoaderReference), PRIORITY_LOW); + registerConverter(new InternalBlackList(), PRIORITY_LOW); registerConverter(new NullConverter(), PRIORITY_VERY_HIGH); registerConverter(new IntConverter(), PRIORITY_NORMAL); @@ -1364,6 +1370,10 @@ public Object unmarshal(HierarchicalStreamReader reader, Object root) { */ public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) { try { + if (insecureWarning) { + insecureWarning = false; + System.err.println("Security framework of XStream not initialized, XStream is probably vulnerable."); + } return marshallingStrategy.unmarshal( root, reader, dataHolder, converterLookup, mapper); @@ -2240,6 +2250,7 @@ public void autodetectAnnotations(boolean mode) { */ public void addPermission(TypePermission permission) { if (securityMapper != null) { + insecureWarning &= permission != NoTypePermission.NONE; securityMapper.addPermission(permission); } } @@ -2413,4 +2424,27 @@ public InitializationException(String message) { super(message); } } + + private class InternalBlackList implements Converter { + + public boolean canConvert(final Class type) { + return (type == void.class || type == Void.class) + || (insecureWarning + && type != null + && (type.getName().equals("java.beans.EventHandler") + || type.getName().endsWith("$LazyIterator") + || type.getName().startsWith("javax.crypto."))); + } + + @Override + public void marshal(final Object source, final HierarchicalStreamWriter writer, + final MarshallingContext context) { + throw new ConversionException("Security alert. Marshalling rejected."); + } + + @Override + public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) { + throw new ConversionException("Security alert. Unmarshalling rejected."); + } + } }
xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+2 −1 modified@@ -67,6 +67,7 @@ public void testExplicitlyConvertEventHandler() { + " </dynamic-proxy>\n" + "</string>"; + xstream.allowTypes(new Class[]{EventHandler.class}); xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream .getReflectionProvider(), EventHandler.class)); @@ -98,7 +99,7 @@ public void testAllowedInstanceOfVoid() { xstream.fromXML("<void/>"); fail("Thrown " + ConversionException.class.getName() + " expected"); } catch (final ConversionException e) { - assertEquals("void", e.get("construction-type")); + assertEquals("void", e.get("required-type")); } } }
6e546ec36641Prevent deserialization of void.
3 files changed · +41 −13
xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java+13 −9 modified@@ -1,6 +1,6 @@ /* * Copyright (C) 2004, 2005 Joe Walnes. - * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers. + * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers. * All rights reserved. * * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider @@ -78,14 +78,18 @@ public Object newInstance(Class type) { throw ex; } ErrorWritingException ex = null; - try { - return unsafe.allocateInstance(type); - } catch (SecurityException e) { - ex = new ObjectAccessException("Cannot construct type", e); - } catch (InstantiationException e) { - ex = new ConversionException("Cannot construct type", e); - } catch (IllegalArgumentException e) { - ex = new ObjectAccessException("Cannot construct type", e); + if (type == void.class || type == Void.class) { + ex = new ConversionException("Type void cannot have an instance"); + } else { + try { + return unsafe.allocateInstance(type); + } catch (final SecurityException e) { + ex = new ObjectAccessException("Cannot construct type", e); + } catch (final InstantiationException e) { + ex = new ConversionException("Cannot construct type", e); + } catch (final IllegalArgumentException e) { + ex = new ObjectAccessException("Cannot construct type", e); + } } ex.add("construction-type", type.getName()); throw ex;
xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java+5 −3 modified@@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 XStream Committers. + * Copyright (C) 2014, 2017 XStream Committers. * All rights reserved. * * Created on 09. January 2014 by Joerg Schaible @@ -8,8 +8,9 @@ import com.thoughtworks.xstream.core.util.Primitives; + /** - * Permission for any primitive type and its boxed counterpart (incl. void). + * Permission for any primitive type and its boxed counterpart (excl. void). * * @author Jörg Schaible * @since 1.4.7 @@ -21,7 +22,8 @@ public class PrimitiveTypePermission implements TypePermission { public static final TypePermission PRIMITIVES = new PrimitiveTypePermission(); public boolean allows(Class type) { - return type != null && type.isPrimitive() || Primitives.isBoxed(type); + return type != null && type != void.class && type != Void.class && type.isPrimitive() + || Primitives.isBoxed(type); } public int hashCode() {
xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+23 −1 modified@@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2014 XStream Committers. + * Copyright (C) 2013, 2014, 2017 XStream Committers. * All rights reserved. * * The software in this package is published under the terms of the BSD @@ -13,9 +13,12 @@ import java.beans.EventHandler; import com.thoughtworks.xstream.XStreamException; +import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; +import com.thoughtworks.xstream.security.ForbiddenClassException; import com.thoughtworks.xstream.security.ProxyTypePermission; + /** * @author Jörg Schaible */ @@ -80,4 +83,23 @@ public void exec() { BUFFER.append("Executed!"); } } + + public void testDeniedInstanceOfVoid() { + try { + xstream.fromXML("<void/>"); + fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); + } catch (final ForbiddenClassException e) { + // OK + } + } + + public void testAllowedInstanceOfVoid() { + xstream.allowTypes(new Class[] { void.class, Void.class }); + try { + xstream.fromXML("<void/>"); + fail("Thrown " + ConversionException.class.getName() + " expected"); + } catch (final ConversionException e) { + assertEquals("void", e.get("construction-type")); + } + } }
b3570be2f392Prevent deserialization of void.
3 files changed · +41 −13
xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java+13 −9 modified@@ -1,6 +1,6 @@ /* * Copyright (C) 2004, 2005 Joe Walnes. - * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers. + * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers. * All rights reserved. * * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider @@ -80,14 +80,18 @@ public Object newInstance(final Class<?> type) { throw ex; } ErrorWritingException ex = null; - try { - return unsafe.allocateInstance(type); - } catch (final SecurityException e) { - ex = new ObjectAccessException("Cannot construct type", e); - } catch (final InstantiationException e) { - ex = new ConversionException("Cannot construct type", e); - } catch (final IllegalArgumentException e) { - ex = new ObjectAccessException("Cannot construct type", e); + if (type == void.class || type == Void.class) { + ex = new ConversionException("Type void cannot have an instance"); + } else { + try { + return unsafe.allocateInstance(type); + } catch (final SecurityException e) { + ex = new ObjectAccessException("Cannot construct type", e); + } catch (final InstantiationException e) { + ex = new ConversionException("Cannot construct type", e); + } catch (final IllegalArgumentException e) { + ex = new ObjectAccessException("Cannot construct type", e); + } } ex.add("construction-type", type.getName()); throw ex;
xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java+5 −3 modified@@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 XStream Committers. + * Copyright (C) 2014, 2017 XStream Committers. * All rights reserved. * * Created on 09. January 2014 by Joerg Schaible @@ -8,8 +8,9 @@ import com.thoughtworks.xstream.core.util.Primitives; + /** - * Permission for any primitive type and its boxed counterpart (incl. void). + * Permission for any primitive type and its boxed counterpart (excl. void). * * @author Jörg Schaible * @since 1.4.7 @@ -22,7 +23,8 @@ public class PrimitiveTypePermission implements TypePermission { @Override public boolean allows(Class<?> type) { - return type != null && type.isPrimitive() || Primitives.isBoxed(type); + return type != null && type != void.class && type != Void.class && type.isPrimitive() + || Primitives.isBoxed(type); } @Override
xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+23 −1 modified@@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2014 XStream Committers. + * Copyright (C) 2013, 2014, 2017 XStream Committers. * All rights reserved. * * The software in this package is published under the terms of the BSD @@ -13,9 +13,12 @@ import java.beans.EventHandler; import com.thoughtworks.xstream.XStreamException; +import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; +import com.thoughtworks.xstream.security.ForbiddenClassException; import com.thoughtworks.xstream.security.ProxyTypePermission; + /** * @author Jörg Schaible */ @@ -80,4 +83,23 @@ public void exec() { BUFFER.append("Executed!"); } } + + public void testDeniedInstanceOfVoid() { + try { + xstream.fromXML("<void/>"); + fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); + } catch (final ForbiddenClassException e) { + // OK + } + } + + public void testAllowedInstanceOfVoid() { + xstream.allowTypes(void.class, Void.class); + try { + xstream.fromXML("<void/>"); + fail("Thrown " + ConversionException.class.getName() + " expected"); + } catch (final ConversionException e) { + assertEquals("void", e.get("construction-type")); + } + } }
b3570be2f392Prevent deserialization of void.
3 files changed · +41 −13
xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java+13 −9 modified@@ -1,6 +1,6 @@ /* * Copyright (C) 2004, 2005 Joe Walnes. - * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers. + * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers. * All rights reserved. * * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider @@ -80,14 +80,18 @@ public Object newInstance(final Class<?> type) { throw ex; } ErrorWritingException ex = null; - try { - return unsafe.allocateInstance(type); - } catch (final SecurityException e) { - ex = new ObjectAccessException("Cannot construct type", e); - } catch (final InstantiationException e) { - ex = new ConversionException("Cannot construct type", e); - } catch (final IllegalArgumentException e) { - ex = new ObjectAccessException("Cannot construct type", e); + if (type == void.class || type == Void.class) { + ex = new ConversionException("Type void cannot have an instance"); + } else { + try { + return unsafe.allocateInstance(type); + } catch (final SecurityException e) { + ex = new ObjectAccessException("Cannot construct type", e); + } catch (final InstantiationException e) { + ex = new ConversionException("Cannot construct type", e); + } catch (final IllegalArgumentException e) { + ex = new ObjectAccessException("Cannot construct type", e); + } } ex.add("construction-type", type.getName()); throw ex;
xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java+5 −3 modified@@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 XStream Committers. + * Copyright (C) 2014, 2017 XStream Committers. * All rights reserved. * * Created on 09. January 2014 by Joerg Schaible @@ -8,8 +8,9 @@ import com.thoughtworks.xstream.core.util.Primitives; + /** - * Permission for any primitive type and its boxed counterpart (incl. void). + * Permission for any primitive type and its boxed counterpart (excl. void). * * @author Jörg Schaible * @since 1.4.7 @@ -22,7 +23,8 @@ public class PrimitiveTypePermission implements TypePermission { @Override public boolean allows(Class<?> type) { - return type != null && type.isPrimitive() || Primitives.isBoxed(type); + return type != null && type != void.class && type != Void.class && type.isPrimitive() + || Primitives.isBoxed(type); } @Override
xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+23 −1 modified@@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2014 XStream Committers. + * Copyright (C) 2013, 2014, 2017 XStream Committers. * All rights reserved. * * The software in this package is published under the terms of the BSD @@ -13,9 +13,12 @@ import java.beans.EventHandler; import com.thoughtworks.xstream.XStreamException; +import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; +import com.thoughtworks.xstream.security.ForbiddenClassException; import com.thoughtworks.xstream.security.ProxyTypePermission; + /** * @author Jörg Schaible */ @@ -80,4 +83,23 @@ public void exec() { BUFFER.append("Executed!"); } } + + public void testDeniedInstanceOfVoid() { + try { + xstream.fromXML("<void/>"); + fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); + } catch (final ForbiddenClassException e) { + // OK + } + } + + public void testAllowedInstanceOfVoid() { + xstream.allowTypes(void.class, Void.class); + try { + xstream.fromXML("<void/>"); + fail("Thrown " + ConversionException.class.getName() + " expected"); + } catch (final ConversionException e) { + assertEquals("void", e.get("construction-type")); + } + } }
6e546ec36641Prevent deserialization of void.
3 files changed · +41 −13
xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java+13 −9 modified@@ -1,6 +1,6 @@ /* * Copyright (C) 2004, 2005 Joe Walnes. - * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers. + * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers. * All rights reserved. * * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider @@ -78,14 +78,18 @@ public Object newInstance(Class type) { throw ex; } ErrorWritingException ex = null; - try { - return unsafe.allocateInstance(type); - } catch (SecurityException e) { - ex = new ObjectAccessException("Cannot construct type", e); - } catch (InstantiationException e) { - ex = new ConversionException("Cannot construct type", e); - } catch (IllegalArgumentException e) { - ex = new ObjectAccessException("Cannot construct type", e); + if (type == void.class || type == Void.class) { + ex = new ConversionException("Type void cannot have an instance"); + } else { + try { + return unsafe.allocateInstance(type); + } catch (final SecurityException e) { + ex = new ObjectAccessException("Cannot construct type", e); + } catch (final InstantiationException e) { + ex = new ConversionException("Cannot construct type", e); + } catch (final IllegalArgumentException e) { + ex = new ObjectAccessException("Cannot construct type", e); + } } ex.add("construction-type", type.getName()); throw ex;
xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java+5 −3 modified@@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 XStream Committers. + * Copyright (C) 2014, 2017 XStream Committers. * All rights reserved. * * Created on 09. January 2014 by Joerg Schaible @@ -8,8 +8,9 @@ import com.thoughtworks.xstream.core.util.Primitives; + /** - * Permission for any primitive type and its boxed counterpart (incl. void). + * Permission for any primitive type and its boxed counterpart (excl. void). * * @author Jörg Schaible * @since 1.4.7 @@ -21,7 +22,8 @@ public class PrimitiveTypePermission implements TypePermission { public static final TypePermission PRIMITIVES = new PrimitiveTypePermission(); public boolean allows(Class type) { - return type != null && type.isPrimitive() || Primitives.isBoxed(type); + return type != null && type != void.class && type != Void.class && type.isPrimitive() + || Primitives.isBoxed(type); } public int hashCode() {
xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+23 −1 modified@@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2014 XStream Committers. + * Copyright (C) 2013, 2014, 2017 XStream Committers. * All rights reserved. * * The software in this package is published under the terms of the BSD @@ -13,9 +13,12 @@ import java.beans.EventHandler; import com.thoughtworks.xstream.XStreamException; +import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; +import com.thoughtworks.xstream.security.ForbiddenClassException; import com.thoughtworks.xstream.security.ProxyTypePermission; + /** * @author Jörg Schaible */ @@ -80,4 +83,23 @@ public void exec() { BUFFER.append("Executed!"); } } + + public void testDeniedInstanceOfVoid() { + try { + xstream.fromXML("<void/>"); + fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); + } catch (final ForbiddenClassException e) { + // OK + } + } + + public void testAllowedInstanceOfVoid() { + xstream.allowTypes(new Class[] { void.class, Void.class }); + try { + xstream.fromXML("<void/>"); + fail("Thrown " + ConversionException.class.getName() + " expected"); + } catch (final ConversionException e) { + assertEquals("void", e.get("construction-type")); + } + } }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
14- www.debian.org/security/2017/dsa-3841ghsavendor-advisoryx_refsource_DEBIANWEB
- access.redhat.com/errata/RHSA-2017:1832ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2017:2888ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2017:2889ghsavendor-advisoryx_refsource_REDHATWEB
- github.com/advisories/GHSA-7hwc-46rm-65jhghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2017-7957ghsaADVISORY
- www.securityfocus.com/bid/100687ghsavdb-entryx_refsource_BIDWEB
- www.securitytracker.com/id/1039499ghsavdb-entryx_refsource_SECTRACKWEB
- x-stream.github.io/CVE-2017-7957.htmlghsax_refsource_CONFIRMWEB
- exchange.xforce.ibmcloud.com/vulnerabilities/125800ghsavdb-entryx_refsource_XFWEB
- github.com/x-stream/xstream/commit/6e546ec366419158b1e393211be6d78ab9604abghsaWEB
- github.com/x-stream/xstream/commit/8542d02d9ac5d384c85f4b33d6c1888c53bd55dghsaWEB
- github.com/x-stream/xstream/commit/b3570be2f39234e61f99f9a20640756ea71b1b4ghsaWEB
- www-prd-trops.events.ibm.com/node/715749ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.