导语:通过列举数个案例助大家快速认知和理解什么是 JavaWeb 内存马。
Goby社区第 21 篇技术分享文章
全文共:6700 字 预计阅读时间:17 分钟
自我介绍:大家好,我是 su18。
无论是个人博客还是社区,已经很久没写技术文章了,原因有很多,时间、精力、心态等等。但在开源社区也算比较活跃,由于工作需要,今年 6 月份我编写并开源了一个项目 ysuserial,在原项目的基础上进行了优化、处理,并增添了很多新功能。
在随后的日子里,我不定期的把在网上看到的、学习到的、研究出来的内容实现并汇总一部分在这个项目里,除了反序列化相关的技术外,我还着重在项目中添加了直接打入内存马的功能,目前项目中已经支持了各种各样常见的内存马,虽然公开的代码在利用上并不是特别深入,但很通用及全面,并经过多个版本的测试。
关于内存马相关的技术文章,我曾经也写过两篇 《JavaWeb 内存马一周目通关攻略》、《JavaWeb 内存马二周目通关攻略》发表在个人博客上,从技术上介绍了常见的几种内存马的实现,事实上这个系列还可以写很多篇,并且可以持续进行深入。去年我也曾经站在 RASP 的角度写过内存马的查杀和防御项目,也分享过一些 PPT。
后来随着时间的推移,我又看到了很多师傅、厂商及平台在实战中使用的不同的内存马的实现,包括不同中间件、不同框架、CMS 等可利用的内存马。我发现大家都不局限于现有的模式,思维发散,从植入、利用、流量上面都进行了很多的 DIY。
再后来我意识到,内存马的使用已经越来越普及,相关的文章也越来越多,但即便如此,很多师傅在咨询我相关的问题时,还是感觉对相关的概念有所模糊,而且在技术的使用上,还是存在着一些不低的门槛,所以这次我打算从一些新的角度切入,再谈谈相关的内容。
0×01 前言
如果要给 Webshell 分个等级,JavaWeb 内存马一定是现阶段当之无愧的 Shell 之王,”它”何德何能?
传统的 Webshell 后门,无论如何花费心思隐藏、如何变化,在现有的防御措施下都已经无法有效长期在目标系统内存留,防御措施简单列举:
对于终端安全:有文件监控、防篡改、EDR;
对于后门:有 Webshell 查杀、流量监测;
对于网络层面:有防火墙防止反连、反向代理系统隐藏真实 IP;
等等。
目前主流的防御措施针对 Webshell 的静态检出率在 90% 以上,在部分环境下甚至完全无法落地,防御方可以做到快速应急响应。正因为这些限制,内存马技术得以诞生并快速发展,无文件攻击、内存 Webshell、进程注入等基于内存的攻击手段也受到了越来越多的师傅青睐,在实战环境中已占得一席之地。可以毫不夸张的说,内存马相关技术将会是未来渗透工程师必须要会使用的安全技术。
本篇名为《JavaWeb 内存马 【认知篇】》,为什么是Java?
1. 对于企业级用户来讲,Java 是范围最大、使用最广、生态最全的编程语言,因此使用 Java 开发的中间件也是最多的,使用的人也是最多的;
2. Java 安全目标行业关注较多,研究较多。
本文将从理论和概念上帮助大家快速认知和理解什么是内存马,什么是 JavaWeb 内存马 ,并列举了数个案例帮助大家理解。
0×02 概念的演变
在 2017 年,由 n1nty 发表在其个人公众号的文章 《Tomcat 源代码调试笔记 - 看不见的 Shell》 提出了两种隐藏 Webshell 的技术手段,时至今日,这篇文章也刚刚 1000 出头的阅读量,但确实是较早的将此项技术提出并实现的文章。
在此之前,我还发现了由园长在 2014 年发表在其个人博客上的 《Java Timer 后门》 ,发现在一些情况下,即使删掉 jsp ,其中的代码也会驻留在程序中继续执行。
我相信在此期间还有诸多师傅发现并使用了类似的技术,以达到在无需 JSP Shell 文件长期存在于服务器上,而可以持续执行其中代码逻辑的目的。
这样的概念在安全行业里一直没有得到完全的重视,只有一些做研究的师傅在社区交流和探索相关的实现,直到冰蝎 Behinder_v3.0 Beta 7 的更新将 java agent 类型的内存马进行了实现,将此种技术带入大众视野。
随着技术的发展和演变,使用 JavaWeb 内存马技术的人越来越多,技术发展也越来越复杂。与此同时,流量检测、终端安全、RASP 等安全厂商也开始了针对内存马的检测和防御,从而激生对应的种种绕过手段。
对于此种技术,在国内的讨论要远大于国外,这可能是因为国内安全人员对 Webshell 管理软件的使用习惯导致,也就是说在这一部分技术领域相关的研究和积累,国内水平是要领先于国际的。但即便如此,内存马技术的实战利用仍处在初级阶段,未来还有很大的技术发展空间。
内存马的攻防还在不断的进行和升级中,相信会有越来越多有趣技术出现。
0×03 内存马的分类
到如今,在互联网上公开讨论的,已经有非常多的内存马利用方式,本篇对其进行一个大致的整理,根据内存马的实现技术,大致可以分为如下几类:
传统 Web 应用型内存马:使用基本 Servlet-API 实现的动态注册内存马,此种类型的内存马最经典,已经被扩展至适应各个中间件。
框架型内存马:除了传统的 Servlet 项目,使用 Spring 全家桶进行开发的项目越来越多,而 Spring-MVC 则是自实现了相关路由注册查找逻辑,以及使用拦截器来进行过滤,思想上与 Servlet-Filter 的设计类似。
中间件型内存马:在中间件的很多功能实现上,因为采用了类似 Filter-FilterChain 的职责链模式,可以被用来做内存马,由于行业对 Tomcat 的研究较多,因此大多数的技术实现和探究是针对 Tomcat 的,但其他中间件也有相当多的探究空间。
其他内存马:还有一些其他非常规的利用思路,可以用在内存马的实现上,例如 WebSocket 协议等。
Agent 型内存马:利用 Java Agent 技术进行植入内存马逻辑的实现方式。
但实际上,内存马的深度和广度完全不局限于此,还有很多思路可以用来进行内存马的扩展:
对于 Agent 型内存马,可以 hook 非常多的位置,如各种 SPI 的实现,可以接管整个 JVM,获取数据;
除了基于 Web 协议的内存马,可以使用各种协议作为内存马的通信途径,如 grpc、jmx、jpda 等,或封装多层协议;
对于各种中间件/框架,利用其设计模式,可挖掘出多种内存马的利用方式。
除了按照内存马的实现方式分类,还可以按照内存马的利用方式分为:冰蝎马、哥斯拉马、蚁剑马、命令回显马、流量隧道马等等。
0×04 实用性讨论
在经过一番调研后,我发现在实战过程中使用内存马技术的人不在少数,使用内存马的人主要有以下原因,这也是内存马的优势:
由于网络原因不能反弹 shell 的;
内部主机通过反向代理暴露 Web 端口的;
服务器上有防篡改、目录监控等防御措施,禁止文件写入的;
服务器上有其他监控手段,写马后会告警监控,人工响应的;
服务使用 Springboot 等框架,无法解析传统 Webshell 的;
对内存马技术感到不明觉厉的....
但同时,内存马的缺点也很明显:
服务重启后会失效;
对于传统内存马,存在的位置相对固定,已经有相关的查杀技术可以检出。
但即使如此,对于大多数线上的服务,由于对可用性要求较高,通常情况下服务频繁重启的可能并不大,再加上诸多优点,内存马还是成为攻击者首选的 Webshell 维持方式。
攻击者通常使用冰蝎、哥斯拉等 Webshell 管理工具的 Webshell 内容作为内存马的恶意逻辑,这样可以使用后续的相关功能。当然也可以使用如 regeorg 等逻辑打通内网隧道,或简单的命令回显。
在内存马的选择和使用上,属于见仁见智,有人喜欢 Servlet-API 内存马,觉得比较原生;有人喜欢 WebSocket 内存马,觉得更新颖;有人喜欢 Agent 型内存马,觉得更通用。无论使用哪种,都需要考虑对实际环境的影响,例如 Filter 型内存马一般将自己放在 FilterChain 的首尾,如果处理 /* 的请求,就需要考虑 FilterChain 中后续 Filter 处理的影响。使用 Agent 型内存马要考虑自己复杂的逻辑会不会导致 JVM Crush 的情况。
本次调研发现,总体来说,最受欢迎的是 Servlet-API 型和 Agent 型内存马,可能是因为这些相关技术已经被实现完全并公之于众,而其他种类的内存马只有少部分人在实战中使用。
除了网络环境、应用环境的影响,内存马还需要考虑的是兼容性的问题,对于一种技术,在不同版本的框架、组件下,技术细节可能由变动,因此想实现一个优秀的内存马,还应该尽可能对其不同版本的组件进行兼容,并经过实战的检验。
在实现攻防中,我发现越是使用小众的、非主流的内存马实现方式,就越容易逃避防御手段的检测。
0×05 技术性攻防延展
内存马的概念已经火了几年,对于内存马的攻防自然也进行了多次的交锋。
首先看一下防御手段的迭代:
LandGrey 于 2020 年发布了 copagent 项目,基于 Java Agent 技术查找关键类的子类、关键注解类,并通过恶意包名标识类,随后将这些类 dump 出来并匹配其中的风险关键字。
c0ny1 也发布了 java-memshell-scanner 项目,基于 Tomcat API 查找关键位置中的信息(Servlet/Filter),通过 ClassLoader 判断是否在磁盘上、类名(包名)等信息进行内存马的检出,还支持将 Class 从内存中 dump 出来进行人工分析。
potats0 通过 sa-jdi.jar 解决了无法获取到使用 redefineClasses 的类处理的类字节码。
还有师傅提出了基于 mbean 的 filter/servlet 风险类识别维度进行内存马的查找。
这些防御手段通过在目标系统中定位关键类,并多维度识别风险的方式进行内存马的检出。
再来看一下绕过检测的手段:
冰蝎通过删除 /tmp/.java_pid+{pid} 文件来阻止 JVM 进程通信,从而禁止查杀 Agent 加载。
ZhouYu 通过阻止后续的 ClassFileTransformer 加载的方式阻止其他 Java Agent 加载来防止检测和查杀。
Glassy 师傅分享通过 Bootstrap ClassLoader 加载恶意类来绕过对内存马的检测。
冰蝎及哥斯拉作者还针对 Agent Self Attach 以及无文件落地注入 Agent 内存马进行了技术上的突破,可以无文件落地注入 agent 内存马。
绕过手段基于对检测方式的透明,对其关键逻辑进行绕过,使检测手段失效。
相关的手段和思路还有很多,这里不再一一列举,除了对内存马针对性的查杀,内存马还面临常规防御的问题,例如,内存马功能交互在流量层的特征防御;内存马执行恶意操作在主机层面或代码层面的防御等等。WAF 也好,RASP 也好,EDR 、HIDS 也好,诸多的防御措施都成为实战中植入内存马的拦路虎。
除了开源项目,各大安全厂商也发布了对内存马的检出和查杀项目,在实战中还需要针对它们进行绕过。
但是可以肯定的是,无论是什么样的防守技术,在越来越偏向底层的内存攻防、越来越动态的攻击手法中,都会捉襟见肘。正所谓,道高一尺,魔高一丈。
0×06 案例
在攻防行动中,内存马技术也已经被不止一次的使用到,攻击方与防守方也都在内存马技术上进行了交锋。这里举几个真实的案例。
案例一:某友 NC 反序列化漏洞
在攻击过程中,发现了一个某友 NC 系统存在反序列化漏洞,测试发现 URLDNS 可以收到日志,但是无法反弹 shell,推测是目标环境无法出网。
在经过几次测试后,发现可以尝试文件写入类的漏洞,但文件落地后,会被快速查杀,推测是有文件目录监控手段,发现有新文件生成后会有设备告警,被防守人员查杀。
后来经过本地测试和研究,通过反序列化漏洞直接打入内存马,目标系统的设备无告警,防守人员无感知,成功拿下目标,并进行内网渗透。
案例二:springboot + shiro 550 不出网
发现目标是自研的应用系统,使用了 springboot 框架,并使用 shiro 进行鉴权,经过测试,系统使用 shiro 版本较低,使用了默认的 AES 加密密钥,于是尝试使用 shiro 550 CB 链进行攻击,但是攻击发现,系统不出网,无法进行反连。
与此同时,程序使用 springboot ,是以 Jar 的形式启动,没有对 JSP 进行解析的目录,无法通过执行命令写入 JSP Webshell 的形式进行 getshell。
为了持久化并进行进一步的攻击,几经测试,后来使用了 Spring Interceptor 型的内存马,获取了 Web 服务器权限。
这样的类似的案例还有很多,在各种不良环境下,内存马能解决很多实际难题。
为了更清晰的给大家展示内存马的作用,这里做一个简单的演示,这里采用OpenRASP最新版(日常迫害)来展示内存马的绕过能力。
0×07 问题
针对内存马说了这么多,其实细节上还有非常多的可研究的点,也是这些点促进了内存马攻防技术的不断提高。
对于内存马领域而言,攻击手段的发展是要远远快于防御手段的,因为攻击者只需要研究实现,无需考虑后果,防御者却要考虑对实际环境带来的影响。
现在大家使用的漏洞利用工具都或多或少提供了一部分内存马的实现,例如 JNDI 注入利用工具、Shiro 利用工具、Weblogic 利用工具等等。但这都局限于单一的某种漏洞利用类型。其他环境,例如某某框架、某某 CMS 的某某漏洞,想要直接打入某种类型的内存马,还是需要大量的研究与调试。
目前常用的哥斯拉、冰蝎、蚁剑等常用的 webshell 管理工具,都提供了一键打入内存马的功能,并在技术实现上非常优秀,但是同时也存在一个致命的逻辑上的“问题”:
要先有文件型 webshell,再植入内存马,这是不是违背了使用内存马技术的初衷?
这其实就非常值得我们思考,对于常见类型的漏洞利用,能否直接植入内存马?而不是通过落地 JSP 再使用 webshell 管理软件进行中转呢?或者是否有一些较为通用的手段或框架,能够在攻击中快速注入及利用内存马呢?
对于这个问题,后续我将会进行展开讨论。
0×08 REFERENCE
1、2017 - Tomcat 源代码调试笔记 - 看不见的 Shell
2、2014 - Java Timer 后门
3、2021 - 冰蝎 Beta 7
4、2020 - copagent
5、2020 - java-memshell-scanner
6、2021 - ZhouYu
7、2021 - aLIEz
8、2022 - RASP攻防下的黑魔法
9、2021 - Java内存攻击技术漫谈
10、2022 - 论如何优雅的注入Java Agent内存马
11、2021 - JavaWeb 内存马一周目通关攻略
12、2021 - JavaWeb 内存马二周目通关攻略
13、2021 - ShiroAttack2
14、2021 - JNDIExploit
15、2022 - ysuserial
16、2020 - MemoryShell
Goby 欢迎表哥/表姐们加入我们的社区大家庭,一起交流技术、生活趣事、奇闻八卦,结交无数白帽好友。
也欢迎投稿到 Goby(Goby 介绍/扫描/口令爆破/漏洞利用/插件开发/ PoC 编写/ IP 库使用场景/ Webshell 等文章均可),审核通过后可加 5000-10000 社区积分哦,我们在积分商城准备了好礼,快来加入微信群体验吧~~~
微信群:公众号发暗号“加群”,参与积分商城、抽奖等众多有趣的活动
如若转载,请注明原文地址