因为平日做开发比较多,对"马"的一些概念基本是一无所知,最近读到了一篇往Tomcat Filter里种内存马的文章挺有意思,因为是无文件落地(其实还是有吧,就是删完后也无影响),直接就可以把马注入到内存里。所以持久性肯定会强,而且今年的hvv对内存马的应用也多了起来,所以在这篇文章里就简单研究一下这个技术点:

贴个内存马的概念:

1.PNG

我学习了几篇文章,对内存马不会有文件落地还是比较疑惑,因为文章里无论是filter型还是servlet api型还都是要上传一个jsp或者用冰蝎连下远程才可以,虽说jsp文件只要上传一次就可以删除了,但是实际上还是有上传的动作在了,然后又学习了几篇文章,给出了如下答案:

比如这篇文章就记录了内存马需要上传文件和无需上传文件(利用了shiro反序列化漏洞进行注入)两种方式:

https://blog.csdn.net/Finlinlts/article/details/119989783

这篇文章的开篇也有提到jsp内存马需要上传文件的问题:

https://www.freeaihub.com/post/106851.html

理解的不够深,下面对Filter型内存马的操作我就都是在可以做文件上传的前提条件下去尝试了:

参考文章:

1、内存马涉及基础知识整理

2、IntelliJ IDEA创建Servlet最新方法 Idea版本2020.2.2以及IntelliJ IDEA创建Servlet 404问题(超详细)

3、Tomcat 内存马学习(一):Filter型

4、Java Filter型内存马的学习与实践

5、中间件内存马注入&冰蝎连接

6、【安全记录】通过jsp文件注入内存马

7、一文看懂内存马

一、环境搭建

之前写过一篇文章是研究Tomcat原理架构,结果Container容器那块没有好好研究,这里贴两张图,因为Filter型内存马实际上都是在Container容器中运行的,后面跟进源码也会用到这两张图:

每个 Context 都代表一个具体的Web应用,在一个 Context 下可以有着多个 Wrapper
Wrapper 主要负责管理 Servlet ,包括的 Servlet 的装载、初始化、执行以及资源回收

3.png

4.png

我们的请求会经过 filter 之后才会到 Servlet ,那么如果我们动态创建一个 filter 并且将其放在最前面,我们的 filter 
就会最先执行,当我们在 filter 中添加恶意代码,就会进行命令执行,这样也就成为了一个内存 Webshell

所以我们后文的目标:动态注册恶意 Filter,并且将其放到 最前面

2.png

在注入 Filter内存马 之前要先看下正常 Filter 在 Tomcat中的流程是怎么样的,主要跟进doFilter的相关代码,首先需要创建Servlet:

我这里已经建好了,可以参考文章2来一步步创建。

5.PNG

参照文章3通过web.xml注册filter并重启tomcat,请求filter的url可以输出结果:

filter1和filter2内容一样,在这个filterchain中由于web.xml设置,1排在2的前面

/**
 * @author jinyunlong
 * @date 2021/10/25 13:36
 * @profession ICBC锅炉房保安
 */

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class filterDemo1 implements Filter{

    /*
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        System.out.println("我是FilterDemo1,客户端向Servlet发送的请求被我拦截到了");
        //对请求放行,进入下一个过滤器FilterDemo2
        chain.doFilter(request, response);
        System.out.println("我是FilterDemo1,Servlet向客户端发送的响应被我拦截到了");
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>filterDemo1</filter-name>
        <filter-class>filterDemo1</filter-class>
    </filter>
    <filter>
        <filter-name>filterDemo2</filter-name>
        <filter-class>filterDemo2</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>filterDemo1</filter-name>
        <url-pattern>/*</url-pattern>
        <!-- /*是对所有的文件进行拦截 -->
    </filter-mapping>
    <filter-mapping>
        <filter-name>filterDemo2</filter-name>
        <url-pattern>/*</url-pattern>
        <!-- /*是对所有的文件进行拦截 -->
    </filter-mapping>
</web-app>

6.PNG

关键是在这一行:

chain.doFilter(servletRequest,servletResponse);

chain.doFilter将请求转发给过滤器链下一个filter,如果没有filter那就是转发给Servlet,所以说过滤链是可以由多个filter组成的。

二、上传内存马

跟进代码流程比较长而且比较复杂,有不少还没弄懂,就不截图了。根据文章3、4可以总结出生成filter型内存马基本流程如下:

    1、创建一个恶意 Filter
    2、利用 FilterDef 对 Filter 进行一个封装
    3、将 FilterDef 添加到 FilterDefs 和 FilterConfig
    4、创建 FilterMap ,将我们的 Filter 和 urlpattern 相对应,存放到 filterMaps中(由于 Filter 生效会有一个先后顺序,所以我们一般都是放在最前面,让我们的 Filter 最先触发)

每次请求createFilterChain都会依据此动态生成一个过滤链,而StandardContext又会一直保留到Tomcat生命周期结束,所以我们的内存马就可以一直驻留下去,直到Tomcat重启

构造jsp代码并上传至Tomcat服务器(我这里是Tomcat8.5.42),访问即创建恶意filter成功,之后便可以命令执行。

7.PNG

8.PNG

三、小结

从面上记了下这次实例的过程,针对filter型内存马,源码的跟进步骤还有点不清楚,参考文章3、4、5写的非常清晰,日后可以继续学习,而且filter型内存马只是非agent型内存马的一种,还有servlet api型和无需上传文件的漏洞型;还有agent型内存马这一大类问题也有待学习。

作为普通开发人员来说,先从面上对这个技术点有个了解,至少知道遇到filter型内存马该如何应对了,(重启Tomcat服务哈哈哈哈)。


标题:Java Filter型内存马的简单研究
作者:jyl
地址:http://jinyunlong.xyz/articles/2021/10/24/1635005678699.html