Version in base suite: 1.4.11.1-1 Base version: libxstream-java_1.4.11.1-1 Target version: libxstream-java_1.4.11.1-1+deb10u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libx/libxstream-java/libxstream-java_1.4.11.1-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libx/libxstream-java/libxstream-java_1.4.11.1-1+deb10u1.dsc changelog | 13 + patches/CVE-2020-26217.patch | 328 +++++++++++++++++++++++++++++++++++++++++++ patches/series | 1 3 files changed, 342 insertions(+) diff -Nru libxstream-java-1.4.11.1/debian/changelog libxstream-java-1.4.11.1/debian/changelog --- libxstream-java-1.4.11.1/debian/changelog 2018-11-10 23:04:59.000000000 +0000 +++ libxstream-java-1.4.11.1/debian/changelog 2020-12-01 22:35:51.000000000 +0000 @@ -1,3 +1,16 @@ +libxstream-java (1.4.11.1-1+deb10u1) buster-security; urgency=high + + * Team upload. + * Fix CVE-2020-26217: + It was found that XStream is vulnerable to Remote Code Execution. The + vulnerability may allow a remote attacker to run arbitrary shell commands + only by manipulating the processed input stream. Users who rely on + blocklists are affected (the default in Debian). We strongly recommend to + use the whitelist approach of XStream's Security Framework because there + are likely more class combinations the blacklist approach may not address. + + -- Markus Koschany Tue, 01 Dec 2020 23:35:51 +0100 + libxstream-java (1.4.11.1-1) unstable; urgency=medium * Team upload. diff -Nru libxstream-java-1.4.11.1/debian/patches/CVE-2020-26217.patch libxstream-java-1.4.11.1/debian/patches/CVE-2020-26217.patch --- libxstream-java-1.4.11.1/debian/patches/CVE-2020-26217.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxstream-java-1.4.11.1/debian/patches/CVE-2020-26217.patch 2020-12-01 22:35:51.000000000 +0000 @@ -0,0 +1,328 @@ +From: Markus Koschany +Date: Tue, 1 Dec 2020 23:11:04 +0100 +Subject: CVE-2020-26217 + +Origin: https://github.com/x-stream/xstream/commit/6ec68c4e4192faec64f350e9449f44bc120c813b +Origin: https://github.com/x-stream/xstream/commit/51abe602e09016c8e43e91325a15226022f4da46 +Origin: https://github.com/x-stream/xstream/commit/0fec095d534126931c99fd38e9c6d41f5c685c1a +--- + .../src/java/com/thoughtworks/xstream/XStream.java | 40 ++---- + .../acceptance/SecurityVulnerabilityTest.java | 136 ++++++++++++++++----- + 2 files changed, 121 insertions(+), 55 deletions(-) + +diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java +index a088877..0ae38b6 100644 +--- a/xstream/src/java/com/thoughtworks/xstream/XStream.java ++++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java +@@ -1,6 +1,6 @@ + /* + * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes. +- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 XStream Committers. ++ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2020 XStream Committers. + * All rights reserved. + * + * The software in this package is published under the terms of the BSD +@@ -36,6 +36,7 @@ import java.net.URL; + import java.nio.charset.Charset; + import java.text.DecimalFormatSymbols; + import java.util.ArrayList; ++import java.util.Arrays; + import java.util.BitSet; + import java.util.Calendar; + import java.util.Collection; +@@ -65,10 +66,8 @@ import com.thoughtworks.xstream.converters.Converter; + 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; +@@ -355,6 +354,8 @@ public class XStream { + + private static final String ANNOTATION_MAPPER_TYPE = "com.thoughtworks.xstream.mapper.AnnotationMapper"; + private static final Pattern IGNORE_ALL = Pattern.compile(".*"); ++ private static final Pattern LAZY_ITERATORS = Pattern.compile(".*\\$LazyIterator"); ++ private static final Pattern JAVAX_CRYPTO = Pattern.compile("javax\\.crypto\\..*"); + + /** + * Constructs a default XStream. +@@ -697,6 +698,12 @@ public class XStream { + } + + addPermission(AnyTypePermission.ANY); ++ denyTypes(new String[]{"java.beans.EventHandler", "javax.imageio.ImageIO$ContainsFilter"}); ++ denyTypes(new Class[]{ java.lang.ProcessBuilder.class, ++ java.beans.EventHandler.class, java.lang.ProcessBuilder.class, ++ java.lang.Void.class, void.class }); ++ denyTypesByRegExp(new Pattern[] {LAZY_ITERATORS, JAVAX_CRYPTO}); ++ allowTypeHierarchy(Exception.class); + securityInitialized = false; + } + +@@ -962,7 +969,6 @@ public class XStream { + 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); +@@ -1482,7 +1488,8 @@ public class XStream { + try { + if (!securityInitialized && !securityWarningGiven) { + securityWarningGiven = true; +- System.err.println("Security framework of XStream not initialized, XStream is probably vulnerable."); ++ System.err ++ .println("Security framework of XStream not explicitly initialized, using predefined black list on your own risk."); + } + return marshallingStrategy.unmarshal( + root, reader, dataHolder, converterLookup, mapper); +@@ -2360,7 +2367,7 @@ public class XStream { + */ + public void addPermission(TypePermission permission) { + if (securityMapper != null) { +- securityInitialized = true; ++ securityInitialized |= permission.equals(NoTypePermission.NONE) || permission.equals(AnyTypePermission.ANY); + securityMapper.addPermission(permission); + } + } +@@ -2539,25 +2546,4 @@ public class XStream { + super(message); + } + } +- +- private class InternalBlackList implements Converter { +- +- public boolean canConvert(final Class type) { +- return (type == void.class || type == Void.class) +- || (!securityInitialized +- && type != null +- && (type.getName().equals("java.beans.EventHandler") +- || type.getName().endsWith("$LazyIterator") +- || type.getName().startsWith("javax.crypto."))); +- } +- +- public void marshal(final Object source, final HierarchicalStreamWriter writer, +- final MarshallingContext context) { +- throw new ConversionException("Security alert. Marshalling rejected."); +- } +- +- public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) { +- throw new ConversionException("Security alert. Unmarshalling rejected."); +- } +- } + } +diff --git a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java +index 85eaf1c..44b0015 100644 +--- a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java ++++ b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java +@@ -11,13 +11,15 @@ + package com.thoughtworks.acceptance; + + import java.beans.EventHandler; ++import java.util.Iterator; + + import com.thoughtworks.xstream.XStream; + import com.thoughtworks.xstream.XStreamException; + import com.thoughtworks.xstream.converters.ConversionException; +-import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; ++import com.thoughtworks.xstream.core.JVM; ++import com.thoughtworks.xstream.security.AnyTypePermission; + import com.thoughtworks.xstream.security.ForbiddenClassException; +-import com.thoughtworks.xstream.security.ProxyTypePermission; ++import com.thoughtworks.xstream.security.NoTypePermission; + + + /** +@@ -31,21 +33,22 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest { + super.setUp(); + BUFFER.setLength(0); + xstream.alias("runnable", Runnable.class); +- xstream.allowTypeHierarchy(Runnable.class); +- xstream.addPermission(ProxyTypePermission.PROXIES); ++ } ++ ++ protected void setupSecurity(XStream xstream) { + } + + public void testCannotInjectEventHandler() { + final String xml = "" +- + "\n" +- + " \n" +- + " java.lang.Runnable\n" +- + " \n" +- + " \n" +- + " exec\n" +- + " \n" +- + " \n" +- + ""; ++ + "\n" ++ + " \n" ++ + " java.lang.Runnable\n" ++ + " \n" ++ + " \n" ++ + " exec\n" ++ + " \n" ++ + " \n" ++ + ""; + + try { + xstream.fromXML(xml); +@@ -57,7 +60,6 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest { + } + + public void testCannotInjectEventHandlerWithUnconfiguredSecurityFramework() { +- xstream = new XStream(createDriver()); + xstream.alias("runnable", Runnable.class); + final String xml = "" + + "\n" +@@ -74,26 +76,24 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest { + xstream.fromXML(xml); + fail("Thrown " + XStreamException.class.getName() + " expected"); + } catch (final XStreamException e) { +- assertTrue(e.getMessage().indexOf(EventHandler.class.getName())>=0); ++ assertTrue(e.getMessage().indexOf(EventHandler.class.getName()) >= 0); + } + assertEquals(0, BUFFER.length()); + } + + public void testExplicitlyConvertEventHandler() { + final String xml = "" +- + "\n" +- + " \n" +- + " java.lang.Runnable\n" +- + " \n" +- + " \n" +- + " exec\n" +- + " \n" +- + " \n" +- + ""; ++ + "\n" ++ + " \n" ++ + " java.lang.Runnable\n" ++ + " \n" ++ + " \n" ++ + " exec\n" ++ + " \n" ++ + " \n" ++ + ""; + + xstream.allowTypes(new Class[]{EventHandler.class}); +- xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream +- .getReflectionProvider(), EventHandler.class)); + + final Runnable[] array = (Runnable[])xstream.fromXML(xml); + assertEquals(0, BUFFER.length()); +@@ -101,6 +101,71 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest { + assertEquals("Executed!", BUFFER.toString()); + } + ++ public void testCannotInjectConvertImageIOContainsFilterWithUnconfiguredSecurityFramework() { ++ if (JVM.isVersion(7)) { ++ final String xml = "" ++ + "\n" ++ + " \n" ++ + " 0\n" ++ + " 1\n" ++ + " 1\n" ++ + " \n" ++ + " \n" ++ + " \n" ++ + " \n" ++ + " \n" ++ + " \n" ++ + " com.thoughtworks.acceptance.SecurityVulnerabilityTest$Exec\n" ++ + " exec\n" ++ + " \n" ++ + " \n" ++ + " exec\n" ++ + " \n" ++ + " \n" ++ + ""; ++ ++ try { ++ xstream.fromXML(xml); ++ fail("Thrown " + XStreamException.class.getName() + " expected"); ++ } catch (final XStreamException e) { ++ assertTrue(e.getMessage().indexOf("javax.imageio.ImageIO$ContainsFilter") >= 0); ++ } ++ assertEquals(0, BUFFER.length()); ++ } ++ } ++ ++ public void testExplicitlyConvertImageIOContainsFilter() { ++ if (JVM.isVersion(7)) { ++ final String xml = "" ++ + "\n" ++ + " \n" ++ + " 0\n" ++ + " 1\n" ++ + " 1\n" ++ + " \n" ++ + " \n" ++ + " \n" ++ + " \n" ++ + " \n" ++ + " \n" ++ + " com.thoughtworks.acceptance.SecurityVulnerabilityTest$Exec\n" ++ + " exec\n" ++ + " \n" ++ + " \n" ++ + " exec\n" ++ + " \n" ++ + " \n" ++ + ""; ++ ++ xstream.allowTypes(new String[]{"javax.imageio.ImageIO$ContainsFilter"}); ++ ++ final Iterator iterator = (Iterator)xstream.fromXML(xml); ++ assertEquals(0, BUFFER.length()); ++ iterator.next(); ++ assertEquals("Executed!", BUFFER.toString()); ++ } ++ } ++ + public static class Exec { + + public void exec() { +@@ -109,6 +174,8 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest { + } + + public void testDeniedInstanceOfVoid() { ++ xstream.addPermission(AnyTypePermission.ANY); // clear out defaults ++ xstream.denyTypes(new Class[] { void.class, Void.class }); + try { + xstream.fromXML(""); + fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); +@@ -118,12 +185,25 @@ public class SecurityVulnerabilityTest extends AbstractAcceptanceTest { + } + + public void testAllowedInstanceOfVoid() { +- xstream.allowTypes(new Class[] { void.class, Void.class }); ++ xstream.allowTypes(new Class[]{void.class, Void.class}); + try { + xstream.fromXML(""); + fail("Thrown " + ConversionException.class.getName() + " expected"); + } catch (final ConversionException e) { +- assertEquals("void", e.get("required-type")); ++ assertEquals("void", e.get("construction-type")); ++ } ++ } ++ ++ public static class LazyIterator { ++ } ++ ++ public void testInstanceOfLazyIterator() { ++ xstream.alias("lazy-iterator", LazyIterator.class); ++ try { ++ xstream.fromXML(""); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ // OK + } + } + } diff -Nru libxstream-java-1.4.11.1/debian/patches/series libxstream-java-1.4.11.1/debian/patches/series --- libxstream-java-1.4.11.1/debian/patches/series 2018-11-10 23:04:59.000000000 +0000 +++ libxstream-java-1.4.11.1/debian/patches/series 2020-12-01 22:35:51.000000000 +0000 @@ -1 +1,2 @@ 01-java7-compatibility.patch +CVE-2020-26217.patch