Sunday 22 December 2013

XStream "Remote Code Execution" exploit on code from "Standard way to serialize and deserialize Objects with XStream" article

At the DefCon 2013 I co-presented (with Abraham and Alvaro) the "RESTing On Your Laurels will Get YOu Pwned", which showed a number of PoCs on how REST interfaces and APIs can create a number a security vulnerabilities:

Since that time, I have blogged about a couple of the demos created:
We also showed a PoC using the XStream API (which had been reported to the XStream developers) which so far has not made it into a blog post (the PoCs presented at DecCon are here and here).

Since a quick search for 'XStream Vulnerabilities' only shows a couple examples (Spring Source OXM Remote OS Command Injection when XStream and IBM JRE are used, JAVA RESTful Services | Fuzzing Down the Rabbit Hole: Part One  and this git commit), I think it is fair to say that this is issue is still quite unknown.
A good example of how the dangers of XStream are not fully understood is the Standard way to serialize and deserialize Objects with XStream:

This blog post shows a "...standard way of using XStream in profeessional projects to generate XML or JSON or Objects..." which unfortunately will make any application that uses that API vulnerable to (amongst other things) remote code execution.

As soon as I saw that article, I thought "humm... this looks vulnerable to the XStream code execution vuln we showed at DefCon" and since it was a slow Saturday here in London, I had a bit of time to create a PoC to confirm my assumption :)

After replicating the XMLGenerator API proposed on the Standard way to serialize and deserialize Objects with XStream article (see full workflow I took below), I was able to pop a Calculator on my OSx test box using this script (gist here):

... which when executed,  first opened the /Application/ and then failed (the XMLGeneration/Stream step) with this cast exception:

Note: we can also use this OSx open command to:

... open the current folder (with an argument of ".")

 ... open a particular webpage (with an argument of ""):

Bottom Line: Be very careful when using XStream

In addition to this remote command execution PoC, XStream allows the creation of server side objects based on reflection (which means that you could have all sorts of business-logic sensitive objects being created). 

Note: As the XStreamMarshaller quote shown at the end of this post shows, It looks like there is an official way to limit which objects XStream will create, but I'm not sure on the best practices (please comment below if you know more about how to 'securely use XStream')

So how is this possible?

Basically (the way I see it), XStream is an 'reflection-based XML-to-Object conversion'.

Where XStream takes the XML provided and tries to create Java objects based on it.

Basically XStream is able to take an XML that represents and object and make it into an nice POJO (which is a great feature and I can see why developers really like it).

The objective of the article in question is to create an API that makes this even simpler:

... which can then be used like this:

To see this in see this in action, let's fire up an new Eclipse project and follow these 23 steps:

1) create a new Java Project

2) call it (for example) XStreamPoC

 3) Add a folder called lib

4) Copy to that folder the xstream-1.4.6.jar file that can be downloaded from here:

5) Add the xstream-1.4.6.jar jar to the Build Path of the current project

6) In your browser, open the Standard way to serialize and deserialize Objects with XStream page, copy the contents of the file (in the middle of the page), (back in Eclipse) select the src folder and select (or type) Paste

7) Note how that Paste created a new Java file with the contents of the clipboard (which is a pretty cool Eclipse feature :) )

8) Go back to the Standard way to serialize and deserialize Objects with XStream page, and do the same thing for the and files

Note: at this stage there should be no compilation errors in the current Eclipse project

9) Next add a new class

10) ... called XStreamPoC (note tick the public static void main(String[] args) checkbox before clicking on Finish)

11) on the Main method add a simple test System.out.Println command and run the project as a Java Application

12) Which should look like this:

13) Now it is time to use the XmlGenerator usage samples from the  Standard way to serialize and deserialize Objects with XStream page:

14) Which when executed should look like this

Note: in the image above we can see the type of 'clean' XML that XStream expects to consume.

15) Next lets remove the serialisation part and just look at the process of converting XML strings into Objects.

In the image below you can see both cases (using the XmlGenerator.generatorToFromXML and the respective XStream code)

16) What is interesting/dangerous about the XStream API, is that it will create the object as defined in the XML file. Note how in the example below, the Java string is created first, and then attempted to be casted into the Square class

17) we can confirm that the Java string is indeed being created ok, if we remove the case to Square and treat the sq1 variable as a Object

18) Here we create a Java string based on its full signature:

19) Which means that we can create any object that is currently loaded in the class path (and we can create the required objects to invoke its constructor).

The next example shows how to create an instance of the InitializationException class:

20) And this one how to create a java.lang.ProcessBuilder object

21) Note that the cast error (using the original code) will occur after the ProcessBuilder object is created

22) At the moment we still have a problem that we are only creating objects, not invoking them. That is where the dynamic-proxy + EventHandle technique comes into play.

First lets see how to invoke a method (in this case the start from the ProcessBuilder object) using a variation of a code sample from Alvaro's thread with the XStream developers:

Note: The cast exception happens when the TreeSet Comparable invokes the EventHandler (which returns the execution result of the start method)

23) the final step is to convert the TreeSort code shown above into XML seen below (I used the XMLGenerator.generateXML to help in the creation of the final payload (which is a variation of the payload we showed at DefCon)):

Note: here are XML examples of the inputs supported by the multiple XStream converters

Conclusion: Be very careful when using XStream and don't feed it XML retrieved from untrusted sources

Hopefully this post shows how dangerous it is to create APIs like the XMLGenerator one. 

What Srinivas Dasari article also shows, is that unless these type of dangers are clearly mapped,  identified exposed and visualised, it is just about impossible for developers (like Srinivas) to understand the dangers of the APIs they are are consuming. 

Appendix A) Source code

All code samples shown in this post are on this gist

Appendix B) XStream in the Spring Framwork.

The original PoC Alvaro created for XStream used the Spring Framework XStreamMarshaller which provides this guidance at the end of this doc: