Security / November 16, 2017

Exploiting Apache Struts: A Case Study in Writing Better Detections


In researching available detection logic for three well-known Apache Struts vulnerabilities (CVE-2017-5638CVE-2017-9791CVE-2017-9805), the Gigamon Applied Threat Research (ATR) team discovered that most publicly available detections for these vulnerabilities failed to identify or prevent successful attacks in the wild.

Publicly available detection logic focused on implementation details (keywords, paths, network indicators) from available exploits, but not details specific to the vulnerability. These implementation-specific details are easily modified by exploit authors to avoid detection. This case study demonstrates how an understanding of the underlying vulnerability as well as exploitation techniques can be combined and applied to create more robust detections.


CVE-2017-9805 is a Java XStream deserialization vulnerability in the Apache Struts REST plugin, affecting Struts versions 2.1.2 to 2.3.34, and 2.5.x to 2.5.13. Java deserialization vulnerabilities occur when Java applications deserialize user-supplied data without sanitization. Successful exploitation of CVE-2017-9805 can grant the attacker remote code execution (RCE) ability on the vulnerable server.

Java deserialization exploits typically use “Property-Oriented Programming” (POP) chains, wherein the exploit passes a sequence of forged serialized class instances, with modified properties, to the vulnerable deserialization method. To learn more about Java deserialization vulnerabilities, see this post.

POP chains generally require multiple gadgets from the following categories:

  • Trigger (or Pivot) Gadget
    • A class with a “magic method” triggered during deserialization, acting upon proxy-able fields, which are attacker controlled and serializable. Trigger Gadgets initiate the execution.
  • Bypass Gadget
    • A class with (preferably) a “magic method” triggered during deserialization which leads to a “nested deserialization” with an unprotected ‘ObjectInputStream’ of attacker-controllable bytes.
  • Helper Gadget
    • A class which glues together other portions of a gadget chain.
  • Abuse Gadget (sinks)
    • A class with a method implementing dangerous functionality that attackers want to execute.

The vulnerability resides within the ‘XStreamHandler’ class, which passes user-supplied data to the ‘toObject’ method. ‘toObject’ does not properly perform input sanitization prior to running the deserialization method ‘xstream.fromXML’.

Submitting an HTTP POST request with an XML-encoded payload to any path that allows HTTP POST and accepts the ‘application/xml’ MIME type will trigger the vulnerability. Furthermore, since ‘XStreamHandler’ can deserialize non-serializable classes, exploit authors have diverse and abundant options for POP gadgets.

Exploit Detection

Most public CVE-2017-9805 detection logic targets implementation specific details that are not required in actual attacks and ignores core vulnerability details and common Java exploitation techniques:

  • Most only detect attacks using the path chosen in the CVE-2017-9805 Metasploit module
  • Some attempt to identify Abuse Gadgets
  • Some attempt to identify ysoserial base64 encoded payload started using ‘TemplatesImpl’
    • Attackers can use the ‘TemplatesImpl’ gadget to define and initialize a class from bytecode by calling an arbitrary constructor or an unmarshaller calling ‘readobject()’. XStream stores bytecode in base64 encoded form

These detections are great first steps that can quickly catch attacks using public PoCs, especially those that immediately followed vulnerability disclosure. However, due to their shortcomings, they are at risk of missing future attacks. For example, if a vulnerable web application exposes a path other than the one targeted by Metasploit, most signatures would not fire. Additionally, any gadgets that attempt to hide their malicious payload, using, for example, remote classloading or JNDI reference indirection, would evade those detections.

With a deeper understanding of CVE-2017-9805 and Java exploitation, detection authors can specifically consider:

  • The payload must be formatted in XML
  • The server must accept POST requests with ‘application/xml’ data at the given HTTP path, but the path does not otherwise matter (e.g., “/struts2-rest-showcase/orders/3” is not necessary)
  • Attackers can utilize multiple gadgets according to commonly used libraries(com.sun, java.lang, etc.) as well as the source code of the targeted application itself
  • Attackers can execute commands using several types of abuse gadget:
    • Local system command execution
      • Use methods such as java.lang.ProcessBuilder to achieve arbitrary code execution
    • Remote classloading
      • Use URLClassLoader to load class bytecode from an attacker provided URL, then initialize the class to gain arbitrary code execution
    • JNDI reference indirection
      • Construct a URLClassLoader utilizing attacker-supplied code and load/initialize the specified object factory class through it, leading to arbitrary code execution
    • Local classloading
      • Define and initialize a class from bytecode, achieve code execution by calling an arbitrary constructor or an unmarshaller calling readobject()

In addition, researchers can consider several common POP gadgets when authoring detections. In an ideal scenario, researchers would know all possible gadgets used for the exploit. However, since this vulnerability can use custom gadgets, consider using strict and loose criteria to cover both common and custom gadgets. The following class paths, extracted from payloads primarily generated by this tool, are good starting points:

Strict Criteria (Common Gadget Class Paths for Xstream):

  • org.springframework.aop.aspectj.autoproxy
  • com.rometools.rome.feed.impl.
  • org.apache.xbean.naming.context.
  • javax.naming.spi.ContinuationDirContext
  • org.apache.commons.configuration.
  • sun.misc.Service$LazyIterator
  • com.sun.jndi.toolkit.dir.LazySearch
  • com.sun.jndi.rmi.registry.Binding
  • javax.imageio.spi.FilterIterator
  • org.apache.commons.beanutils.
  • org.codehaus.groovy.runtime.MethodClosure
  • java.beans.EventHandler

Loose Criteria (Abuse Gadget Class Paths):

  • JNDI:
    • com.sun.rowset.JdbcRowSetImpl
    • com.sun.jndi.ldap.LdapAttribute
  • Remote classloading(plain):
    • javax.naming.Reference
    • com.sun.jndi.rmi.registry.
  • Remote classloading(serviceloader):
    • javax.script.ScriptEngineFactory
  • System command execution:
    • java.lang.ProcessBuilder
    • java.lang.Runtime.exec
  • Local classloading:
      .xsltc.trax.TemplatesImpl (as seen here)


While we can’t expect perfect detection coverage, we can dramatically increase the effectiveness of detection methods through vulnerability research, and an understanding of attacker exploitation techniques. By blending these two perspectives, we can move beyond detecting singular instances of an attack to the reliable detection of an entire attack class. The Gigamon ATR team is continually iterating on this research and delivering more robust threat detection capabilities for our customers.

Gigamon Insight is a network security analytics solution that offers a SaaS capability that enables customers to gain and utilize widespread network visibility for security operations. As part of its research, the Gigamon ATR team coordinates disclosure of security threats and vulnerabilities with relevant parties in order to maximize both the response and victim remediation efforts as well as working to truly improve the security of customers and other victims prior to publishing blog posts. To learn more about the Gigamon ATR team, please visit

This article was written by ATR team members Chenming Xu, Justin Warner, Stephen Hink, and Dan Caselden.

Back to top