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

    Filter/Servlet型內存馬的掃描抓捕與查殺

    一顆小胡椒2022-05-19 22:38:22

    0x01 背景

    在內存馬橫行的當下,藍隊or應急的師傅如何能快速判斷哪些Filter/Servlet是內存馬,分析內存馬的行為功能是什么?最終又如何不重啟的將其清除?紅隊師傅又如何抓鋪其他師傅的內存馬為自己用,亦或是把師傅的內存馬踢掉?

    在當下攻防對抗中,一直缺少著針對內存馬掃描,捕捉與查殺的輔助腳本。下面就以Tomcat 8.5.47為例子,分享下編寫方法,其他中間件萬變不離其宗。

    考慮到Agent技術針對紅隊來說比較重,我們這次使用jsp技術來解決以上問題。

    0x02 掃描Filter和Servlet

    要想掃描web應用內存中的Filter和Servlet,我們必須知道它們存儲的位置。通過查看代碼,我們知道StandardContext對象中維護的是一個

    和Filter相關的是filterDefs和filterMaps兩個屬性。這兩個屬性分別維護著全局Filter的定義,以及Filter的映射關系。

    和Servlet相關的是children和servletMappings兩個屬性。這兩個屬性分別維護這全家Servlet的定義,以及Servlet的映射關系。

    其他request對象中就存儲這StandardContext對象。


    request.getSession().getServletContext() {ApplicationContextFacade}  -> context {ApplicationContext}     -> context {StandardContext}      * filterDefs      * filterMaps      * children      * servletMappings
    

    所以我們只需要通過反射遍歷request,最終就可以拿到Filter和Servlet的如下信息。


    Filter/Servlet名匹配路徑Class名ClassLoaderClass文件存儲路徑。內存中Class字節碼(方便反編譯審計其是否存在惡意代碼)該Class是否有對應的磁盤文件(判斷內存馬的重要指標)
    

    具體反射遍歷代碼放文末github,這里值得一提是拿到Class名通過如下方法就能拿到其被加載到內存中的字節碼內容。


    byte[] classBytes = Repository.lookupClass(Class.forName("me.gv7.Memshell")).getBytes();
    

    0x03 注銷Filter內存馬

    通過分析調試Tomcat源碼,我們知道Tomcat注銷filter其實就是將該Filter從全局filterDefs和filterMaps中清除掉。具體的操作分別如下removeFilterDef和removeFilterMap兩個方法中。


    //org.apache.catalina.core.StandardContext#removeFilterDefpublic void removeFilterDef(FilterDef filterDef) {    synchronized(this.filterDefs) {        this.filterDefs.remove(filterDef.getFilterName());    }    this.fireContainerEvent("removeFilterDef", filterDef);}
    //org.apache.catalina.core.StandardContext#removeFilterMappublic void removeFilterMap(FilterMap filterMap) {    this.filterMaps.remove(filterMap);    this.fireContainerEvent("removeFilterMap", filterMap);}
    

    我們只需要反射調用它們即可注銷Filter。


    public synchronized void deleteFilter(HttpServletRequest request,String filterName) throws Exception{    Object standardContext = getStandardContext(request);
        // org.apache.catalina.core.StandardContext#removeFilterDef    HashMap filterConfig = getFilterConfig(request);    Object appFilterConfig = filterConfig.get(filterName);    Field _filterDef = appFilterConfig.getClass().getDeclaredField("filterDef");    _filterDef.setAccessible(true);    Object filterDef = _filterDef.get(appFilterConfig);    Method removeFilterDef = standardContext.getClass().getDeclaredMethod("removeFilterDef", new Class[]{org.apache.tomcat.util.descriptor.web.FilterDef.class});    removeFilterDef.setAccessible(true);    removeFilterDef.invoke(standardContext,filterDef);
        // org.apache.catalina.core.StandardContext#removeFilterMap    Object[] filterMaps = getFilterMaps(request);    for(Object filterMap:filterMaps){        Field _filterName = filterMap.getClass().getDeclaredField("filterName");        _filterName.setAccessible(true);        String filterName0 = (String)_filterName.get(filterMap);        if(filterName0.equals(filterName)){            Method removeFilterMap = standardContext.getClass().getDeclaredMethod("removeFilterMap", new Class[]{org.apache.catalina.deploy.FilterMap.class});            removeFilterDef.setAccessible(true);            removeFilterMap.invoke(standardContext,filterMap);        }    }}
    

    0x04 注銷Servlet內存馬

    注銷Servlet的原理也是類似,將該Servlet從全局servletMappings和children中清除掉即可。在Tomcat源碼中對應的是removeServletMapping和removeChild方法。


    //org.apache.catalina.core.StandardContext#removeServletMappingpublic void removeServletMapping(String pattern) {    String name = null;    synchronized(this.servletMappingsLock) {        name = (String)this.servletMappings.remove(pattern);    }
        Wrapper wrapper = (Wrapper)this.findChild(name);    if (wrapper != null) {        wrapper.removeMapping(pattern);    }
        this.fireContainerEvent("removeServletMapping", pattern);}
    //org.apache.catalina.core.StandardContext#removeChildpublic void removeChild(Container child) {    if (!(child instanceof Wrapper)) {        throw new IllegalArgumentException(sm.getString("standardContext.notWrapper"));    } else {        super.removeChild(child);    }}
    

    我們只需要反射調用它們即可注銷Servlet。


    public synchronized void deleteServlet(HttpServletRequest request,String servletName) throws Exception{    HashMap childs = getChildren(request);    Object objChild = childs.get(servletName);    String urlPattern = null;    HashMap servletMaps = getServletMaps(request);    for(Map.Entry servletMap:servletMaps.entrySet()){        if(servletMap.getValue().equals(servletName)){            urlPattern = servletMap.getKey();            break;        }    }
        if(urlPattern != null) {        // 反射調用 org.apache.catalina.core.StandardContext#removeServletMapping        Object standardContext = getStandardContext(request);        Method removeServletMapping = standardContext.getClass().getDeclaredMethod("removeServletMapping", new Class[]{String.class});        removeServletMapping.setAccessible(true);        removeServletMapping.invoke(standardContext, urlPattern);        // Tomcat 6必須removeChild 789可以不用        // 反射調用 org.apache.catalina.core.StandardContext#removeChild        Method removeChild = standardContext.getClass().getDeclaredMethod("removeChild", new Class[]{org.apache.catalina.Container.class});        removeChild.setAccessible(true);        removeChild.invoke(standardContext, objChild);    }}
    

    0x05 演示

    我們只需要把編寫好的tomcat-memshell-scanner.jsp放到可能被注入內存的web項目中,然后通過瀏覽器訪問即可。假設掃描結果如下:

    通過分析掃描出的信息,可知filter-b2b1cad2-44be-4f43-8db0-bd43da5ad368是Filter型內存馬,原因如下:

    1. classLoader是可疑的com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$TransletClassLoader,這是反序列化漏洞執行代碼用的classLoader。

    2. class在磁盤中沒有對應的class文件,只駐留在內存。

    /favicon.ico是Servlet型內存馬,判斷原因如下。

    1. classLoader是自定義classLoader,當下比較流行的java webshell基本都是自定義了class loader來實現任意代碼執行。

    2. class在磁盤中沒有對應的class文件,只駐留在內存。

    最后我們可以dump出那么對應的class,反編譯看代碼分析filter-b2b1cad2-44be-4f43-8db0-bd43da5ad368是Filter型cmd內存馬,/favicon.ico是Servlet型哥斯拉內存馬。

    原文鏈接:https://gv7.me/articles/2020/filter-servlet-type-memshell-scan-capture-and-kill/
    
    servlet
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    0x01 背景 在內存馬橫行的當下,藍隊or應急的師傅如何能快速判斷哪些Filter/Servlet是內存馬,分析內存馬的行為功能是什么?考慮到Agent技術針對紅隊來說比較重,我們這次使用jsp技術來解決以上問題。
    filter是javaweb中的過濾器,會對客戶端發送的請求進行過濾并做一些操作,我們可以在filter中寫入命令執行的惡意文件,讓客戶端發來的請求通過它來做命令執行。 而filter內存馬是通過動態注冊一個惡意filter,由于是動態注冊的,所以這個filter沒有文件實體,存在于內存中,隨著tomcat重啟而消失。 一般我們把這個filter放在所有filter最前面優先執行,這樣我們的請
    Eclipse Jetty是一個Java Web 服務器和Java Servlet容器。雖然 Web 服務器通常與向人們提供文檔相關聯,但 Jetty 現在通常用于機器對機器的通信,通常在更大的軟件框架內。Jetty 是作為Eclipse Foundation的一部分開發的免費和開源項目。Web 服務器用于Apache ActiveMQ、Alfresco、Scalatra、Apache Geron
    CVE-2022-2143 Advantech iView NetworkServlet 命令注入RCE
    Resin存在類似iis6.0的文件解析漏洞,影響全部版本,不僅能夠豐富其他高危漏洞挖掘知識庫,也給隱藏后門帶來了新的一種潛在方式。
    用友 U8 OA test.jsp SQL注入漏洞。用友 GRP-U8 UploadFileData 任意文件上傳漏洞。用友ERP-NC 目錄遍歷漏洞。用友 U8 OA getSessionList.jsp 敏感信息泄漏漏洞
    拿來即用的Tomcat7/8/9/10版本Listener/Filter/Servlet內存馬,支持注入CMD內存馬和冰蝎內存馬。
    拿來即用的Tomcat7/8/9/10版本Listener/Filter/Servlet內存馬,支持注入CMD內存馬和冰蝎內存馬。
    拿來即用的Tomcat7/8/9/10版本Listener/Filter/Servlet內存馬,支持注入CMD內存馬和冰蝎內存馬。
    開箱即用的內存馬
    2022-08-04 07:00:15
    拿來即用的Tomcat7/8/9/10版本Listener/Filter/Servlet內存馬,支持注入CMD內存馬和冰蝎內存馬。
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类