内存马初识 | 45期

admin 2023年10月19日12:25:21评论13 views字数 3623阅读12分4秒阅读模式
内存马初识 | 45期

内存马初识

01 基础概念

内存与硬盘

在程序运行时,硬盘和内存扮演着不同的角色:

  • 硬盘用于存储程序的可执行文件、库文件、配置文件和其他必要的数据文件。当程序首次运行或在需要时,这些文件从硬盘加载到内存中。

  • 内存用于存储程序的指令和数据,包括代码、变量、对象、堆栈等。当程序需要执行特定的指令或访问特定的数据时,CPU从内存中读取这些内容进行处理。

因为内存的成本是很高的,所以内存的容量通常比硬盘小得多,但读取和写入速度更快。所以在运行程序将他放入内存,平时放在硬盘来节约内存空间。

安全问题-内存马

普通的木马是写入一个文件去访问,恶意代码是依靠于文件的。执行后就会在内存中被释放掉。但是内存马是依赖于程序本身的动态注册,会在内存中进行一个保存,视为程序的一部分。实现脱离文件后依旧可以运行。 

02 Tomcat内存马

(此文章默认你已经了解javaweb)

对于Tomcat内存马,我们首先要知道Java会将JSP文件翻译成一个Servlet的文件的。同时你会发现JSP是热部署的。即可以不停止整个java服务来添加新的Jsp页面。这对与Java-web开发来说是极为方便的,但是方便就容易带来安全的问题。结合Servlet3支持动态注册,我们就可以构造各种Web组件内存马。

Listener内存马

ServletRequestListener

调用链

我们直接通过书写一个Listener,然后进行调试即可发现调用链为:

内存马初识 | 45期

我们的代码逻辑是记录在requestInitialized方法中的,那么我们就寻找是怎么调用的requestInitialized方法。

StandardContext:

内存马初识 | 45期

我们可以看到是通过listener.requestInitialized这里进行的一个调用。而这个listener是通过getApplicationEventListeners()获取的。

内存马初识 | 45期

那么关键就是这个applicationEventListenersList的内容了。

内存马初识 | 45期

并且StandardContext类中提供了这么一个方法给我们添加。那么StandardContext类我们如何获取勒,查看调用链子简单寻找了下,StandardHostValve类中存在对StandardContext的获取。

内存马初识 | 45期

那么我们就要获取request类了,在JSP中是自带有RequestFacade类的。我们要获取的是Request类,所以我们直接通过反射来进行获取。

内存马初识 | 45期

其中的this.request被传入了Request类,也就是StandardHostValve类中的request。然后写入我们的Listener就可以了。

思路总结

Listener是会检测任何数据的变化的,对于ServletRequestListener对象,对于每一个会话连接都要进行一个检测。那么就一定存在一个全局的存储位置。然后通过反射对这个变量进行更改即可实现Listener的建立。这里即为StandardContext.applicationEventListenersList。

POC

内存马初识 | 45期

Filter类型的创建

调用链

内存马初识 | 45期

internalDoFilter:189.ApplicationFilterChain:

内存马初识 | 45期

这里可以看出我们的Filter是由filters属性来进行存储的。那么我们寻找一下是如何进行初始化的。

invoke:197.StandardWrapperValve中使用了ApplicationFilterFactory.createFilterChain来新建一个ApplicationFilterChain类。

内存马初识 | 45期

我们可以看到其中是通过读取StandardContext的属性来进行构建ApplicationFilterChain类的。

内存马初识 | 45期
内存马初识 | 45期

所以我们即对StandardContext的属性filterConfigs和filterMap进行设置即可。我们来查看是否有对应的属性设置的方法。

创建filterMap:

内存马初识 | 45期
内存马初识 | 45期

创建filterConfigs:

内存马初识 | 45期

filterConfigs本质是个Map,看看它是如何被赋值。

内存马初识 | 45期

那么我们就要对filterDefs进行一个赋值:

filterDef。

内存马初识 | 45期
内存马初识 | 45期

然后再对filterConfigs进行一个赋值:

内存马初识 | 45期

思路总结

  • 获取StandardContext对象;

  • 设置StandardContext中的FilterMaps对象;

  • 设置filterDefs对象,然后组装进filterConfig,然后将filterConfig写入filterConfigs中。

POC

内存马初识 | 45期
内存马初识 | 45期

Servlet型

调用链

这个是较为简单的,应用一下大佬的调试链子。

内存马初识 | 45期

通过configureContext(webXml)方法创建StandWrapper对象,并根据解析参数初始化StandWrapper对象。

Servlet的所有信息是存储在wrapper中的。

内存马初识 | 45期
内存马初识 | 45期

思路总结

所以综上我们的思路就是:

  • 老套路获取StandardContext对象;

  • 然后通过StandardContext.createWrapper()创建StandardWrapper对象;

  • 设置StandardWrapper对应的属性,并将StandardWrapper对象添加进StandardContext对象;

  • 通过StandardContext.addServletMappingDecoded()添加对应的路径映射。

POC

内存马初识 | 45期
内存马初识 | 45期
内存马初识 | 45期

Valve

(个人感觉这个是分析起来最简单的。)

管道机制主要涉及到两个名词,Pipeline(管道)和Valve(阀门)。如果我们把请求比作管道(Pipeline)中流动的水,那么阀门(Valve)就可以用来在管道中实现各种功能,如控制流速等。因此通过管道机制,我们能按照需求,给在不同子容器中流通的请求添加各种不同的业务逻辑(即其中的invoke方法)。

即通过一个Pipeline类来维护一个通道,具体的逻辑是由Valve类来进行维护的。

内存马初识 | 45期
内存马初识 | 45期

其中的invoke方法即为我们的逻辑书写点。

调用链

直接使用Filter的调试。

内存马初识 | 45期

在invoke:97.StandardContextValve(org.apache.catalina.core)中调用了管道中的Valve的invoke方法。

内存马初识 | 45期

思路总结

我们的思路即创建一个Value加入到管道StandardPipeline类中即可。

  1. 获取StandardContext对象;

  2. 通过StandardContext对象获取StandardPipeline;

  3. 编写恶意Valve;

  4. 通过StandardPipeline.addValve()动态添加Valve。

POC

内存马初识 | 45期

03 内存马的检测

有攻击就有防,根据上文内存马的构造我们就可以写出相应的检测软件。

Listener内存马

我们知道我们是对StandardContext.applicationEventListenersList属性进行更改来注册Listener内存马。那么我们就可以直接对applicationEventListenersList属性进行一个读取即可。

内存马初识 | 45期

那么如何从这些类中去读取那些是内存马勒,我们可以直接去读取它的一个class文件。查询是否存在对于文件,如果不存在就可以初步判断他是一个内存马了。

内存马初识 | 45期

代码:

内存马初识 | 45期

Filter内存马

前文我们是自己对filterConfigs的一个注册,我们对于他的一个检测就简单多了,只用考虑读取就是了。一样的套路使用反射对StandardContext类的属性进行一个读取。

内存马初识 | 45期

然后核实这些类是否存在对于的class文件。

内存马初识 | 45期
内存马初识 | 45期

Servlet内存马

Servlet是通过standardContext.addChild来对一个Wrapper进行添加的。那么我们直接去看看是否有其他的方法可以进行获取。

内存马初识 | 45期

同时查找一下Wrapper对servlet的获取方式。通过getServletClass()对servlet的类名进行一个获取。

内存马初识 | 45期

后面就是一个相同的思路了。查找对应的类名是否存在对应的类文件。

内存马初识 | 45期
内存马初识 | 45期

Value内存马

StandardPipeline类直接提供了对应的getValves方法,那么就很简单了。

内存马初识 | 45期

一样的思路去获取类后查找是否存在对应的class文件即可。

内存马初识 | 45期

04 原创检测工具

基本原理上文已经提到了,就是进行一些整合和进行一些页面的美化。

源码地址https://github.com/TvT-dog/Tomcat-memshell-find。希望大家点点star。😊

05 参考文章

https://goodapple.top/archives/1355

https://longlone.top/%E5%AE%89%E5%85%A8/java/java%E5%AE%89%E5%85%A8/%E5%86%85%E5%AD%98%E9%A9%AC/Tomcat-Servlet%E5%9E%8B/

内存马初识 | 45期

长按二维码关注

D0g3

道格安全


原文始发于微信公众号(道格安全):内存马初识 | 45期

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年10月19日12:25:21
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   内存马初识 | 45期http://cn-sec.com/archives/2127350.html

发表评论

匿名网友 填写信息