Struts' dynamic method invocation is off by default, and that is not the same as gone

CVE-2016-3081 was published in April 2016 and reached CISA's Known Exploited Vulnerabilities catalog on 8 October 2026. NVD scores it 8.1 with the vector AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H. The vulnerability allows remote attackers to execute arbitrary code through a method: prefix in a chained expression when Dynamic Method Invocation is enabled in Apache Struts 2.3.19 through 2.3.20.2, 2.3.21 through 2.3.24.1, and 2.3.25 through 2.3.28.

The precondition is the whole story

DMI is a configuration flag. When it is enabled, a request parameter can name the method Struts invokes on an action, and the OGNL expression language used to resolve that name can be coaxed into executing code. When DMI is disabled, the same application does not expose this path.
That distinction is why the score carries AC:H. Exploitation is not a matter of sending a request to any Struts deployment. It requires a deployment where someone turned DMI on, usually years ago, usually because a legacy page relied on it, and usually with no record of the decision.
The catalog listing tells you that someone, somewhere, found such a deployment and used it. It does not tell you that every Struts 2.3.x server is exploitable.

Finding the flag in a real estate

Configuration files accumulate. A struts.xml in an old WAR, a properties file inside a shared library, a WAR that was rebuilt from a branch nobody tracks. Grepping for struts.enable.DynamicMethodInvocation across source repositories finds the intentional settings. It does not find the deployed artefacts that were built before the setting existed.
The reliable inventory is at runtime: enumerate the deployed web applications, extract each Struts core JAR version, and determine whether DMI is active in that application's configuration chain. Where you cannot establish the setting, treat the deployment as unknown rather than safe. An unknown flag on a framework with three decades of remote code execution history is a risk statement, not an absence of evidence.

What a successful exploit looks like

The attacker sends a request that resolves a method name containing an OGNL expression. The expression runs in the JVM with the privileges of the application server. From there the outcomes are conventional: command execution as the service account, reading of configuration and connection strings, and outbound connections to attacker infrastructure.
Because the request looks like an ordinary parameter to a web tier, signature-based detection on payload strings has a short half-life. Struts payloads have been obfuscated in public exploits for years, and the OGNL grammar offers many equivalent spellings.
The durable detection is behavioural. A Java process that spawns
sh, cmd.exe, or powershell is anomalous in most application servers. So is an outbound connection from an application host to a host that no application policy authorises. Both are worth alerting on regardless of the framework.

Remediation order

Upgrade Struts. The affected range ends at 2.3.28 and the fix has been available for a decade. A deployment still on 2.3.x has an upgrade project rather than a patch, and that project is the correct response.
If the upgrade cannot happen this quarter, disable DMI explicitly and confirm the setting is effective in the running application. Then test the pages that relied on it, because the feature was probably enabled for a reason.
Finally, review the application host for evidence of past exploitation. Web server logs older than your retention window are gone, so focus on what persists: unexpected files in the application deployment directory, new scheduled tasks, and any change to the JVM's startup arguments.

The pattern behind the catalog entry

Three entries added on the same day in October 2026 cover 2015, 2016 and 2021. That clustering is not a coincidence in the exploit economy. It reflects a scanning model that finds old framework versions on the internet, tests a known payload, and monetises whatever answers.
CVE-2016-3081 is a reminder that "off by default" describes the vendor's default and nothing about the deployment you inherited. The setting lives in a file, the file lives in an artefact, and the artefact is running somewhere.

References

  • NIST NVD record for CVE-2016-3081, https://nvd.nist.gov/vuln/detail/CVE-2016-3081

  • CISA Known Exploited Vulnerabilities catalog entry, https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2016-3081

  • Apache Struts project security information, https://struts.apache.org/security/