Upgrade to 1.4.20 for fix CVE-2022-40151 and CVE-2022-41966
(cherry picked from commit 118839b555b27f3be23f74f2a99fd56738adc617)
This commit is contained in:
parent
8a4aa33cd5
commit
48e3bbe100
@ -1,877 +0,0 @@
|
|||||||
From e8e88621ba1c85ac3b8620337dd672e0c0c3a846 Mon Sep 17 00:00:00 2001
|
|
||||||
From: joehni <joerg.schaible@gmx.de>
|
|
||||||
Date: Mon, 27 Dec 2021 01:24:08 +0100
|
|
||||||
Subject: [PATCH] Describe and fix CVE-2021-43859.
|
|
||||||
|
|
||||||
---
|
|
||||||
.../src/content/CVE-2021-43859.html | 199 ++++++++++++++++++
|
|
||||||
.../src/content/security.html | 40 +++-
|
|
||||||
xstream-distribution/src/content/website.xml | 1 +
|
|
||||||
.../com/thoughtworks/xstream/XStream.java | 42 +++-
|
|
||||||
.../collections/CollectionConverter.java | 6 +-
|
|
||||||
.../converters/collections/MapConverter.java | 6 +-
|
|
||||||
.../extended/NamedMapConverter.java | 5 +-
|
|
||||||
.../xstream/core/SecurityUtils.java | 56 +++++
|
|
||||||
.../xstream/core/TreeUnmarshaller.java | 3 +
|
|
||||||
.../security/AbstractSecurityException.java | 29 +++
|
|
||||||
.../security/ForbiddenClassException.java | 6 +-
|
|
||||||
.../security/InputManipulationException.java | 27 +++
|
|
||||||
.../acceptance/SecurityVulnerabilityTest.java | 155 +++++++++++++-
|
|
||||||
14 files changed, 568 insertions(+), 21 deletions(-)
|
|
||||||
create mode 100644 xstream-distribution/src/content/CVE-2021-43859.html
|
|
||||||
create mode 100644 xstream/src/java/com/thoughtworks/xstream/core/SecurityUtils.java
|
|
||||||
create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/AbstractSecurityException.java
|
|
||||||
create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/InputManipulationException.java
|
|
||||||
|
|
||||||
diff --git a/xstream-distribution/src/content/CVE-2021-43859.html b/xstream-distribution/src/content/CVE-2021-43859.html
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..531298d3
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/xstream-distribution/src/content/CVE-2021-43859.html
|
|
||||||
@@ -0,0 +1,199 @@
|
|
||||||
+<html>
|
|
||||||
+<!--
|
|
||||||
+ Copyright (C) 2021 XStream committers.
|
|
||||||
+ All rights reserved.
|
|
||||||
+
|
|
||||||
+ The software in this package is published under the terms of the BSD
|
|
||||||
+ style license a copy of which has been included with this distribution in
|
|
||||||
+ the LICENSE.txt file.
|
|
||||||
+
|
|
||||||
+ Created on 23. December 2021 by Joerg Schaible
|
|
||||||
+ -->
|
|
||||||
+ <head>
|
|
||||||
+ <title>CVE-2021-43859</title>
|
|
||||||
+ </head>
|
|
||||||
+ <body>
|
|
||||||
+
|
|
||||||
+ <h2 id="vulnerability">Vulnerability</h2>
|
|
||||||
+
|
|
||||||
+ <p>CVE-2021-43859: XStream can cause a Denial of Service by injecting highly recursive collections or maps.</p>
|
|
||||||
+
|
|
||||||
+ <h2 id="affected_versions">Affected Versions</h2>
|
|
||||||
+
|
|
||||||
+ <p>All versions until and including version 1.4.18 are affected.</p>
|
|
||||||
+
|
|
||||||
+ <h2 id="description">Description</h2>
|
|
||||||
+
|
|
||||||
+ <p>The processed stream at unmarshalling time contains type information to recreate the formerly written objects.
|
|
||||||
+ XStream creates therefore new instances based on these type information. An attacker can manipulate the processed
|
|
||||||
+ input stream and replace or inject objects, that result in exponential recursively hashcode calculation, causing a denial
|
|
||||||
+ of service.</p>
|
|
||||||
+
|
|
||||||
+ <h2 id="reproduction">Steps to Reproduce</h2>
|
|
||||||
+
|
|
||||||
+ <p>The attack uses the hashcode implementation of collection types in the Java runtime. Following types are affected with
|
|
||||||
+ lastest Java versions available in December 2021:</p>
|
|
||||||
+ <ul>
|
|
||||||
+ <li>java.util.HashMap</li>
|
|
||||||
+ <li>java.util.HashSet</li>
|
|
||||||
+ <li>java.util.Hashtable</li>
|
|
||||||
+ <li>java.util.LinkedHashMap</li>
|
|
||||||
+ <li>java.util.LinkedHashSet</li>
|
|
||||||
+ <li>java.util.Stack (older Java revisions only)</li>
|
|
||||||
+ <li>java.util.Vector (older Java revisions only)</li>
|
|
||||||
+ <li>Other third party collection implementations that use their element's hash code may also be affected</li>
|
|
||||||
+ </ul>
|
|
||||||
+ <p>Create a simple HashSet and use XStream to marshal it to XML. Replace the XML with following snippet, increase the
|
|
||||||
+ depth of the structure and unmarshal it with XStream:</p>
|
|
||||||
+<div class="Source XML"><pre><set>
|
|
||||||
+ <set>
|
|
||||||
+ <string>a</string>
|
|
||||||
+ <set>
|
|
||||||
+ <string>a</string>
|
|
||||||
+ <set>
|
|
||||||
+ <string>a</string>
|
|
||||||
+ </set>
|
|
||||||
+ <set>
|
|
||||||
+ <string>b</string>
|
|
||||||
+ </set>
|
|
||||||
+ </set>
|
|
||||||
+ <set>
|
|
||||||
+ <set reference="../../set/set"/>
|
|
||||||
+ <string>b</string>
|
|
||||||
+ <set reference="../../set/set[2]"/>
|
|
||||||
+ </set>
|
|
||||||
+ </set>
|
|
||||||
+ <set>
|
|
||||||
+ <set reference="../../set/set"/>
|
|
||||||
+ <string>b</string>
|
|
||||||
+ <set reference="../../set/set[2]"/>
|
|
||||||
+ </set>
|
|
||||||
+</set>
|
|
||||||
+</pre></div>
|
|
||||||
+<div class="Source Java"><pre>XStream xstream = new XStream();
|
|
||||||
+xstream.fromXML(xml);
|
|
||||||
+</pre></div>
|
|
||||||
+ <p>Create a simple HashMap and use XStream to marshal it to XML. Replace the XML with following snippet, increase the
|
|
||||||
+ depth of the structure and unmarshal it with XStream:</p>
|
|
||||||
+<div class="Source XML"><pre><map>
|
|
||||||
+ <entry>
|
|
||||||
+ <map>
|
|
||||||
+ <entry>
|
|
||||||
+ <string>a</string>
|
|
||||||
+ <string>b</string>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map>
|
|
||||||
+ <entry>
|
|
||||||
+ <string>a</string>
|
|
||||||
+ <string>b</string>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map>
|
|
||||||
+ <entry>
|
|
||||||
+ <string>a</string>
|
|
||||||
+ <string>b</string>
|
|
||||||
+ </entry>
|
|
||||||
+ </map>
|
|
||||||
+ <map>
|
|
||||||
+ <entry>
|
|
||||||
+ <string>c</string>
|
|
||||||
+ <string>d</string>
|
|
||||||
+ </entry>
|
|
||||||
+ </map>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map reference="../../entry[2]/map[2]"/>
|
|
||||||
+ <map reference="../../entry[2]/map"/>
|
|
||||||
+ </entry>
|
|
||||||
+ </map>
|
|
||||||
+ <map>
|
|
||||||
+ <entry>
|
|
||||||
+ <string>c</string>
|
|
||||||
+ <string>d</string>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map reference="../../../entry[2]/map"/>
|
|
||||||
+ <map reference="../../../entry[2]/map[2]"/>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map reference="../../../entry[2]/map[2]"/>
|
|
||||||
+ <map reference="../../../entry[2]/map"/>
|
|
||||||
+ </entry>
|
|
||||||
+ </map>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map reference="../../entry[2]/map[2]"/>
|
|
||||||
+ <map reference="../../entry[2]/map"/>
|
|
||||||
+ </entry>
|
|
||||||
+ </map>
|
|
||||||
+ <map>
|
|
||||||
+ <entry>
|
|
||||||
+ <string>c</string>
|
|
||||||
+ <string>d</string>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map reference="../../../entry[2]/map"/>
|
|
||||||
+ <map reference="../../../entry[2]/map[2]"/>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map reference="../../../entry[2]/map[2]"/>
|
|
||||||
+ <map reference="../../../entry[2]/map"/>
|
|
||||||
+ </entry>
|
|
||||||
+ </map>
|
|
||||||
+ </entry>
|
|
||||||
+ <entry>
|
|
||||||
+ <map reference="../../entry[2]/map[2]"/>
|
|
||||||
+ <map reference="../../entry[2]/map"/>
|
|
||||||
+ </entry>
|
|
||||||
+</map>
|
|
||||||
+</pre></div>
|
|
||||||
+<div class="Source Java"><pre>XStream xstream = new XStream();
|
|
||||||
+xstream.fromXML(xml);
|
|
||||||
+</pre></div>
|
|
||||||
+
|
|
||||||
+ <p>As soon as the XML is unmarshalled, the hash codes of the elements are calculated and the calculation time increases
|
|
||||||
+ exponentially due to the highly recursive structure.</p>
|
|
||||||
+
|
|
||||||
+ <p>Note, this example uses XML, but the attack can be performed for any supported format, that supports references, i.e.
|
|
||||||
+ JSON is not affected.</p>
|
|
||||||
+
|
|
||||||
+ <h2 id="impact">Impact</h2>
|
|
||||||
+
|
|
||||||
+ <p>The vulnerability may allow a remote attacker to allocate 100% CPU time on the target system depending on CPU
|
|
||||||
+ type or parallel execution of such a payload resulting in a denial of service only by manipulating the processed
|
|
||||||
+ input stream.</p>
|
|
||||||
+
|
|
||||||
+ <h2 id="workarounds">Workarounds</h2>
|
|
||||||
+
|
|
||||||
+ <p>If your object graph does not use referenced elements at all, you may simply set the NO_REFERENCE mode:</p>
|
|
||||||
+
|
|
||||||
+<div class="Source Java"><pre>XStream xstream = new XStream();
|
|
||||||
+xstream.setMode(XStream.NO_REFERENCES);
|
|
||||||
+</pre></div>
|
|
||||||
+
|
|
||||||
+ <p>If your object graph contains neither a Hashtable, HashMap nor a HashSet (or one of the linked variants of it) then you
|
|
||||||
+ can use the security framework to deny the usage of these types:</p>
|
|
||||||
+
|
|
||||||
+<div class="Source Java"><pre>XStream xstream = new XStream();
|
|
||||||
+xstream.denyTypes(new Class[]{
|
|
||||||
+ java.util.HashMap.class, java.util.HashSet.class, java.util.Hashtable.class, java.util.LinkedHashMap.class, java.util.LinkedHashSet.class
|
|
||||||
+});
|
|
||||||
+</pre></div>
|
|
||||||
+
|
|
||||||
+ <p>Unfortunately these types are very common. If you only use HashMap or HashSet and your XML refers these only as default
|
|
||||||
+ map or set, you may additionally change the default implementation of java.util.Map and java.util.Set at unmarshalling time:</p>
|
|
||||||
+
|
|
||||||
+<div class="Source Java"><pre>xstream.addDefaultImplementation(java.util.TreeMap.class, java.util.Map.class);
|
|
||||||
+xstream.addDefaultImplementation(java.util.TreeSet.class, java.util.Set.class);
|
|
||||||
+</pre></div>
|
|
||||||
+
|
|
||||||
+ <p>However, this implies that your application does not care about the implementation of the map and all elements are comparable.</p>
|
|
||||||
+
|
|
||||||
+ <h2 id="credits">Credits</h2>
|
|
||||||
+
|
|
||||||
+ <p>r00t4dm at Cloud-Penetrating Arrow Lab found and reported the issue to XStream and provided the required information to
|
|
||||||
+ reproduce it.</p>
|
|
||||||
+
|
|
||||||
+ </body>
|
|
||||||
+ </html>
|
|
||||||
diff --git a/xstream-distribution/src/content/security.html b/xstream-distribution/src/content/security.html
|
|
||||||
index f0e0177c..fe0a8217 100644
|
|
||||||
--- a/xstream-distribution/src/content/security.html
|
|
||||||
+++ b/xstream-distribution/src/content/security.html
|
|
||||||
@@ -30,13 +30,13 @@
|
|
||||||
context of the server running the XStream process or cause a denial of service by crashing the application or
|
|
||||||
manage to enter an endless loop consuming 100% of CPU cycles.</p>
|
|
||||||
|
|
||||||
- <p class=highlight>Note: XStream supports other data formats than XML, e.g. JSON. Those formats can be used for
|
|
||||||
- the same attacks.</p>
|
|
||||||
+ <p class=highlight>Note: XStream supports other data formats than XML, e.g. JSON. Those formats can usually be used
|
|
||||||
+ for the same attacks.</p>
|
|
||||||
|
|
||||||
- <p>Note, that the XML data can be manipulated on different levels. For example, manipulating values on existing
|
|
||||||
- objects (such as a price value), accessing private data, or breaking the format and causing the XML parser to fail.
|
|
||||||
- The latter case will raise an exception, but the former case must be handled by validity checks in any application
|
|
||||||
- which processes user-supplied XML.</p>
|
|
||||||
+ <p>The XML data can be manipulated on different levels. For example, manipulating values on existing objects (such
|
|
||||||
+ as a price value), accessing private data, or breaking the format and causing the XML parser to fail. The latter
|
|
||||||
+ case will raise an exception, but the former case must be handled by validity checks in any application which
|
|
||||||
+ processes user-supplied XML.</p>
|
|
||||||
|
|
||||||
<h2 id="CVEs">Documented Vulnerabilities</h2>
|
|
||||||
|
|
||||||
@@ -49,6 +49,14 @@ <h2 id="CVEs">Documented Vulnerabilities</h2>
|
|
||||||
<th>CVE</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
+ <tr>
|
|
||||||
+ <th>Version 1.4.18</th>
|
|
||||||
+ <td></td>
|
|
||||||
+ </tr>
|
|
||||||
+ <tr>
|
|
||||||
+ <th><a href="CVE-2021-43859.html">CVE-2021-43859</a></th>
|
|
||||||
+ <td>XStream can cause a Denial of Service by injecting highly recursive collections or maps.</td>
|
|
||||||
+ </tr>
|
|
||||||
<tr>
|
|
||||||
<th>Version 1.4.17</th>
|
|
||||||
<td></td>
|
|
||||||
@@ -258,6 +266,16 @@ <h2 id="implicit">Implicit Security</h2>
|
|
||||||
because no-one can assure, that no other vulnerability is found. A better approach is the usage of a whitelist
|
|
||||||
i.e. the allowed class types are setup explicitly. This is the default for XStream 1.4.18 (see below).</p>
|
|
||||||
|
|
||||||
+ <p>XStream supports references to objects already occuring on the object graph in an earlier location. This allows
|
|
||||||
+ an attacker to create a highly recursive object structure. Some collections or maps calculate the position of a
|
|
||||||
+ member based on the data of the member itself. This is true for sorting collections or maps, but also for
|
|
||||||
+ collections or maps based on the hash code of the individual members. The calculation time for the member's
|
|
||||||
+ position can increase exponentially depending on the recursive depth of the structure and cause therefore a Denial
|
|
||||||
+ of Service. Therefore XStream measures the time consumed to add an element to a collection or map since version
|
|
||||||
+ 1.4.19. Normally this operation is performed in a view milliseconds, but if adding elements take longer than a
|
|
||||||
+ second, then the time is accumulated and an exception is thrown if it exceeds a definable limit (20 seconds by
|
|
||||||
+ default).</p>
|
|
||||||
+
|
|
||||||
<h2 id="explicit">Explicit Security</h2>
|
|
||||||
|
|
||||||
<p>Starting with XStream 1.4.7, it is possible to define <a href="#framework">permissions</a> for types, to check
|
|
||||||
@@ -285,6 +303,16 @@ <h2 id="explicit">Explicit Security</h2>
|
|
||||||
<p class=highlight>Apart from value manipulations, this implementation still allows the injection of allowed
|
|
||||||
objects at wrong locations, e.g. inserting an integer into a list of strings.</p>
|
|
||||||
|
|
||||||
+ <p>To avoid an attack based on the position of an element in a collection or map, you should also use XStream's
|
|
||||||
+ default converters for 3rd party or own implementations of collections or maps. Own custom converters of such
|
|
||||||
+ types should measure the time to add an element at deserialization time using the following sequence in the
|
|
||||||
+ implementation of the unmarshal method:<div class="Source Java">
|
|
||||||
+<pre>// unmarshal element of collection
|
|
||||||
+long now = System.currentTimeMillis();
|
|
||||||
+// add element here, e.g. list.add(element);
|
|
||||||
+SecurityUtils.checkForCollectionDoSAttack(context, now);
|
|
||||||
+</pre></div></p>
|
|
||||||
+
|
|
||||||
<h2 id="validation">XML Validation</h2>
|
|
||||||
|
|
||||||
<p>XML itself supports input validation using a schema and a validating parser. With XStream, you can use e.g. a
|
|
||||||
diff --git a/xstream-distribution/src/content/website.xml b/xstream-distribution/src/content/website.xml
|
|
||||||
index 157baeb9..ad85d03d 100644
|
|
||||||
--- a/xstream-distribution/src/content/website.xml
|
|
||||||
+++ b/xstream-distribution/src/content/website.xml
|
|
||||||
@@ -89,6 +89,7 @@
|
|
||||||
<page>CVE-2021-39152.html</page>
|
|
||||||
<page>CVE-2021-39153.html</page>
|
|
||||||
<page>CVE-2021-39154.html</page>
|
|
||||||
+ <page>CVE-2021-43859.html</page>
|
|
||||||
<page>CVE-2020-26217.html</page>
|
|
||||||
<page>CVE-2020-26258.html</page>
|
|
||||||
<page>CVE-2020-26259.html</page>
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
||||||
index 7d90dc7f..9787059d 100644
|
|
||||||
--- a/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java
|
|
||||||
@@ -151,6 +151,7 @@
|
|
||||||
import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper;
|
|
||||||
import com.thoughtworks.xstream.security.AnyTypePermission;
|
|
||||||
import com.thoughtworks.xstream.security.ArrayTypePermission;
|
|
||||||
+import com.thoughtworks.xstream.security.InputManipulationException;
|
|
||||||
import com.thoughtworks.xstream.security.ExplicitTypePermission;
|
|
||||||
import com.thoughtworks.xstream.security.InterfaceTypePermission;
|
|
||||||
import com.thoughtworks.xstream.security.NoPermission;
|
|
||||||
@@ -295,6 +296,8 @@
|
|
||||||
|
|
||||||
// CAUTION: The sequence of the fields is intentional for an optimal XML output of a
|
|
||||||
// self-serialization!
|
|
||||||
+ private int collectionUpdateLimit = 20;
|
|
||||||
+
|
|
||||||
private ReflectionProvider reflectionProvider;
|
|
||||||
private HierarchicalStreamDriver hierarchicalStreamDriver;
|
|
||||||
private ClassLoaderReference classLoaderReference;
|
|
||||||
@@ -329,6 +332,9 @@
|
|
||||||
public static final int PRIORITY_LOW = -10;
|
|
||||||
public static final int PRIORITY_VERY_LOW = -20;
|
|
||||||
|
|
||||||
+ public static final String COLLECTION_UPDATE_LIMIT = "XStreamCollectionUpdateLimit";
|
|
||||||
+ public static final String COLLECTION_UPDATE_SECONDS = "XStreamCollectionUpdateSeconds";
|
|
||||||
+
|
|
||||||
private static final String ANNOTATION_MAPPER_TYPE = "com.thoughtworks.xstream.mapper.AnnotationMapper";
|
|
||||||
private static final Pattern IGNORE_ALL = Pattern.compile(".*");
|
|
||||||
|
|
||||||
@@ -1182,6 +1188,23 @@ public void setMarshallingStrategy(MarshallingStrategy marshallingStrategy) {
|
|
||||||
this.marshallingStrategy = marshallingStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /**
|
|
||||||
+ * Set time limit for adding elements to collections or maps.
|
|
||||||
+ *
|
|
||||||
+ * Manipulated content may be used to create recursive hash code calculations or sort operations. An
|
|
||||||
+ * {@link InputManipulationException} is thrown, it the summed up time to add elements to collections or maps
|
|
||||||
+ * exceeds the provided limit.
|
|
||||||
+ *
|
|
||||||
+ * Note, that the time to add an individual element is calculated in seconds, not milliseconds. However, attacks
|
|
||||||
+ * typically use objects with exponential growing calculation times.
|
|
||||||
+ *
|
|
||||||
+ * @param maxSeconds limit in seconds or 0 to disable check
|
|
||||||
+ * @since upcoming
|
|
||||||
+ */
|
|
||||||
+ public void setCollectionUpdateLimit(int maxSeconds) {
|
|
||||||
+ collectionUpdateLimit = maxSeconds;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* Serialize an object to a pretty-printed XML String.
|
|
||||||
*
|
|
||||||
@@ -1388,6 +1411,13 @@ public Object unmarshal(HierarchicalStreamReader reader, Object root) {
|
|
||||||
*/
|
|
||||||
public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) {
|
|
||||||
try {
|
|
||||||
+ if (collectionUpdateLimit >= 0) {
|
|
||||||
+ if (dataHolder == null) {
|
|
||||||
+ dataHolder = new MapBackedDataHolder();
|
|
||||||
+ }
|
|
||||||
+ dataHolder.put(COLLECTION_UPDATE_LIMIT, new Integer(collectionUpdateLimit));
|
|
||||||
+ dataHolder.put(COLLECTION_UPDATE_SECONDS, new Integer(0));
|
|
||||||
+ }
|
|
||||||
return marshallingStrategy.unmarshal(root, reader, dataHolder, converterLookup, mapper);
|
|
||||||
} catch (ConversionException e) {
|
|
||||||
Package pkg = getClass().getPackage();
|
|
||||||
@@ -2053,15 +2083,23 @@ public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader
|
|
||||||
* @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
|
|
||||||
* @since 1.4.10
|
|
||||||
*/
|
|
||||||
- public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader reader, final DataHolder dataHolder)
|
|
||||||
+ public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader reader, DataHolder dataHolder)
|
|
||||||
throws IOException {
|
|
||||||
+ if (collectionUpdateLimit >= 0) {
|
|
||||||
+ if (dataHolder == null) {
|
|
||||||
+ dataHolder = new MapBackedDataHolder();
|
|
||||||
+ }
|
|
||||||
+ dataHolder.put(COLLECTION_UPDATE_LIMIT, new Integer(collectionUpdateLimit));
|
|
||||||
+ dataHolder.put(COLLECTION_UPDATE_SECONDS, new Integer(0));
|
|
||||||
+ }
|
|
||||||
+ final DataHolder dh = dataHolder;
|
|
||||||
return new CustomObjectInputStream(new CustomObjectInputStream.StreamCallback() {
|
|
||||||
public Object readFromStream() throws EOFException {
|
|
||||||
if (!reader.hasMoreChildren()) {
|
|
||||||
throw new EOFException();
|
|
||||||
}
|
|
||||||
reader.moveDown();
|
|
||||||
- final Object result = unmarshal(reader, null, dataHolder);
|
|
||||||
+ final Object result = unmarshal(reader, null, dh);
|
|
||||||
reader.moveUp();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/collections/CollectionConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/collections/CollectionConverter.java
|
|
||||||
index 94474193..f3606f1d 100644
|
|
||||||
--- a/xstream/src/java/com/thoughtworks/xstream/converters/collections/CollectionConverter.java
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/collections/CollectionConverter.java
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2003, 2004, 2005 Joe Walnes.
|
|
||||||
- * Copyright (C) 2006, 2007, 2010, 2011, 2013, 2018 XStream Committers.
|
|
||||||
+ * Copyright (C) 2006, 2007, 2010, 2011, 2013, 2018, 2021 XStream Committers.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The software in this package is published under the terms of the BSD
|
|
||||||
@@ -13,6 +13,7 @@
|
|
||||||
|
|
||||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
|
||||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
|
||||||
+import com.thoughtworks.xstream.core.SecurityUtils;
|
|
||||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
|
||||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
|
||||||
import com.thoughtworks.xstream.mapper.Mapper;
|
|
||||||
@@ -96,7 +97,10 @@ protected void populateCollection(HierarchicalStreamReader reader, Unmarshalling
|
|
||||||
protected void addCurrentElementToCollection(HierarchicalStreamReader reader, UnmarshallingContext context,
|
|
||||||
Collection collection, Collection target) {
|
|
||||||
final Object item = readItem(reader, context, collection); // call readBareItem when deprecated method is removed
|
|
||||||
+
|
|
||||||
+ long now = System.currentTimeMillis();
|
|
||||||
target.add(item);
|
|
||||||
+ SecurityUtils.checkForCollectionDoSAttack(context, now);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object createCollection(Class type) {
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/collections/MapConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/collections/MapConverter.java
|
|
||||||
index af007f95..f93cec8e 100644
|
|
||||||
--- a/xstream/src/java/com/thoughtworks/xstream/converters/collections/MapConverter.java
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/collections/MapConverter.java
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2003, 2004, 2005 Joe Walnes.
|
|
||||||
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2018 XStream Committers.
|
|
||||||
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2018, 2021 XStream Committers.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The software in this package is published under the terms of the BSD
|
|
||||||
@@ -13,6 +13,7 @@
|
|
||||||
|
|
||||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
|
||||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
|
||||||
+import com.thoughtworks.xstream.core.SecurityUtils;
|
|
||||||
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
|
|
||||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
|
||||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
|
||||||
@@ -104,7 +105,10 @@ protected void putCurrentEntryIntoMap(HierarchicalStreamReader reader, Unmarshal
|
|
||||||
Map map, Map target) {
|
|
||||||
final Object key = readCompleteItem(reader, context, map);
|
|
||||||
final Object value = readCompleteItem(reader, context, map);
|
|
||||||
+
|
|
||||||
+ long now = System.currentTimeMillis();
|
|
||||||
target.put(key, value);
|
|
||||||
+ SecurityUtils.checkForCollectionDoSAttack(context, now);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object createCollection(Class type) {
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedMapConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedMapConverter.java
|
|
||||||
index 4c5ec9cf..59021489 100644
|
|
||||||
--- a/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedMapConverter.java
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedMapConverter.java
|
|
||||||
@@ -1,5 +1,5 @@
|
|
||||||
/*
|
|
||||||
- * Copyright (C) 2013, 2016, 2018 XStream Committers.
|
|
||||||
+ * Copyright (C) 2013, 2016, 2018, 2021 XStream Committers.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The software in this package is published under the terms of the BSD
|
|
||||||
@@ -21,6 +21,7 @@
|
|
||||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
|
||||||
import com.thoughtworks.xstream.converters.collections.MapConverter;
|
|
||||||
import com.thoughtworks.xstream.core.JVM;
|
|
||||||
+import com.thoughtworks.xstream.core.SecurityUtils;
|
|
||||||
import com.thoughtworks.xstream.core.util.HierarchicalStreams;
|
|
||||||
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
|
|
||||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
|
||||||
@@ -339,7 +340,9 @@ protected void populateMap(HierarchicalStreamReader reader, UnmarshallingContext
|
|
||||||
value = valueConverter.fromString(reader.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
+ long now = System.currentTimeMillis();
|
|
||||||
target.put(key, value);
|
|
||||||
+ SecurityUtils.checkForCollectionDoSAttack(context, now);
|
|
||||||
|
|
||||||
if (entryName != null) {
|
|
||||||
reader.moveUp();
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/SecurityUtils.java b/xstream/src/java/com/thoughtworks/xstream/core/SecurityUtils.java
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..0eedd523
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/core/SecurityUtils.java
|
|
||||||
@@ -0,0 +1,56 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2021 XStream Committers.
|
|
||||||
+ * All rights reserved.
|
|
||||||
+ *
|
|
||||||
+ * The software in this package is published under the terms of the BSD
|
|
||||||
+ * style license a copy of which has been included with this distribution in
|
|
||||||
+ * the LICENSE.txt file.
|
|
||||||
+ *
|
|
||||||
+ * Created on 21. September 2021 by Joerg Schaible
|
|
||||||
+ */
|
|
||||||
+package com.thoughtworks.xstream.core;
|
|
||||||
+
|
|
||||||
+import com.thoughtworks.xstream.XStream;
|
|
||||||
+import com.thoughtworks.xstream.converters.ConversionException;
|
|
||||||
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
|
||||||
+import com.thoughtworks.xstream.security.InputManipulationException;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * Utility functions for security issues.
|
|
||||||
+ *
|
|
||||||
+ * @author Jörg Schaible
|
|
||||||
+ * @since upcoming
|
|
||||||
+ */
|
|
||||||
+public class SecurityUtils {
|
|
||||||
+
|
|
||||||
+ /**
|
|
||||||
+ * Check the consumed time adding elements to collections or maps.
|
|
||||||
+ *
|
|
||||||
+ * Every custom converter should call this method after an unmarshalled element has been added to a collection or
|
|
||||||
+ * map. In case of an attack the operation will take too long, because the calculation of the hash code or the
|
|
||||||
+ * comparison of the elements in the collection operate on recursive structures.
|
|
||||||
+ *
|
|
||||||
+ * @param context the unmarshalling context
|
|
||||||
+ * @param start the timestamp just before the element was added to the collection or map
|
|
||||||
+ * @since upcoming
|
|
||||||
+ */
|
|
||||||
+ public static void checkForCollectionDoSAttack(final UnmarshallingContext context, final long start) {
|
|
||||||
+ final int diff = (int)((System.currentTimeMillis() - start) / 1000);
|
|
||||||
+ if (diff > 0) {
|
|
||||||
+ final Integer secondsUsed = (Integer)context.get(XStream.COLLECTION_UPDATE_SECONDS);
|
|
||||||
+ if (secondsUsed != null) {
|
|
||||||
+ final Integer limit = (Integer)context.get(XStream.COLLECTION_UPDATE_LIMIT);
|
|
||||||
+ if (limit == null) {
|
|
||||||
+ throw new ConversionException("Missing limit for updating collections.");
|
|
||||||
+ }
|
|
||||||
+ final int seconds = secondsUsed.intValue() + diff;
|
|
||||||
+ if (seconds > limit.intValue()) {
|
|
||||||
+ throw new InputManipulationException(
|
|
||||||
+ "Denial of Service attack assumed. Adding elements to collections or maps exceeds " + limit.intValue() + " seconds.");
|
|
||||||
+ }
|
|
||||||
+ context.put(XStream.COLLECTION_UPDATE_SECONDS, new Integer(seconds));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/TreeUnmarshaller.java b/xstream/src/java/com/thoughtworks/xstream/core/TreeUnmarshaller.java
|
|
||||||
index a17363f4..be1ef0d7 100644
|
|
||||||
--- a/xstream/src/java/com/thoughtworks/xstream/core/TreeUnmarshaller.java
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/core/TreeUnmarshaller.java
|
|
||||||
@@ -26,6 +26,7 @@
|
|
||||||
import com.thoughtworks.xstream.core.util.PrioritizedList;
|
|
||||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
|
||||||
import com.thoughtworks.xstream.mapper.Mapper;
|
|
||||||
+import com.thoughtworks.xstream.security.AbstractSecurityException;
|
|
||||||
|
|
||||||
|
|
||||||
public class TreeUnmarshaller implements UnmarshallingContext {
|
|
||||||
@@ -74,6 +75,8 @@ protected Object convert(Object parent, Class type, Converter converter) {
|
|
||||||
} catch (final ConversionException conversionException) {
|
|
||||||
addInformationTo(conversionException, type, converter, parent);
|
|
||||||
throw conversionException;
|
|
||||||
+ } catch (AbstractSecurityException e) {
|
|
||||||
+ throw e;
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
ConversionException conversionException = new ConversionException(e);
|
|
||||||
addInformationTo(conversionException, type, converter, parent);
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/security/AbstractSecurityException.java b/xstream/src/java/com/thoughtworks/xstream/security/AbstractSecurityException.java
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..3ca6309c
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/security/AbstractSecurityException.java
|
|
||||||
@@ -0,0 +1,29 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2021 XStream Committers.
|
|
||||||
+ * All rights reserved.
|
|
||||||
+ *
|
|
||||||
+ * Created on 21. September 2021 by Joerg Schaible
|
|
||||||
+ */
|
|
||||||
+package com.thoughtworks.xstream.security;
|
|
||||||
+
|
|
||||||
+import com.thoughtworks.xstream.XStreamException;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * General base class for a Security Exception in XStream.
|
|
||||||
+ *
|
|
||||||
+ * @author Jörg Schaible
|
|
||||||
+ * @since upcoming
|
|
||||||
+ */
|
|
||||||
+public abstract class AbstractSecurityException extends XStreamException {
|
|
||||||
+ private static final long serialVersionUID = 20210921L;
|
|
||||||
+
|
|
||||||
+ /**
|
|
||||||
+ * Constructs a SecurityException.
|
|
||||||
+ * @param message the exception message
|
|
||||||
+ * @since upcoming
|
|
||||||
+ */
|
|
||||||
+ public AbstractSecurityException(final String message) {
|
|
||||||
+ super(message);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/security/ForbiddenClassException.java b/xstream/src/java/com/thoughtworks/xstream/security/ForbiddenClassException.java
|
|
||||||
index 017fc301..2eded6cf 100644
|
|
||||||
--- a/xstream/src/java/com/thoughtworks/xstream/security/ForbiddenClassException.java
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/security/ForbiddenClassException.java
|
|
||||||
@@ -1,20 +1,18 @@
|
|
||||||
/*
|
|
||||||
- * Copyright (C) 2014 XStream Committers.
|
|
||||||
+ * Copyright (C) 2014, 2021 XStream Committers.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Created on 08. January 2014 by Joerg Schaible
|
|
||||||
*/
|
|
||||||
package com.thoughtworks.xstream.security;
|
|
||||||
|
|
||||||
-import com.thoughtworks.xstream.XStreamException;
|
|
||||||
-
|
|
||||||
/**
|
|
||||||
* Exception thrown for a forbidden class.
|
|
||||||
*
|
|
||||||
* @author Jörg Schaible
|
|
||||||
* @since 1.4.7
|
|
||||||
*/
|
|
||||||
-public class ForbiddenClassException extends XStreamException {
|
|
||||||
+public class ForbiddenClassException extends AbstractSecurityException {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a ForbiddenClassException.
|
|
||||||
diff --git a/xstream/src/java/com/thoughtworks/xstream/security/InputManipulationException.java b/xstream/src/java/com/thoughtworks/xstream/security/InputManipulationException.java
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..2d87f660
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/xstream/src/java/com/thoughtworks/xstream/security/InputManipulationException.java
|
|
||||||
@@ -0,0 +1,27 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2021 XStream Committers.
|
|
||||||
+ * All rights reserved.
|
|
||||||
+ *
|
|
||||||
+ * Created on 21. September 2021 by Joerg Schaible
|
|
||||||
+ */
|
|
||||||
+package com.thoughtworks.xstream.security;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * Class for a Security Exception assuming input manipulation in XStream.
|
|
||||||
+ *
|
|
||||||
+ * @author Jörg Schaible
|
|
||||||
+ * @since upcoming
|
|
||||||
+ */
|
|
||||||
+public class InputManipulationException extends AbstractSecurityException {
|
|
||||||
+ private static final long serialVersionUID = 20210921L;
|
|
||||||
+
|
|
||||||
+ /**
|
|
||||||
+ * Constructs a SecurityException.
|
|
||||||
+ * @param message the exception message
|
|
||||||
+ * @since upcoming
|
|
||||||
+ */
|
|
||||||
+ public InputManipulationException(final String message) {
|
|
||||||
+ super(message);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
||||||
index 09b96a8d..167939d7 100644
|
|
||||||
--- a/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
||||||
+++ b/xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java
|
|
||||||
@@ -17,13 +17,20 @@
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
+import java.util.HashMap;
|
|
||||||
+import java.util.HashSet;
|
|
||||||
+import java.util.Hashtable;
|
|
||||||
import java.util.Iterator;
|
|
||||||
+import java.util.LinkedHashMap;
|
|
||||||
+import java.util.LinkedHashSet;
|
|
||||||
+import java.util.Map;
|
|
||||||
+import java.util.Set;
|
|
||||||
|
|
||||||
-import com.thoughtworks.xstream.XStreamException;
|
|
||||||
import com.thoughtworks.xstream.converters.ConversionException;
|
|
||||||
import com.thoughtworks.xstream.core.JVM;
|
|
||||||
import com.thoughtworks.xstream.security.AnyTypePermission;
|
|
||||||
import com.thoughtworks.xstream.security.ForbiddenClassException;
|
|
||||||
+import com.thoughtworks.xstream.security.InputManipulationException;
|
|
||||||
import com.thoughtworks.xstream.security.ProxyTypePermission;
|
|
||||||
|
|
||||||
|
|
||||||
@@ -56,9 +63,9 @@ public void testCannotInjectEventHandler() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
xstream.fromXML(xml);
|
|
||||||
- fail("Thrown " + XStreamException.class.getName() + " expected");
|
|
||||||
- } catch (final XStreamException e) {
|
|
||||||
- assertTrue(e.getMessage().indexOf(EventHandler.class.getName()) > 0);
|
|
||||||
+ fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
|
|
||||||
+ } catch (final ForbiddenClassException e) {
|
|
||||||
+ // OK
|
|
||||||
}
|
|
||||||
assertEquals(0, BUFFER.length());
|
|
||||||
}
|
|
||||||
@@ -126,7 +133,7 @@ public void exec() {
|
|
||||||
public void testInstanceOfVoid() {
|
|
||||||
try {
|
|
||||||
xstream.fromXML("<void/>");
|
|
||||||
- fail("Thrown " + ConversionException.class.getName() + " expected");
|
|
||||||
+ fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
|
|
||||||
} catch (final ForbiddenClassException e) {
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
@@ -163,7 +170,7 @@ public void testCannotUseJaxwsInputStreamToDeleteFile() {
|
|
||||||
xstream.aliasType("is", InputStream.class);
|
|
||||||
try {
|
|
||||||
xstream.fromXML(xml);
|
|
||||||
- fail("Thrown " + ConversionException.class.getName() + " expected");
|
|
||||||
+ fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
|
|
||||||
} catch (final ForbiddenClassException e) {
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
@@ -261,4 +268,140 @@ public void testExplicitlyUnmarshalEndlessByteArryInputStream() {
|
|
||||||
assertEquals("ArrayIndexOutOfBoundsException expected reading invalid stream", 5, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ public void testDoSAttackWithHashSet() {
|
|
||||||
+ final Set set = new HashSet();
|
|
||||||
+ Set s1 = set;
|
|
||||||
+ Set s2 = new HashSet();
|
|
||||||
+ for (int i = 0; i < 30; i++) {
|
|
||||||
+ final Set t1 = new HashSet();
|
|
||||||
+ final Set t2 = new HashSet();
|
|
||||||
+ t1.add("a");
|
|
||||||
+ t2.add("b");
|
|
||||||
+ s1.add(t1);
|
|
||||||
+ s1.add(t2);
|
|
||||||
+ s2.add(t2);
|
|
||||||
+ s2.add(t1);
|
|
||||||
+ s1 = t1;
|
|
||||||
+ s2 = t2;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ xstream.setCollectionUpdateLimit(5);
|
|
||||||
+ final String xml = xstream.toXML(set);
|
|
||||||
+ try {
|
|
||||||
+
|
|
||||||
+ xstream.fromXML(xml);
|
|
||||||
+ fail("Thrown " + InputManipulationException.class.getName() + " expected");
|
|
||||||
+ } catch (final InputManipulationException e) {
|
|
||||||
+ assertTrue("Limit expected in message", e.getMessage().contains("exceeds 5 seconds"));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public void testDoSAttackWithLinkedHashSet() {
|
|
||||||
+ final Set set = new LinkedHashSet();
|
|
||||||
+ Set s1 = set;
|
|
||||||
+ Set s2 = new LinkedHashSet();
|
|
||||||
+ for (int i = 0; i < 30; i++) {
|
|
||||||
+ final Set t1 = new LinkedHashSet();
|
|
||||||
+ final Set t2 = new LinkedHashSet();
|
|
||||||
+ t1.add("a");
|
|
||||||
+ t2.add("b");
|
|
||||||
+ s1.add(t1);
|
|
||||||
+ s1.add(t2);
|
|
||||||
+ s2.add(t2);
|
|
||||||
+ s2.add(t1);
|
|
||||||
+ s1 = t1;
|
|
||||||
+ s2 = t2;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ xstream.setCollectionUpdateLimit(5);
|
|
||||||
+ final String xml = xstream.toXML(set);
|
|
||||||
+ try {
|
|
||||||
+ xstream.fromXML(xml);
|
|
||||||
+ fail("Thrown " + InputManipulationException.class.getName() + " expected");
|
|
||||||
+ } catch (final InputManipulationException e) {
|
|
||||||
+ assertTrue("Limit expected in message", e.getMessage().contains("exceeds 5 seconds"));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public void testDoSAttackWithHashMap() {
|
|
||||||
+ final Map map = new HashMap();
|
|
||||||
+ Map m1 = map;
|
|
||||||
+ Map m2 = new HashMap();
|
|
||||||
+ for (int i = 0; i < 25; i++) {
|
|
||||||
+ final Map t1 = new HashMap();
|
|
||||||
+ final Map t2 = new HashMap();
|
|
||||||
+ t1.put("a", "b");
|
|
||||||
+ t2.put("c", "d");
|
|
||||||
+ m1.put(t1, t2);
|
|
||||||
+ m1.put(t2, t1);
|
|
||||||
+ m2.put(t2, t1);
|
|
||||||
+ m2.put(t1, t2);
|
|
||||||
+ m1 = t1;
|
|
||||||
+ m2 = t2;
|
|
||||||
+ }
|
|
||||||
+ xstream.setCollectionUpdateLimit(5);
|
|
||||||
+
|
|
||||||
+ final String xml = xstream.toXML(map);
|
|
||||||
+ try {
|
|
||||||
+ xstream.fromXML(xml);
|
|
||||||
+ fail("Thrown " + InputManipulationException.class.getName() + " expected");
|
|
||||||
+ } catch (InputManipulationException e) {
|
|
||||||
+ assertTrue("Limit expected in message", e.getMessage().contains("exceeds 5 seconds"));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public void testDoSAttackWithLinkedHashMap() {
|
|
||||||
+ final Map map = new LinkedHashMap();
|
|
||||||
+ Map m1 = map;
|
|
||||||
+ Map m2 = new LinkedHashMap();
|
|
||||||
+ for (int i = 0; i < 25; i++) {
|
|
||||||
+ final Map t1 = new LinkedHashMap();
|
|
||||||
+ final Map t2 = new LinkedHashMap();
|
|
||||||
+ t1.put("a", "b");
|
|
||||||
+ t2.put("c", "d");
|
|
||||||
+ m1.put(t1, t2);
|
|
||||||
+ m1.put(t2, t1);
|
|
||||||
+ m2.put(t2, t1);
|
|
||||||
+ m2.put(t1, t2);
|
|
||||||
+ m1 = t1;
|
|
||||||
+ m2 = t2;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ xstream.setCollectionUpdateLimit(5);
|
|
||||||
+ final String xml = xstream.toXML(map);
|
|
||||||
+ try {
|
|
||||||
+ xstream.fromXML(xml);
|
|
||||||
+ fail("Thrown " + InputManipulationException.class.getName() + " expected");
|
|
||||||
+ } catch (final InputManipulationException e) {
|
|
||||||
+ assertTrue("Limit expected in message", e.getMessage().contains("exceeds 5 seconds"));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public void testDoSAttackWithHashtable() {
|
|
||||||
+ final Map map = new Hashtable();
|
|
||||||
+ Map m1 = map;
|
|
||||||
+ Map m2 = new Hashtable();
|
|
||||||
+ for (int i = 0; i < 100; i++) {
|
|
||||||
+ final Map t1 = new Hashtable();
|
|
||||||
+ final Map t2 = new Hashtable();
|
|
||||||
+ t1.put("a", "b");
|
|
||||||
+ t2.put("c", "d");
|
|
||||||
+ m1.put(t1, t2);
|
|
||||||
+ m1.put(t2, t1);
|
|
||||||
+ m2.put(t2, t1);
|
|
||||||
+ m2.put(t1, t2);
|
|
||||||
+ m1 = t1;
|
|
||||||
+ m2 = t2;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ xstream.setCollectionUpdateLimit(5);
|
|
||||||
+ final String xml = xstream.toXML(map);
|
|
||||||
+ try {
|
|
||||||
+ xstream.fromXML(xml);
|
|
||||||
+ fail("Thrown " + InputManipulationException.class.getName() + " expected");
|
|
||||||
+ } catch (final InputManipulationException e) {
|
|
||||||
+ assertTrue("Limit expected in message", e.getMessage().contains("exceeds 5 seconds"));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
13
settings.xml
13
settings.xml
@ -1,13 +0,0 @@
|
|||||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
|
|
||||||
http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
|
||||||
<mirrors>
|
|
||||||
<mirror>
|
|
||||||
<id>huaweicloud</id>
|
|
||||||
<mirrorOf>central</mirrorOf>
|
|
||||||
<name>central repo</name>
|
|
||||||
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
|
|
||||||
</mirror>
|
|
||||||
</mirrors>
|
|
||||||
</settings>
|
|
||||||
Binary file not shown.
16
xstream.spec
16
xstream.spec
@ -1,14 +1,12 @@
|
|||||||
%bcond_with jp_minimal
|
%bcond_with jp_minimal
|
||||||
Name: xstream
|
Name: xstream
|
||||||
Version: 1.4.18
|
Version: 1.4.20
|
||||||
Release: 3
|
Release: 1
|
||||||
Summary: Java XML serialization library
|
Summary: Java XML serialization library
|
||||||
License: BSD
|
License: BSD
|
||||||
URL: http://x-stream.github.io/
|
URL: http://x-stream.github.io/
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
Source0: https://repo.maven.apache.org/maven2/com/thoughtworks/xstream/xstream-distribution/%{version}/xstream-distribution-%{version}-src.zip
|
Source0: https://repo.maven.apache.org/maven2/com/thoughtworks/xstream/xstream-distribution/%{version}/xstream-distribution-%{version}-src.zip
|
||||||
Source1: settings.xml
|
|
||||||
Patch0: CVE-2021-43859.patch
|
|
||||||
|
|
||||||
BuildRequires: maven-local mvn(cglib:cglib) mvn(dom4j:dom4j) mvn(javax.xml.bind:jaxb-api)
|
BuildRequires: maven-local mvn(cglib:cglib) mvn(dom4j:dom4j) mvn(javax.xml.bind:jaxb-api)
|
||||||
BuildRequires: mvn(joda-time:joda-time) mvn(net.sf.kxml:kxml2-min)
|
BuildRequires: mvn(joda-time:joda-time) mvn(net.sf.kxml:kxml2-min)
|
||||||
@ -17,7 +15,7 @@ BuildRequires: mvn(org.apache.maven.plugins:maven-enforcer-plugin)
|
|||||||
BuildRequires: mvn(org.codehaus.mojo:build-helper-maven-plugin)
|
BuildRequires: mvn(org.codehaus.mojo:build-helper-maven-plugin)
|
||||||
BuildRequires: mvn(org.codehaus.woodstox:woodstox-core-asl) mvn(org.jdom:jdom)
|
BuildRequires: mvn(org.codehaus.woodstox:woodstox-core-asl) mvn(org.jdom:jdom)
|
||||||
BuildRequires: mvn(org.jdom:jdom2) mvn(stax:stax) mvn(stax:stax-api) mvn(xpp3:xpp3)
|
BuildRequires: mvn(org.jdom:jdom2) mvn(stax:stax) mvn(stax:stax-api) mvn(xpp3:xpp3)
|
||||||
BuildRequires: mvn(xpp3:xpp3_min) maven
|
BuildRequires: mvn(xpp3:xpp3_min) maven mvn(org.codehaus.mojo:build-helper-maven-plugin)
|
||||||
%if %{without jp_minimal}
|
%if %{without jp_minimal}
|
||||||
BuildRequires: mvn(javassist:javassist) mvn(org.codehaus.jettison:jettison)
|
BuildRequires: mvn(javassist:javassist) mvn(org.codehaus.jettison:jettison)
|
||||||
BuildRequires: mvn(org.hibernate:hibernate-core) mvn(org.hibernate:hibernate-envers)
|
BuildRequires: mvn(org.hibernate:hibernate-core) mvn(org.hibernate:hibernate-envers)
|
||||||
@ -69,8 +67,7 @@ Requires: xstream = %{version}-%{release}
|
|||||||
Parent POM for xstream.
|
Parent POM for xstream.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -qn xstream-%{version}
|
%autosetup -n xstream-%{version} -p1
|
||||||
%patch0 -p1
|
|
||||||
|
|
||||||
sed -i "s/3.2.7/4.0.0/g" pom.xml
|
sed -i "s/3.2.7/4.0.0/g" pom.xml
|
||||||
find . -name "*.class" -print -delete
|
find . -name "*.class" -print -delete
|
||||||
@ -109,10 +106,8 @@ rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/
|
|||||||
%mvn_file :xstream xstream/xstream xstream
|
%mvn_file :xstream xstream/xstream xstream
|
||||||
%mvn_file :xstream-benchmark xstream/xstream-benchmark xstream-benchmark
|
%mvn_file :xstream-benchmark xstream/xstream-benchmark xstream-benchmark
|
||||||
%mvn_package :xstream
|
%mvn_package :xstream
|
||||||
cp -a %{_sourcedir}/settings.xml .
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
mvn install --settings ./settings.xml -Dmaven.test.skip=true
|
|
||||||
%mvn_build -f -s -- -Dversion.java.source=8
|
%mvn_build -f -s -- -Dversion.java.source=8
|
||||||
|
|
||||||
%install
|
%install
|
||||||
@ -134,6 +129,9 @@ mvn install --settings ./settings.xml -Dmaven.test.skip=true
|
|||||||
%license LICENSE.txt
|
%license LICENSE.txt
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue Dec 12 2023 yaoxin <yao_xin001@hoperun.com> - 1.4.20-1
|
||||||
|
- Upgrade to 1.4.20 for fix CVE-2022-40151 and CVE-2022-41966
|
||||||
|
|
||||||
* Thu Nov 10 2022 liyanan <liyanan32@h-partners.com> - 1.4.18-3
|
* Thu Nov 10 2022 liyanan <liyanan32@h-partners.com> - 1.4.18-3
|
||||||
- Change source
|
- Change source
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user