浅析JavaWeb内存马基础原理与查杀思路 |
您所在的位置:网站首页 › 木马源码怎么找 › 浅析JavaWeb内存马基础原理与查杀思路 |
文章目录
前言Java内存马内存马分类&原理JavaWeb三大组件注入Servlet内存马注入Filter型内存马JAVA Agent内存马
哥斯拉木马0x01 WebShell0x02 MemShell0x03 FilterShell0x04 Arthas排查0x05 scanner查杀
总结
前言
几年前写过《Web安全-一句话木马》,主要介绍了一句话木马的原理和应用,同时介绍了小马和大马这类常见 Webshell: Webshell 的变迁过程大致如下所述: Web服务器管理页面——> 大马 ——> 小马拉大马 ——> 一句话木马 ——> 加密一句话木马 ——> 加密内存马本文来学习下 Java 内存马的基础原理和在实战中的基础应用,以及当前的一些简单查杀手段。 Java内存马 内存马分类&原理根据内存马的实现技术,大致可以分为如下几类(引用《Shell中的幽灵王者—JAVAWEB 内存马 【认知篇】》一张图): 【内存马基本原理】 内存马类型核心原理Servlet-API 型内存马通过命令执行漏洞、反序列化漏洞、已有传统 Webshell 木马等可以 RCE 执行命令的攻击前提,借助 Java 反射技术,在 JVM 中动态注册一个新的 listener、filter 或者servlet 组件,从而实现在内存中注入可命令执行的无落地文件类的隐蔽木马。特定框架、容器的内存马原理与此类似,如 spring 的controller 内存马,tomcat 的 valve内存马。Java-agent 型内存马Java Agent 简单来说就是 JVM 提供的一种动态 hook class 字节码的技术,通过 Instrumentation (Java Agent API),开发者(攻击者)能够以一种无侵入的方式 (类似 Spring AOP),在 JVM 加载某个 class 之前修改其字节码的内容,或者修改已经被 JVM 加载过的 class,此技术正常情况下可被用于 Java 程序的性能监控、信息收集、问题诊断等。而 Agent 内存马的实现就是利用了这一特性,动态修改特定类的特定方法,在内存中注入恶意代码。【内存马的优劣势】 内存马的运用场景内存马的缺点1)由于网络原因不能反弹 shell 的;2)内部主机通过反向代理暴露 Web 端口的;3)服务器上有防篡改、目录监控等防御措施,禁止文件写入的;4)服务器上有其他监控手段,写马后会告警监控,人工响应的;5)服务使用 Springboot 等框架,无法解析传统 Webshell 的;服务重启后会失效;对于传统内存马,存在的位置相对固定,已经有相关的查杀技术可以检出 JavaWeb三大组件JavaWeb 三大组件指的是:Servlet 程序、Filter 过滤器、Listener 监听器。 接下来将参考《 初识JAVA内存马》一文(强烈推荐仔细阅读),来认识下传统 JavaWeb 的 Servlet、Filter 类型内存马的注入原理与过程,环境直接使用在 Ubuntu 虚拟机上基于 Vulhub 的 Aapache Tomcat AJP Arbitrary File Read / Include Vulnerability(CVE-2020-1938) 漏洞环境。 然后需要将这个 ShellServlet 注册进 tomcat 容器,也就是在 web.xml 中写入: Getshell com.example.servlet.ShellServlet Getshell /shell接着访问/shell并带上 cmd 参数就可以实现命令执行了。 现在我们的目标是往当前 Tomcat 搭建的 Web 服务中动态注入一个恶意 Servlet(即内存马),完成这个目标的当前前提是已经拥有了一个 Webshell(是的,当前想要注入内存马之前还需要拥有一个传统落地文件类型的马子来实现 RCE 才行,除非可以直接借助反序列化漏洞或命令执行漏洞直接 RCE,具体可参见《Tomcat反序列化注入回显内存马》,后续会单独学习),此处为了聚焦内存马的学习(实际上是懒得一步步搭建完整的漏洞环境),直接忽略此前提,直接手动向将一个恶意 jsp 文件,实现一个恶意 Servlet 的动态注册,从而注入内存马。 Title以上恶意 shell.jsp 文件通过反射技术,动态将一个路由为 /shell2的 "Shell2Servlet"组件注册到目标 Web 系统的 JVM 之中,而"Shell2Servlet"组件接受了外部传递的 “cmd” 参数并执行命令(典型的 jsp 木马),从而实现命令执行。 直接将上述 shell.jsp 复制存放到 Tomcat 靶场的 /webapps/ROOT路径下: Filter 作为 Java web 三大件之一,是一种可以对请求和响应进行拦截和处理的组件。Filter可以实现许多功能,如登录控制,权限管理,过滤敏感词汇等。Filter 的使用需要实现Filter接口,重写 doFilter 方法,并且配置拦截路径。 和 servlet 类似,我们先按正常操作添加一个 Myfilter: package com.example.filter; import javax.servlet.*; import java.io.IOException; public class Myfilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("Filter被执行了"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }需要在 web.xml 中绑定 url: Myfilter com.example.filter.Myfilter Myfilter /hello此时在访问 /hello的时候 doFilter 的逻辑代码就会被调用。 接下来我们的目的是注入一个 Filter 型内存马,即借助反射技术向 Tomcat 容器中直接注册一个恶意 Filter,使得在访问任意 URL 的时候均能调用到恶意代码。这个过程自然需要去阅读 Tomcat 源码看看其是如何完成 JavaWeb 项目中的 Filter 组件的解析和注册的,详情请参考《 初识JAVA内存马》。 总的来说,Tomcat Filter 的工作流程如下: 根据请求的 URL 从 FilterMaps 中找出与之 URL 对应的 Filter 名称;根据 Filter 名称去 FilterConfigs 中寻找对应名称的 FilterConfig;找到对应的 FilterConfig 之后添加到 FilterChain中,并且返回 FilterChain;filterChain 中调用 internalDoFilter 遍历获取 chain 中的 FilterConfig ,然后从 FilterConfig 中获取 Filter,然后调用 Filter 的 doFilter 方法;根据上面的流程分析,不难发现最开始是从 context 中获取的 FilterMaps,将符合条件的依次按照顺序进行调用,那么我们可以将自己创建的一个 FilterMap 然后将其放在 FilterMaps 的最前面,这样当 urlpattern 匹配的时候就回去找到对应 FilterName 的 FilterConfig ,然后添加到 FilterChain 中,最终触发内存马。 此处直接给出最终的恶意 shell.jsp 代码: Title以上恶意 shell.jsp 文件通过反射技术,动态将一个路由为 /tr0e的 "Shellfilter"过滤器组件注册到目标 Web 系统的 JVM 之中,而"Shellfilter"过滤器组件在其 doFilter 函数中接受了外部传递的 “cmd” 参数并执行命令(典型的 jsp 木马),从而实现命令执行。 同样直接将上述 shell.jsp 放到服务器的 ROOT 根路径下,然后访问 shell.jsp,完成恶意 Filter 的注册(完成内存马的注入): 前面已经简单介绍了 Java Agent 内存马的基本原理,Java 在 jdk 1.5 之后引入了 java.lang.instrument 包,该包提供了检测 java 程序的 Api,比如用于监控、收集性能信息、诊断问题,Java Agent 能够在不影响正常编译的情况下来修改字节码,即动态修改已加载或者未加载的类,包括类的属性、方法。Agent 内存马的实现就是利用了这一特性使其动态修改特定类的特定方法,将我们的恶意方法添加进去。 【0x01 Java Agent基础】 首先推荐一篇博文:《Java Agent 从入门到内存马》,从 0 到 1 讲述了 Java Agent 基本原理和 Agent 内存马的生成,很适合像我这样第一次了解 Java Agent 内存马的新手学习。特别声明:本小节参考了此文章大部分内容。 Java agent 的使用方式有两种: 实现 premain 方法,在 JVM 启动前加载。实现 agentmain 方法,在 JVM 启动后加载。以一个简单的 premain 为例,创建一个类并且实现 premain 方法: package com.shiroha.demo; import java.lang.instrument.Instrumentation; public class PreDemo { public static void premain(String args, Instrumentation inst) throws Exception{ for (int i = 0; i 反编译成 java 代码-> 源码 webshell 检测。目前常用的哥斯拉、冰蝎、蚁剑等常用的 Webshell 管理工具,都提供了一键打入内存马的功能,但是同时也存在一个致命的逻辑上的“问题”:要先有文件型 webshell,再植入内存马,这是不是违背了使用内存马技术的初衷? 攻防实战中是否也一定要通过落地 JSP 再使用 Webshell 管理软件进行内存马注入?能否实现完全无落地文件便注入内存马?答案是当然的,比如我们也可以直接借助反序列化漏洞或命令执行漏洞等 RCE 漏洞直接植入内存马,具体可参见《Tomcat反序列化注入回显内存马》,后续会结合反序列化漏洞进行单独学习。 本文参考文章: Shell中的幽灵王者—Java内存马_认知篇;一文看懂内存马 - FreeBuf网络安全行业门户;初识JAVA内存马_JavaWeb传统内存马从0到1;Java Agent 从入门到内存马;干货|冰蝎、哥斯拉 内存马应急排查;内存马检测排查手段;Java内存马攻防实战_攻击基础篇_全;JAVA内存马的“一生”(很全面);JavaWeb 内存马一周目通关攻略 | 素十八; |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |