刘向伟 张晓娇 宋金金
作者简介:刘向伟(1993— ),男,浙江嘉兴人,工程师,学士;研究方向:网络安全。
摘要:随着互联网的发展,恶意软件逐渐成为威胁网络安全的重要因素。而 Java 内存马作为一种内存驻留的恶意软件,不仅具有隐蔽性高、易于传播等特点,还能够利用一些 Java 的高级特性实现更复杂的攻击行为,给网络安全带来更大的威胁。文章提出了一种基于 YARA的Java内存马检测方案,通过向JVM中注入Agent将高风险类导出并通过YARA实现对Java内存中的恶意代码的检测和定位,再对该方法进行了实验验证。实验结果表明,该方案能够有效地检测Java内存马,具有较高的检测准确率和较低的误报率。
关键词:Java 内存马;YARA;恶意软件;检测方法
中图分类号:TP399 文献标志码:A
0 引言
Java是一种跨平台的编程语言,因其安全性、易用性和可移植性而广泛应用于网络应用程序的开发[1]。然而,随着Java应用程序的不断发展,内存马成为网络攻击的一种常见手段。内存马可以通过修改Java虚拟机(JVM)内存中的字节码来实现程序的恶意行为,例如,窃取敏感信息、扫描网络端口、占有服务器资源挖矿等。传统的基于落地文件的检测已经难以应对,因此针对注入内存中的恶意代码可行性检测方案的研究变得越来越重要。
1 Java内存马方案设计
1.1 Java 内存马检测需求分析
本方案设计之初笔者查询了大量的现有方案,希望该方案可落地、可实现。同时,在查杀种类上能尽可能覆盖所有Java内存马种类与攻击路径;在误报率上可以做到较少误报,甚至是零误报;在性能上,作为一个安全类的检测方案,不会占用太多的服务器资源,将对系统性能造成的影响降到最低;同时,在内存马攻击侧热度不减的当下,不断有新攻击手段与利用类的更新,希望该方案是可扩展的。
为了达到全面性、低误报、低占用、可扩展的目标,笔者分别对Java内存马的种类及攻击路径做出分析,对内存的提取思路做出优化,对内存马检出的判断体系做出选取,最终形成了一套明晰的检测流程与方案。
1.2 Java内存马的种类及攻击路径分析
常见的Java内存马在实现方式技术上可以划分为以下3种类型,每种类型的实现原理:(1)基于Java Servlet规范利用的内存马实现技术。该类型主要是利用了Java Servlet 3.0+规范,通过对Servlet,Filter,Listener组件的注册来实现[2]。(2)基于特定Java 框架利用的内存马实现技术。利用Java 框架的技术规范(如,Spring MVC框架),动态注册框架的组件来实现。(3)基于Java api接口类型的内存马实现技术。利用Java Agent技术或是JavaSsist技术通过修改JVM中加载类的字节码的特性来实现。
上述的Java内存马实现的攻击路径主要体现在两种形式:(1)通过落地文件将木马注入内存。这种形式下黑客往往通过常见漏洞上传或写入恶意文件从而获取系统权限,为了更好地隐藏自己不被安全检测工具发现以及稳定地维持访问,将木马代码注入内存中[3]。(2)通过漏洞攻击直接将木马注入内存。攻击者通过反序列化等相关漏洞直接利用写入的木马注入内存当中,这种形式下往往无落地文件产生。
通过对常见的Java内存马的种类分析可以明确查杀种类,做到检测与查杀的全面性。同时,对内存马的攻击路径进行分析可以发现,常见的木马检测针对的落地文件,在内存马查杀方面效果不大,需要将查杀的重点放在程序运行时内存上。
1.3 可疑内存提取思路
本次方案对内存提取采用了Java Agent技术来实现,Java Agent技术不单单可以作为内存马的实现,还可以被用来检测内存马。通过跟踪Java进程PID,遍历JVM中所有加载的类并导出为内存中的字节码来实现内存的提取。出于性能方面的考虑,通过对现有内存马技术利用类和方法进行分类总结,在此只对可疑类进行导出。
具体实现步骤如下:(1)遍历系统中运行的JVM进程,将Agent注入对应的进程中;(2)遍历 JVM中所有加载的类,将所有的高风险类在内存中的字节码DUMP出来。
1.4 YARA判别
为了满足对恶意代码鉴别方案的可扩展性,本文选取了YARA引擎进行恶意代码的判别。YARA 是一个旨在(但不限于)帮助恶意软件研究人员识别和分类恶意软件样本的工具。目前,使用 YARA 的知名软件有赛门铁克、火眼、卡巴斯基、McAfee、VirusTotal 等。本文采用Java动态加载YARA方式实现规则判断,可以轻松地集成开源规则库。此外,YARA的规则编写非常简单,可以轻松地编写出一条想要的规则,如根据上面提到的Java内存马的特征分析和提取方法,可以編写相应的YARA规则来检测Java内存马。以下是一个简单的YARA内存马检测规则示例:
rule Java_Memory_Malware
{
meta:
author = "XXX"
description = "Detect Java memory malware"
strings:
$class_name = "Java/lang/reflect/Method"
$method_name = "invoke"
$parameter_types = "Java/lang/Object;[LJava/lang/Object;"
condition:
all of them
}
上述YARA规则是一个非常典型的检测Java内存马的示例规则,它检测使用反射调用Method.invoke()方法的恶意代码。具体解释为,(1)rule Java_Memory_Malware:规则名称用于识别匹配的规则。(2)meta:author = “XXX”,description = “Detect Java memory malware”:规则的元数据,包括作者和描述信息等。(3)strings:字符串匹配部分,定义需要匹配的字符串,包括class_name,method_name和parameter_types。(4)condition: all of them:规则的匹配条件,所有的字符串都必须匹配才能触发规则。
此外,YARA还支持自定义函数、变量和操作符,可以将多个特征组合成一个复杂的匹配规则。YARA还提供了多种修饰符,可以调整匹配的方式和结果。
1.5 整体方案
本文确立一条明晰的检出流程,如图1所示。首先,通过检索主机JVM进程并对指定进程进行选择;其次,将Agent注入指定JVM进程中对Class进行遍历,查找到高风险类将内存中的字节码Dump到本地;最后,引入YARA引擎对保存在本地的字节码匹配和判定并进行结果汇总。检出全流程可分解为开发中的重要模块:(1)Java进程扫描模块。用于扫描当前系统中运行的Java进程,获取Java进程的PID和内存信息。(2)Java进程注入模块。用于将Agent注入指定Java中。(3)Agent提取模块。用于遍历Class并进行高风险类的Dump。(4)YARA规则加载模块。用于加载YARA规则文件,将规则文件中的规则编译为可用的规则对象。(5)规则匹配模块。用于将内存信息和YARA规则进行匹配,识别是否存在Java内存马。(6)报告生成模块。用于生成检测报告,包括检测结果、恶意代码位置等信息。
2 程序重点模块的实现
2.1 Java进程扫描模块与注入模块
可跟踪获取Java进程的PID,如存在多项,通过大小,命名的方式做简单区分后将指定JVM的PID赋值给jvm_pid参数,然后将Agent.jar注入进程中去。具体实现代码如下:
public static void attach(String jvm_pid, String agent_jar_path) throws Exception {
VirtualMachine virtualMachine = null;
VirtualMachineDescriptor virtualMachineDescriptor = null;
for (VirtualMachineDescriptor descriptor : VirtualMachine.list()) {
String pid = descriptor.id();
if (pid.equals(jvm_pid)) {
virtualMachineDescriptor = descriptor;
break;
}}
try {
if (null == virtualMachineDescriptor) {
virtualMachine = VirtualMachine.attach(jvm_pid);
} else {
virtualMachine = VirtualMachine.attach(virtualMachineDescriptor);
}
Properties targetSystemProperties = virtualMachine.getSystemProperties();
virtualMachine.loadAgent(agent_jar_path);
通过VirtualMachine类的attach(pid)方法,便可以attach到一个运行中的Java进程上,之后便可以通过loadAgent(agentJarPath)来将agent的jar包注入对应的进程,然后对应的进程会调用agentmain方法。
2.2 Agent模块
Agent模块的主要作用遍历Class类并找到定义的危险类和接口。可以定义出一套黑客常调用的数据类型。如riskInterface.add(“Javax.servlet.Servlet”),遍历相关类找到上述可疑名单并将其保存,实现代码如下:
for (String inter : riskInterface) {
if (interfaces.contains(inter)) {
resultClasses.add(clazz);
break;}}
最后,通过ClassUtils.dumpClass(ins,resultClasses)将字节码检出。
2.3 YARA规则加载模块
YARA规则加载模块的主要作用是将YARA规则文件加载到程序中,将规则编译为可用的规则对象。在Java中可以使用YARA-Java库来实现YARA规则的加载和编译。具体实现代码如下:
import com.github.plusvic.yara.*;
public class RuleLoader {
private YaraCompiler compiler;
private YaraRules rules;
public RuleLoader(String rulePath) {
compiler = new YaraCompiler();
compiler.addRulesFile(rulePath);
rules = compiler.createRules();}
public YaraRules getRules() {
return rules;}}
上述代碼中,RuleLoader类用于加载YARA规则文件,并将规则编译为可用的规则对象。构造函数中,通过传入规则文件路径来加载规则文件,使用YaraCompiler对象将规则文件编译为可用的规则对象,然后通过getRules()方法获取规则对象。
2.4 規则匹配模块
在Java中可以使用YARA库来实现YARA规则的匹配,具体实现代码如下:
import com.github.plusvic.yara.YaraCompiler;
import com.github.plusvic.yara.YaraMatch;
public class RuleMatcher {
public static void match(resultClasses, String ruleFilePath) throws Exception {
YaraCompiler compiler = new YaraCompiler();
compiler.addFile(ruleFilePath);
compiler.load();
YaraScanner scanner = compiler.createScanner();
for (CodeInfo codeInfo : resultClasses.getCodeInfoList()) {
List
for (YaraMatch match : matches) {
process.addMatchInfo(match.getRule().getIdentifier(), codeInfo.getClassName(), codeInfo.getMethodName(),
codeInfo.getSignature(), codeInfo.getMd5(), match.getOffset(), match.getLength());}}}}
上述代码中,RuleMatcher类用于将内存信息和YARA规则进行匹配,识别是否存在Java内存马。首先,使用YaraCompiler对象编译YARA规则文件;其次,创建YaraScanner对象;最后,遍历resultClasses对象中的CodeInfo列表,使用YaraScanner对象进行匹配,获取匹配信息。
3 测试与结果
为了验证所提出的基于YARA的Java内存马检测方案的有效性和准确性,本文设计了一组实验,使用一组包含Java内存马的样本集进行测试。实验包括以下步骤:
3.1 获取Java内存马样本集
本方案从公开的样本库中获取了一组Java内存马样本集,包括20个不同的样本,这些样本使用不同的混淆技术、攻击路径以及加载方式以此来判断该方案的全面性。分别部署在不同的3组Java容器中,且分别部署了开源的Web系统,以模拟真实世界中的Java内存马,以此来判定其误报率。
3.2 设计YARA规则
本文设计了一组YARA规则,用于检测Java内存马中常见的特征。这些规则包括检测Java类名、方法名、字节码序列、代码签名等特征。笔者使用YARA语言编写这些规则,并将其保存在规则文件中。
3.3 进行实验测试
本方案使用收集的Java内存马样本集对检测工具进行测试,以评估其准确性和性能。笔者记录了检测工具的检测结果,包括每个样本的匹配结果、匹配时间等信息;比较了该检测工具与现有的Java内存马检测工具的性能和准确性。
3.4 实验结果
本文提出的基于YARA的Java内存马检测方法具有较高的准确性和良好的性能,如表1所示。在测试集中,该检测工具成功检测出了所有的Java内存马样本,同时没有发生误报。相对现有的Java内存马检测工具来说,具有更高的实用性和应用价值。
4 结语
本文提出了一种基于YARA的Java内存马检测方法,该方法可以在运行时对Java进程中的内存信息进行扫描,并使用预定义的YARA规则进行匹配,以检测是否存在Java内存马。实验结果显示,该方法具有较高的准确性、良好的性能和可扩展性。未来笔者将进一步改进方法提高准确性和性能,并将其应用于实际的恶意代码检测和安全防御中。未来工作的方向包括但不限于以下几个方面。(1)优化算法性能:尽管采用多种技术手段优化算法性能,但仍有可能出现性能瓶颈。因此,笔者将继续研究如何进一步提高算法性能,以确保检测系统的高效稳定运行。(2)支持更多的内存马类型:目前,该检测系统只能检测到Java内存马攻击。但随着网络攻击技术的不断发展和演进,还有许多其他类型的内存马攻击。因此,笔者将研究如何支持更多类型的内存马攻击,并不断更新和完善检测系统。(3)实现自动化检测:笔者希望能够在不影响程序性能的同时实现一套自动化检测系统,能够自动检测Java应用程序中的内存马攻击,并实现实时监测和告警。这将使得Java应用程序的安全检测更加便捷和高效。
总之,Java内存马检测是一个充满挑战的领域,需要不断地研究和探索,以实现更加高效、准确、稳定的检测方案。相信在不久的将来,Java内存马检测技术将得到进一步的发展和完善,为Java应用程序的安全提供更加全面的保障。
参考文献
[1]陈强.精通Java开发技术[M].北京:清华大学出版社,2014.
[2]孟正,梅瑞,张涛,等.Linux下基于SVM分类器的WebShell检测方法研究[J].信息网络安全,2014(5):5-9.
[3]朱魏魏,胡勇.基于NN-SVM的Webshell检测方法[J].通信与信息技术,2015(2):55-58.
(编辑 姚 鑫)
Abstract: With the development of the Internet, malware has gradually become an important factor threatening network security. As a type of memory-resident malware, Java memory-resident malware not only has high concealment and ease of propagation, but also can use some advanced features of Java to implement more complex attack behaviors, posing greater threats to network security. This paper proposes a YARA-based method for detecting Java memory-resident malware, which defines some feature strings and regular expression rules to detect and locate malicious code in Java memory, and verifies the method through experiments. The experimental results show that the method can effectively detect Java memory-resident malware with high detection accuracy and low false positive rate.
Key words: Java memory-resident malware; YARA; malware; detection method