java内存马排除
内存马
介绍
webshell技术历程
在Web安全领域,Webshell一直是一个非常重要且热门的话题。在目前传统安全领域,Webshell根据功能的不同分为三种类型,分别是:一句话木马,小马,大马。而根据现在防火墙技术的更新迭代,随后出现了加密的木马技术,比如:加密一句话。而我们今天要说的是一种新的无文件的Webshell类型:内存马。
为什么使用内存马
传统Webshell连接方式,都是先通过某种漏洞将恶意的脚本木马文件上传,然后通过中国菜刀,或者蚁剑,冰蝎等Webshell管理软件进行链接。
这种方式目前仍然流行,但是由于近几年防火墙,IDS,IPS,流量分析等各种安全设备的普及和更新,这种连接方式非常容易被设备捕获拦截,而且由于文件是明文存放在服务器端,所以又很容易被杀毒软件所查杀。在今天看来这种传统连接方式显然已经过时,于是乎,进化了一系列的加密一句话木马,但是这种方式还是不能绕过有类似文件监控的杀毒软件,于是乎进化了新一代的Webshell—》内存马。
什么是内存马
内存马是无文件Webshell,什么是无文件webshell呢?简单来说,就是服务器上不会存在需要链接的webshell脚本文件。那有的同学可能会问了?这种方式为什么能链接呢?内存马的原理就像是MVC架构,即通过路由访问控制器,我通过自身的理解,概述的说一下, 内存马的原理就是在web组件或者应用程序中,注册一层访问路由,访问者通过这层路由,来执行我们控制器中的代码
内存马的类型
- Tomcat-Servlet
- Tomcat-Filter
- Tomcat-Listener
- Tomcat-Websocket
- Tomcat-Agent
- spring类型的内存马
后面三种还不太熟悉,目前先就前面三种进行介绍
基础
servlet
Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。它负责处理用户的请求,并根据请求生成相应的返回信息提供给用户。
Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
- Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第4步,否则,执行第2步。
- 装载并创建该Servlet的一个实例对象。
- 调用Servlet实例对象的init()方法。
- 创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
- WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。
Filter
Filter译为过滤器。过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理,通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理。
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
Listener
监听器用于监听Web应用中某些对象的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当监听范围的对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计网站在线人数、系统加载时进行信息初始化、统计网站的访问量等等。
主要由三部分构成:
- 事件源:被监听的对象
- 监听器:监听的对象,事件源的变化会触发监听器的响应行为
- 响应行为:监听器监听到事件源的状态变化时所执行的动作
在初始化时,需要将事件源和监听器进行绑定,也就是注册监听器。
可以使用监听器监听客户端的请求、服务端的操作等。通过监听器,可以自动出发一些动作,比如监听在线的用户数量,统计网站访问量、网站访问监控等。
tomcat
在 Tomcat 中,每个 Host 下可以有多个 Context (Context 是 Host 的子容器), 每个 Context 都代表一个具体的Web应用,都有一个唯一的路径就相当于下图中的 /shop /manager 这种,在一个 Context 下可以有着多个 Wrapper
Wrapper 主要负责管理 Servlet ,包括的 Servlet 的装载、初始化、执行以及资源回收
实战
首先,前提条件:必须你能上传jsp文件,并且可以被成功解析
上传代码如下
1 |
|
访问这个页面就可以成功注入了
最后直接访问任意Servlet路由都可以执行命令,只需要在后门加上?cmd=命令
即可
这时候内存马就注入成功了,即使删除我们的注入文件jsp
也是一样可以执行,这样就可以达到无文件的Webshell管理方式了。
只要重启服务器内存马就不存在了
内存马检测工具
排查思路
先判断是通过什么方法注入的内存马,可以先查看web日志是否有web访问日志,如果是Filter或者Listener类型就会有大量的URL请求路径相同参数不同的,或者页面不存在但是返回200的,查看是否有类似哥斯拉,冰蝎相同的url请求,哥斯拉和冰蝎的内存马注入流量特征与普通webshell的流量特征基本吻合。
通过查找返回200的URL路径对比Web目录下是否真实存在文件,如不存在大概率为内存马,如在web日志中并未发现异常,可以排除是否为中间件漏洞导致执行的内存马注入,排查中间件的error.log日志查看是否有可疑的报错,根据注入的时间和方法根据业务使用的组件排查是否可能存在java代码执行漏洞以及是否存在webshell,排查框架漏洞,反序列化漏洞。
java-memshell-scanner
下载好后,直接将tomcat-memshell-scanner.jsp文件放入到服务上访问即可。
Copagent
cop.jar文件
步骤:
- dump内存下来,遇到禁止注入到jvm就g
- 将java内存下载到本地,直接使用D盾扫描下载下来的class,java文件即可
项目地址https://github.com/LandGrey/copagent
jar包地址https://github.com/LandGrey/copagent/raw/release/cop.jar 使用下载的包,自己打的jar出错了
jps 可以看 java的进程
上传到服务器上的tomcat目录前面,然后执行,选择tomcat进程,会在copagent中生成class,java文件夹,然后下载到本地,然后直接用D盾排查
java-memshell-generator
shell-analyzer
基于java agent的内存马查杀的GUI工具
这个工具,可以关掉内存马,当不重启服务时。
使用这个工具需要确保Tomcat端口和10032端口开放。
使用过程
1 |
|
java -cp remote-0.1.jar:/usr/lib/jvm/java-8-openjdk-amd64/lib/tools.jar com.n1ar4.RemoteLoader 4981 admin123
注意:使用jdk下的lib的tools.jar包
启动gui时,也需要选择好jdk下的tools.jar工具注意,选择依赖jdk下的tools.jar包
windows上启动gui.注意,选择好jdk下的tools.jar的包,依赖的主类
可以查看到,代码(也可以将代码复制出来,交给D盾,来判断)
疑问:servlet中间件,和filter,listener关系。
技巧:(工具)哥斯拉,冰蝎,内存马注入的名字,几乎一样的,(收集一下)
复制名字到,方框里面,然后点击删除,就可以了。(当然,删除操作需要谨慎,弄不好就得重新启动服务了)
arthas-bools
linux自带的java环境openjdk不支持jps,jstack等命令
启动命令
1 |
|
查看一下内存中的mbean信息
1 |
|
Arthas常用的命令
1 |
|
Arthas排查内存马命令总结
1 |
|
注意事项
使用Arthas-bools可能会遇到下面的报错
1 |
|
改报错是因为tomcat是以tomcat用户运行的,而我们arthas是用root用户运行的,JVM只能attach同意用户下的java进程
使用runuser命令即可tomcat用户运行arthas。
1 |
|
哥斯拉
首先,使用哥斯拉生成码子,然后放在网站的根目录上。(略,自己弄个tomcat服务器,放在根目录ROOT下即可)
植入内存马前查看内存中的mbean信息。
1 |
|
哥斯拉的内存马有两种形式memoryshell和Filtershell两种。
Filtershell
注入内存马
可以看到所有的哥斯拉内存马的Filter的name中都带有时间戳
1 |
|
使用jad反编译我们认为可疑的类
1 |
|
代码中大量运用invoke反射来实现。
Memoryshell
1 |
|
可疑的classloader
冰蝎
冰蝎内存马
冰蝎内存马由于对底层函数做了hook的操作,所以特征更弱一些。
先生成冰蝎4.0的服务端。
上传后注入内存马
开启冰蝎的防检测功能。
连上内存马。
冰蝎的classloader。
冰蝎马属于servlet类型的,不过并不是加载内存马之后才有的,而是连接冰蝎服务端的时候就有的。
反编译冰蝎的马,可以看到明显的AES加密的key
但是有个终极排查思路,就是内存dump
内存马清除
找了一圈发现,arthas并没有直接关闭指定类的功能。但是可以使用arthas进行热更新代码;但是我使用它做编译的时候失败了,后来学习了一下Javaagent技术,可以对jvm内的运行时类操作,于是可以编写一个agent使用retransformClass字节码重定义技术重新定义这个类。
工具:https://github.com/Garck3h/killBehinderMemShell
直接使用工具重置javax.servlet.http.HttpServlet类
1 |
|
heapdump的使用
不管冰蝎内存马如何hook,但是内存马肯定是存在内存中的,并且访问的时候有路由映射,那么内存dump出来的文件肯定会有记录。
1 |
|
使用string查看post请求的记录;发现可疑的请求目录
查看可疑路径
1 |
|
至此,冰蝎内存马已经排查完毕。
参考链接:https://blog.csdn.net/m0_60571990/article/details/128487029