vlambda博客
学习文章列表

想不到!Spring MVC 拦截器也有漏洞。。

1 基础拦截器和调用流程的探索

学习、探索和实现过程很多都基于大佬的文章:

https://landgrey.me/blog/19/

https://landgrey.me/blog/12/

1.1 基础拦截器

前不久实现cotroller内存马能添加冰蝎代码后,又想到spring mvc的拦截器应该也可以用于注入内存马,目前的关键点在于找到拦截器是如何被触发以及如何动态添加拦截器

首先来写个正常的拦截器TestInterceptor类,并添加xml配置

想不到!Spring MVC 拦截器也有漏洞。。
想不到!Spring MVC 拦截器也有漏洞。。

然后启动程序,在访问/home/index,并添加code参数弹个计算器

想不到!Spring MVC 拦截器也有漏洞。。

1.2 探索拦截器的调用链

断点打在TestInterceptor类中,调试看看调用链

preHandle:31, TestInterceptor (bitterz.interceptors)
applyPreHandle:134, HandlerExecutionChain (org.springframework.web.servlet)
doDispatch:956, DispatcherServlet (org.springframework.web.servlet)
doService:895, DispatcherServlet (org.springframework.web.servlet)
processRequest:967, FrameworkServlet (org.springframework.web.servlet)
doGet:858, FrameworkServlet (org.springframework.web.servlet)
service:621, HttpServlet (javax.servlet.http)
service:843, FrameworkServlet (org.springframework.web.servlet)
service:728, HttpServlet (javax.servlet.http)
internalDoFilter:305, ApplicationFilterChain (org.apache.catalina.core)
doFilter:210, ApplicationFilterChain (org.apache.catalina.core)
invoke:222, StandardWrapperValve (org.apache.catalina.core)
invoke:123, StandardContextValve (org.apache.catalina.core)
invoke:472, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:171, StandardHostValve (org.apache.catalina.core)
invoke:99, ErrorReportValve (org.apache.catalina.valves)
invoke:947, AccessLogValve (org.apache.catalina.valves)
invoke:118, StandardEngineValve (org.apache.catalina.core)
service:408, CoyoteAdapter (org.apache.catalina.connector)
process:1009, AbstractHttp11Processor (org.apache.coyote.http11)
process:589, AbstractProtocol$AbstractConnectionHandler (org.apache.coyote)
run:312, JIoEndpoint$SocketProcessor (org.apache.tomcat.util.net)
runWorker:1142, ThreadPoolExecutor (java.util.concurrent)
run:617, ThreadPoolExecutor$Worker (java.util.concurrent)
run:745, Thread (java.lang)

推荐一个 Spring Boot 基础教程及实战示例:
https://github.com/javastacks/spring-boot-best-practice

关键点在doDispatch方法,先通过getHandler方法获取了mappedHandler对象

想不到!Spring MVC 拦截器也有漏洞。。

在后方调用mappedHandler的applyPreHandler方法

想不到!Spring MVC 拦截器也有漏洞。。

这个方法中就是依次调用每个interceptor实例的preHandle方法,实际上就进入了前面写好的TestInterceptor类的preHandle方法中。

想不到!Spring MVC 拦截器也有漏洞。。

1.3 探索拦截器是如何被添加的

跟踪mappedHandler的获取过程,先是调用了org.springframework.web.servlet.DispatcherServlet中的getHandler方法

想不到!Spring MVC 拦截器也有漏洞。。

跟进getHandler方法,这里会遍历this.handlerMappings,获取HandlerMapping的实例,再调用getHandler方法

想不到!Spring MVC 拦截器也有漏洞。。

这里断点跟进getHandler函数处,会发现实际上调用了org.springframework.web.servlet.handler.AbstractHandlerMapping类中的getHandler方法。最新面试题整理好了,点击小程序在线刷题。

想不到!Spring MVC 拦截器也有漏洞。。

再跟进getHandlerExecutionChain方法,发现其中会遍历adaptedInterceptors这数组,并判断获取的interceptor实例是不是MappedInterceptor类的实例对象,而MappedInterceptor类就是对拦截器HandlerInterceptor接口的实现,所以前面定义的TestInterceptor自然会被加入chain中并返回

想不到!Spring MVC 拦截器也有漏洞。。

至此,拦截器的加载和调用流程就清楚了, 动态添加拦截器的话,只需要在org.springframework.web.servlet.handler.AbstractHandlerMapping类的实例对象的adaptedInterceptors数组中添加恶意interceptor实例对象即可!

那么关键就在于找到org.springframework.web.servlet.handler.AbstractHandlerMapping类的实例对象,CTRL+ALT+B找到所有AbstractHandlerMapping的子类,并在beanFactory的beanDefinitionNames中找到它的实例org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

想不到!Spring MVC 拦截器也有漏洞。。

因此可以通过context.getBean("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping")获取该对象,再反射获取其中的adaptedInterceptors属性,并添加恶意interceptor实例对象即可完成内存马的注入。

2 实践

 
 

 
 

想不到!Spring MVC 拦截器也有漏洞。。
想不到!Spring MVC 拦截器也有漏洞。。

可见Interceptor内存马已经注入了,现在弹个计算器验证一下

想不到!Spring MVC 拦截器也有漏洞。。

想不到!Spring MVC 拦截器也有漏洞。。









。。






关注Java技术栈看更多干货



想不到!Spring MVC 拦截器也有漏洞。。
获取 Spring Boot 实战笔记!