[备份]JFinal框架内存马实现

0x01 介绍

看了师傅们的TomcatSpringMVC内存马思路

于是我尝试找了个国产框架分析,经过不少的坑,成功造出了内存马

核心原理类似FilterTomcat内存马,不过又有较大的区别

在成功分析内存马的时候,有了进一步的思考,也许一些思路可以用于Tomcat内存马的进阶免杀

框架名称是JFinal,在国内Java开发圈子中名气不错,应用范围不如Spring不过也不算冷门

github地址为:https://github.com/jfinal/jfinal

目前该项目有3.1K的Star

 

0x02 源码浅析

该框架有点类似SpringMVC,基于Tomcat,路由控制也叫做Controller

添加路由需要编写一个类继承自JFinalConfig类,重写configRoute方法,按照如下的方式添加

web.xml中需要配置一个核心Filter,其中初始化参数为上文的配置类

这个核心Filter代码如下,删减了无用的部分

源码大致看到这里就可以了,其中的一些坑将在后文分析

 

0x03 思路分析

Jfinal不如SpringMVC完善,导致了一些困难

例如它没有SpringContext,也没有各种register*接口供用户动态注册

添加内存马的思路很简单,想办法注册一个路由,映射到恶意的代码造成RCE

所以首先需要分析框架如何处理请求的

所有的映射关系都保存在这样的一个类中

ActionHandler类中处理请求,该类比较复杂

其实看完ActionHandler方法后大概有思路了,构造一个新的映射关系,替换全局变量actionMapping

然而不现实,因为该变量是非静态的,无法反射获取,无法做到直接获取JVM中的对象

所以只能走init方法,寻找构造ActionHandler类的地方,分析传入的ActionMapping参数是否可控

JFinal类找到唯一的一处调用init方法代码

不过有了新的问题:JFinal类的Handler属性和actionMapping都不可以反射设置

先静心继续分析,总会有突破口

注意到handler的一处对外方法getHandler

寻找调用点,在JfinalFilterinit方法中被调用

init方法被初始化ActionHandler后,在doFilter方法中调用

看到handler.handle方法,大概有了新思路

只要可以操作JFinalFilterActionHandler属性,设置其中的ActionMapping为添加了恶意的映射,在doFilter方法中调用handle方法,使请求可以匹配到恶意Controller进而实现内存马

不过JFinalFilterActionHandler非静态属性是不可以反射设置的

唯一设置的地方在这里:jfinal.getHandler();

这个jfinal是什么东西?

这是一个静态JFinal类变量,虽然反射设置final属性比较麻烦,但可以设置了,找到突破点!

结合以上的思路,构造出一个恶意的JFinal类,设置对应的属性,反射调用initHandler方法得到目标ActionHandler

然后设置JFinalFilterJFinal属性为构造的恶意类,这时候触发JFinalFilterinit方法即可实现添加路由

新的问题出现,无法设置JVM中的JFinalFilter对象的属性,只能设置新对象的属性

于是想到一个巧妙的手法:

  1. 利用c0ny1师傅写的Tomcat删除Filter代码,删除目前的JFinalFilter
  2. 添加反射构造的恶意JFinalFilter,甚至不需要手动触发init方法即可实现内存马

又有一个新的问题,目前运行环境已有了的路由会和新的冲突

例如已有/hello如果重新注册Filter会再次加载配置文件,处理其中的/hello会报错

我们新增的内存马路由排序是位于/hello之后的,抛出异常后导致无法处理内存马路由

解决起来不麻烦,自己造一个空的配置文件,并设置到JFinalFilter调用init方法的参数

JFinalFilterinit方法中,如果filterConfig存在,如果不为空那么就不会解析配置,成功绕过

(这个空文件和null要区分开,空文件是为了防止路由冲突

这时获取到的handler就是恶意构造的

 

0x04 代码实现

思路清晰后就剩代码实现了

首先来一个恶意的Controller

添加恶意路由

构造恶意JFinal对象并设置ActionMapping属性

这一步也是至关重要,必须调用了JFinal.initHandler才可以调用到ActionHandler.init方法

调用ActionHandler.init方法传入上文设置的恶意ActionMapping才可以构造出恶意的ActionHandler

构造一个新的JFinalFilter对象

设置jfinal属性,对象的final属性操作比较麻烦

构造一个空的jfinalConfig并设置到JfinalFilter对象中

参考c0ny1师傅的删除Filter代码删除已存在的JFinalFilter对象

添加新的JfinalFilter

涉及到的几个方法代码,参考自c0ny1师傅

 

0x05 效果

最终效果

img

 

0x06 总结思考

这种替换Filter操作实现的内存马是一种新的免杀思路:

谁都不会想到真正有问题的filter会是核心配置JFinalFilter

不只可以用于JFinal这种,也可以考虑TomcatFilter型以及各种其他框架