Goby 利用内存马中的一些技术细节【技术篇】_内存码流量特征

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Golang全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注go)
img

正文

  • C3P0 在原版中,C3P0 链使用了 PoolBackedDataSource 进行远程类加载来进行漏洞利用,但实际上,C3P0 还可以通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入,可以通过 EL 表达式来进行内存马的打入,除了 EL 表达式,还可以使用 Groovy、SnakeYaml 等。

在这里插入图片描述

这里随便举了几个反序列化利用链串联到内存马的技术思路,除此之外还有更多的漏洞利用情况,可以酌情进行“曲线救国”,考虑到行文的篇幅,这里就不在赘述更多的思路。

三、内存马的生成

说过了前置的漏洞利用方向,接下来,讲下在内存马生成过程中涉及到的一些技术细节。

1. 动态生成技术

考虑到不同漏洞利用点,不同的漏洞利用场景和需求,不同人员的习惯不同等,在实际环境中,内存马的内容不能是一成不变的,需要根据种种配置进行动态生成。

因此,这里使用 javassist 进行内存马恶意类字节码的动态生成与写入。在内存马的准备过程中,将会面临一些的一些需求:

  • 漏洞利用方式是固定的,例如命令执行、常用的冰蝎、哥斯拉或者自研的 webshell 交互工具,基本都是可复用的自定义漏洞利用方式;
  • 内存马能够自定义 URL 、自定义密码,除了常见的 AES 密钥,还可以设置额外的鉴权机制;
  • 可以随意选用任意一种内存马技术,使用任意一种利用方式,均可以快速动态生成。

因此,我这里将关键逻辑最终抽象成一个相同的方法,这个方法的前两个参数分别是 Requst 和 Response 对象,无论是命令执行、冰蝎、哥斯拉等等,都可以在这个方法下注入自己的逻辑。对于不同的中间件,由于封装和实现和不同,在进入关键逻辑前进行额外的判定以及处理,使最终处理逻辑一致。

例如下面是冰蝎的核心逻辑:

在这里插入图片描述

下面是哥斯拉的核心逻辑:

在这里插入图片描述

下面是命令执行的逻辑:

在这里插入图片描述

在确定了利用的参数后,则可以根据不同的内存马类型、不同的利用方式进行字节码的组装,将关键方法依次插入恶意类,最终形成一个完整的内存马。

2. ClassLoader 的问题

之前提到了在恶意类的动态加载和初始化时,要考虑 ClassLoader 的选取问题,这里在内存马加载后也一样,有关 ClassLoader 的问题需要额外注意。

第一种情况,作为内存马文件本身,一般需要将自身的实例放在处理路由的关键位置中,如全局上下文的某个 Map 成员变量中,这种情况就需要传递一个实例的引用,只要在内存马恶意类初始化时将自身对象的一个实例注册在系统内关键位置即可。

但是也有例外,例如在 Struts2 框架中,关键位置中储存的不是类实例,而是类名,在处理路由时,如果找到映射,则动态创建类实例并调用其 execute 方法进行处理,因此,在进行恶意内存马的注入时,不应单单进行类名和路由的映射,还应该将内存马自身类加载到关键上下文中,使其在实例化类时能够找到我们注入的恶意类。

在利用方式上,除了命令执行回显外,内存马的关键逻辑依旧还是通过传递类字节码来实现的。涉及到类加载的部分,除了之前提到的 URLClassLoader、自定义 ClassLoader、线程上下文类加载器之外,依旧可以玩出很多的花样:

  • 使用 java.lang.reflect.Proxy#defineClass0() 注册类;
  • 使用 sun.misc.Unsafe#defineAnonymousClass() 向 JVM 中直接注册类;

也可以使用一些封装类,这些封装类可能调用一些不常见的 ClassLoader 等:

  • 使用 jdk.nashorn.internal.runtime.ScriptLoader#installClass() 注册对象
  • 使用 com.sun.naming.internal.VersionHelper#loadClass()

除了上面这些,还有 JavaSec 群友分享了他找到一些方法:

  • jxxload_help.PathVFSJavaLoader#loadClassFromBytes
  • org.python.core.BytecodeLoader1#loadClassFromBytes
  • sun.org.mozilla.javascript.internal.DefiningClassLoader#defineClass
  • java.security.SecureClassLoader#defineClass
  • org.mozilla.classfile.DefiningClassLoader#defineClass

3. 利用方式

对于内存马利用方式,最常见的三种利用即是,命令执行回显、冰蝎及哥斯拉,三种各有各的优势:

  • 命令执行回显:简单命令执行,可以看到回显;
  • 冰蝎、哥斯拉马:都提供了一些高级的利用功能,可以按需选择。

除了常规的 Webshell 利用方式,最近比较流行的就是隧道马的打入。攻击人员在获取 Webshell 之后,往往进行的下一步动作将会是利用这个机器作为跳板,进行进一步的内网渗透,此时就需要一条打通的流量隧道。

在以前的做法通常是在目标服务器上上传一个流量转发工具如 FRP 等,借由这个工具进行流量转发。若在网络层面不是全端口映射,还要牵扯到端口复用等技术。

但有了内存马,则可以直接一键打入隧道马,直接使用相应的客户端进行连接,真正实现“一把梭”。

在这里插入图片描述

4. Agent No File

由 rebeyond 师傅实现的 AgentNoFile 技术,给我们提供了无需提供 Agent.jar 或者 Agent.so 来直接调用 JVMTI 接口的能力,借助这种能力,我们可以实现无需文件落地进行 Agent 型内存马的注入。

在 Linux 平台下,通过修改 /proc/self/mem 的方式来执行 shellcode,在 Windows 平台下通过 Java 向 PID 为 -1 的进程植入运行shellcode ,从而构造 JPLISAgent 对象,获取调用 Java Agent 的所有能力。

在 BeichenDream 的 Kcon2021Code 项目中,也分享了类似技术思路的代码。

在内存马的实现上,则是通过向目标环境不落地的注入一个 Javassist 依赖 jar,并动态修改目标关键类,注入恶意逻辑,实现 Agent 马的动态修改,例如下图是实现了一个对 ApplicationFilterChain 的 doFilter 方法进行 Hook 的逻辑,实现冰蝎内存马的注入,并从服务器 dump 出来的 class。

在这里插入图片描述

四、内存马的使用

通过漏洞直打内存马的问题解决了,内存马的生成和利用方式的问题解决了,接下来要解决的问题就是在内存马使用过程中遇到的问题。

之前的文章中提到,内存马技术的提出主要为了对抗落地文件会有安全防护设备发现告警的问题,因此,内存马技术从一诞生,就面临并承担着与各种防护能力进行对抗的责任和使命。

1. 安全防护的绕过

首先面临的是流量侧设备的绕过,这部分实际上是 WebShell 管理端和内存马之间通信协议的流量特征。由于主流使用 AES 加解密,少部分使用 DES 加解密等,以及在行为方面会有规律,例如在连接 WebShell 时会发几个包,基于这两项会有一些检测 webshell 连接的手段。因此无论是冰蝎还是哥斯拉,如果没有经过魔改,在流量上的基本特征都会被发现。

但是基本上大家都有魔改的习惯,因此流量层的特征还是不容易统一防护的,而且最新的冰蝎客户端已经支持了自定义的通信协议加解密程序,这样攻击者可以将冰蝎流量伪装为类似业务数据的流量,如 Restful API 返回数据,或类似 base64 图片资源返回数据等。

其次是主机层面的绕过,在主机层面,可能面临着一些 EDR 设备等主机层的防御,这部分防御可能会对 Java 进程调用系统资源进行监控,但大多数时候来讲,这一层的防御几乎无法识别 Java 层面的操作是否属于敏感操作。

最后是 Java 层面的绕过,在 Java 层面,可能面临一些 RASP 产品的防护,或自研安全规则的防御。这些防御措施在一些敏感函数执行的位置进行 Hook ,并基于堆栈或行为等方式拦截可疑行为。

此时我们可以通过反射来进行绕过,无论是通过反射调用更深层次的代码乃至 native 方法,还是反射获取系统里面对指定方法有封装的对象去执行,目的都是为了扰乱堆栈或行为调用链条,使 Java 层面的防御无法判断你是恶意操作还是系统行为,以此来绕过检测逻辑。

例如通过反射调用 native 方法来对命令执行的防御进行绕过:

在这里插入图片描述

或者使用乱七八糟的反射来使调用链难以捉摸,无法判断:

在这里插入图片描述

在或者使用 unsafe 这样的 API 来进行恶意类的创建,都有可能绕过一定的安全防御:

在这里插入图片描述

除了安全防护,内存马再使用上还有一些有趣的方向可以关注,例如可以使用 Websocket 型的内存马以创建长连接的方式来绕过负载均衡,避免打进去的马找不到的问题。

2. 防检测

在之前的内存马文章也提到过,很多工具已经提供了扫描指定位置来检查是否存在内存马的检测手段,此时检查会包含一些维度的判断,同样的,我们需要再这些维度上进行进行一定的处理,来进行防检测,例如:

  1. 恶意类名、包名的检测:对于一些防御手段,会禁止一些已知的恶意包名、类名的加载,因此这里通过动态拼接和生成恶意类包名的方式来迷惑防御系统或管理员。

在这里插入图片描述

  1. 从 ClassLoader 里查看文件是否落地的检测:可以通过自定义 ClassLoader 携带虚假信息或使用系统类加载器加载恶意类的方式使恶意类的类加载器为空来绕过检测逻辑。

在这里插入图片描述

  1. 系统关键位置的检测:有些检测工具可以获取关键位置的信息,并辅助人工排查,例如部分工具获取系统内全部 Filter 型内存马,并进行展示。此时可以通过挖掘非常规内存马的方式来进行规避,在之前我分享的关于 JavaWeb 内存马的 PPT 上层提到过,在 web 请求处理过程中,全部使用职责链设计模式的组件,都能用来作为内存马的挖掘利用方向,因此在各个 web 中间件中,再挖掘一种新的内存马也并非难事。

在这里插入图片描述
4. 很多工具会提供 dump class 的功能,通过将内存中的类字节码 dump 出来进行排查,因此可以通过修改 Java 类在 JVM 中的存在形式 InstanceKlass 数据结构中的相关信息的缓存,如 _cached_class_file 等,来使 dump 出来的 class 是不包含危险代码的类,进行欺骗和隐藏的目的。
5. 一些 RASP 还会使用 redefineClasses 将恶意类、恶意函数的关键方法内容置为空,来达到在运行的系统中清除内存马的目的,此时可以通过修改恶意类的函数修饰符、新增成员变量、方法等方式来使其报错,因为 redefineClasses 不允许类结构和签名的改变。
6. 目前大多数的内存马查杀、防御手段,是通过 Java Agent 技术来实现的,因此防止新的 Agent 注入,也是防检测的重点思路,在第一篇中也提到过,可以通过删除 java pid 文件来阻止 JVM 进程通信,也可以通过阻止后续的 ClassFileTransformer 加载的方式阻止其他 Java Agent 加载来防止检测。

3. 来无影去无踪

首先内存马已经达到了文件不落地的情况,还能不能做什么再次隐匿自己呢?答案是肯定的。

那就是中间件访问日志的清除,在进行访问请求时,中间件会记录日志,这个日志通常会作为后续审查、应急的依据,如果在内存马访问时,能清除访问日志,岂不是做到无痕浏览?

有了思路,执行也很简单,那就是找到中间件中负责记录日志的组件,将其清空,以 Tomcat 为例。

在这里插入图片描述

4. 持久化

最后一个问题就是持久化的问题,需要考虑在服务重启甚至操作系统重启后能否重新恢复内存马的注入:

  • 对于 Java 层面,可以使用 Java shutdown hook 进行内存马的落地等操作,如果目标环境是 Tomcat 可以在 Jar 包的 Resource 目录下写入 JSP 文件等;
  • 若目标环境面临可能被 kill -9 的操作,可以启动一个“守护进程” 关注服务器上的 Java 进程;
  • 对于操作系统的重启,可以提前将关键恶意操作注册成为定时任务等方式进行持久化。

由于这部分的动作是作为内存马技术的延伸,并且为了达到持久化的目的可能会有 Jar 包、资源文件的篡改和落地,有点违背使用内存马的初衷,所以这部分不再展开讨论,期待更优雅的思路。

五、总结

以上部分简单列举了一些实战使用内存马技术中所使用的一些技术问题和遇到的一些坑的解决方案,在经过对以上技术的研究和解决后,在实战上快速使用内存马基本上就没有什么问题了。

虽然我们讨论的是 JavaWeb 内存马技术,但实际可以看到,对抗的思路和技术早已经不单单在 Java 层,而是延伸到了 native 层、内存层面。这仍然是实战化利用中的九牛一毛。在实际环境的使用中,由于操作系统不同、中间件版本不同、JDK 发行版、版本不同等等差异情况、安全限制、安全防护等等复杂的情况,还会遇到种种难题,因此,多研究,多调试,积累思路,才能在实战化的利用中高效、快速利用内存马。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
效、快速利用内存马。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-igwpmO6G-1713128707857)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值