由于 Web 应用程序的复杂性和重要性, 导致其成为网络攻击的主要目标之一。攻击者在入侵一个网站后, 通常会植入一个 Webshell, 来持久化控制网站。但随着攻防双方的博弈, 各种检测技术、终端安全产品被广泛应用, 使得传统的以文件形式驻留的 Webshell 越来越容易被检测到, 内存型 Webshell 成为新的趋势。本文面向 Java 应用程序, 总结内存型 Webshell 的特征和原理, 构建内存型Webshell 威胁模型, 定义了高对抗内存型 Webshell, 并提出一种基于RASP(Runtime application self-protection, 运行时应用程序自我保护)的动静态结合的高对抗内存型 Webshell 检测技术。实验表明, 与其他检测工具相比, 本文方法检测内存型 Webshell 效果最佳, 准确率为 96.45%, 性能消耗为 7.74%,具有可行性, 并且根据检测结果可以准确定位到内存型Webshell 的位置。
目录
3 内存型 Webshell 威胁模型
3.1 内存型 Webshell 原理
3.2 形式化定义
3.3 威胁模型
3 内存型 Webshell 威胁模型
3.1 内存型 Webshell 原理
内存型 Webshell 是无文件攻击的一种, 是将恶意代码注入到内存中, 利用中间件的进程执行某些
恶意代码, 没有文件落地, 即服务器上不存在可远程访问的 Webshell 文件。其原理如图 1 所示, 攻击者首先构造与请求处理相关的恶意代码, 包括注册恶意组件的代码、修改已有类逻辑的代码, 通过漏洞等场景执行恶意代码, 成功添加恶意组件到 JVM 进程或修改内存中已有类的逻辑, 将恶意代码驻留在系统内存中, 因此得名内存型 Webshell。注入成功后,攻击者通过访问特定(带参数的)URL, 达到命令执行、文件操作、数据库操作等远程控制 Web 服务器的目的。Java 的反射机制和Instrumentation 机制为内存型 Webshell 提供了良好的植入方式。根据内存型Webshell 的利用技术不同, 将其分为两类, 一类是组件类(也称为非 Agent 类), 一类是 Agent 类。
(1) 组件类
组件类的内存型 Webshell 主要是通过动态注册一个包含恶意代码的组件到运行内存中, 将恶意代
码长期驻留在内存中。常见的组件包括 Java Web 的三大组件, 分别为 Filter、Servlet、Listener。除此之外, 还包括特定框架和容器的特有组件, 例如 Spring框架的 Controller、Interceptor 组件, Tomcat 容器的Valve 组件等。
利用场景一般通过反序列化等漏洞直接注入恶意组件到内存, 或通过文件上传漏洞上传一个 JSP
文件(包含恶意组件注入程序), 执行后删除文件, 达到无文件 Webshell 的效果。该类型 Webshell 要求目标环境可以执行任意 Java 代码, 对目标环境依赖性较强, 通用性差。
其实现过程如图 2 所示。首先创建一个组件, 添加恶意逻辑到其中, 然后通过反序列化、代码执行等漏洞将注册组件代码执行, 注入到特定环境的目标应用程序中, 最后通过访问固定 URL 或带固定参数的 URL 来执行 Payload, 达到 Webshell 的特权状态。
(2) Agent 类
Agent 类的内存型 Webshell 主要是利用 JavaAgent 技术动态修改 JVM 中加载的类文件, 将恶意代码注入其中, 该类在磁盘上还是正常文件, 只有在运行内存中才会包含恶意代码, 达到无文件落地。
Agent 类的内存型 Webshell 也包括 premain 和agentmain 两种注入方式, 但是实际环境中, 目标应
用程序一般都是已启动状态, 只能使用 agentmain 的方式注入。利用场景通常是通过漏洞上传一个 Jar 文件, 执行成功后删除该文件。该类型 Webshell 在 Java虚拟机层操作, 通用性强。
其实现过程如图 3 所示。首先通过漏洞上传一个 Jar 包, 用于加载 Java Agent 程序, 将 Jar 包注入到目标程序运行内存后, 就可以删除该文件。然后通过访问固定 URL 或带固定参数的 URL, 恶意逻辑会利用 Agent 技术修改类字节码, 再执行 Payload, 达到Webshell 的特权状态。
(3) 两种类型异同组件类和Agent类的内存型Webshell, 相同之处都是利用漏洞将恶意程序注入目标程序内存中, 然后通过访问特定的请求连接 Webshell, 执行 Payload,达到各种控制服务器的特权状态的目的。
不同之处在于, 前者有创建并注册组件的动态过程, 新增了一个组件, 组件中包含恶意逻辑; 而后者是利用 Agent 技术直接修改 JVM 中已经存在的类的逻辑, 不产生新的类。
3.2 形式化定义
内存型 Webshell 是一种网站后门, 根据研究人员对后门的定义, 可以将后门分为输入源、触发器、攻击载荷、特权状态 4 个组件。本节从这 4 个组件出发, 结合内存型Webshell的原理, 对其进行形式化定义。
如图4所示, 目标程序中存在内存型Webshell(θ)可表示为:
θ = (S, i, e, t, Σ, p), i∈S 且 e∈S
S 表示目标程序的全部有限状态集合。I 表示输入源, 即初始状态集合, I S ⊆ 。E 表示内存型 Webshell触发后到达的特权状态集合, E S ⊆ 。t 表示状态转移函数, 也是触发器, 有 t(I, c) = S, c 表示状态转移条件。Σ 表示后门触发条件。p 为攻击载荷, 表示为达到特权状态而采用的有效代码。特别地, 当存在 i∈I, c = Σ, e∈E, 且攻击载荷 p 被执行, 使得 t(i, Σ) = e时, 表示后门被触发, 存在内存型 Webshell。n 表示后门没有被触发时的正常转移状态, n∈S。
输入源表示激活后门触发器的输入来源。内存型 Webshell 的输入源 I 包括:
(1)Java Web 组件, 例如servlet、filter、listener 等;
(2)Java 容器组件, 例如tomcat valve 组件、weblogic 的组件;
(3)Java 框架组件, Java的框架有很多, 包括spring、springboot等, 例如 spring 框架的 controller 组件;
(4)二进制, 例如Agent 类内存型 Webshell 的字节码。
3.3 威胁模型
内存型 Webshell 具有持久性、隐蔽性, 并且将在上节提到的 4 个组件中不断增强, 本节从攻击载荷、触发器两方面进行分析。
(1) 攻击载荷
目前公开的内存型 Webshell 样本基本都是明文的 Payload, 主要关注点在 Webshell 存在于内存中而非磁盘上, 过于关注输入源、触发器的状态, 而忽略了攻击载荷的形态。随着无文件检测技术的不断发展和提升, 内存型 Webshell 将会在 Payload 上做更多的变形。
(2) 触发器
我们假设攻击者在植入组件类高对抗内存型Webshell 时, 触发器的场景包括 1)通过反序列化漏洞等注入恶意字节码, 2)通过 RMI、LDAP 等远程方法调用恶意类, 3)通过文件上传等漏洞注入恶意 JSP
文件。前两种方式是无文件攻击, 目标应用程序的磁盘没有恶意文件落地, 但是也考虑攻击者故意写入磁盘文件的情况, 以绕过无文件这一特性。第三种方式的 JSP 文件在执行过程中, 会先被编译成 class 文件, 然后再执行程序, 即使执行完可以删除文件达到无文件攻击, 但动态检测是在执行过程中进行的,执行过程中不可避免的有文件落地。检测时需针对以上情况分别考虑。