完整教程:Towards the Detection of Malicious Java Packages论文梳理分析

论文《Towards the Detection of Malicious Java Packages》系统分析报告

一、论文概述

1.1 研究背景与意义

开源软件供应链攻击通过污染开源包感染下游用户,而Java 生态系统虽应用广泛,却是供应链攻击检测领域的研究薄弱点(对比 npm、PyPI 等生态的成熟方案)。现有 antivirus(AV)工具对恶意 Java 包的检测率极低(Maven Central 样本仅 3% 被识别),且恶意代码常以 “少量恶意代码隐藏在大量合法代码中” 的形式存在(类似 Android 恶意软件的 “搭便车” 模式),传统检测方法难以覆盖。

1.2 研究目标

依据静态分析 Java 字节码,解决两个核心研究问题(RQ):

  • RQ1:从字节码中可提取哪些 “容易且有效” 的恶意行为指标?
  • RQ2:这些指标及其组合在检测恶意 Java 包时的性能如何?

1.3 核心办法

以 Java 字节码为分析对象(因开发者常通过预编译 JAR 获取依赖),从两大维度设计检测指标:

  1. 常量池分析:提取字符串特征(如混淆字符串、敏感关键词);
  1. 字节码指令分析:识别敏感 API 调用、异常处理模式(空 catch 块)及恶意数据流。

通过 “人工注入恶意载荷” 的实验验证指标有效性(因 Java 恶意样本稀缺,仅 Backstabber’s Knife Collection(BKC)数据集有 4 个 Java 样本)。

二、关键理论基础与研究动机

2.1 理论基础

(1)Java 类文件格式

  • 字节码结构:1 字节操作码 + 0 / 多字节操作数,常量(如字符串、类名)存储于常量池(类似符号表);
  • 常量池索引机制:Utf8 类型存储字符串原始值,String、Class 等类型通过索引指向 Utf8(如图 1,#22 String指向#23 Utf8的 bash 命令字符串),是字符串提取的核心依据。

(2)恶意样本数据集(BKC)

  • 包含 2886 个开源恶意包,覆盖 Ruby(813)、Python(261)、JavaScript(1807),但Java 仅 4 个
  • 恶意行为分类(论文聚焦 5 类):

恶意类型

核心行为

反向 Shell

生成 Shell 进程,通过 socket 重定向输入输出到攻击者机器

载荷下载器(Dropper)

连接攻击者服务器下载二级载荷并执行

数据泄露

读取敏感文件 / 环境信息,发送至远程端点(最常见行为)

拒绝服务(DoS)

资源耗尽(如 fork 炸弹)或删除系统文件

非法获利

执行加密挖矿(论文归为数据泄露子类)

2.2 研究动机:现有检测能力不足

论文依据 VirusTotal 扫描 BKC 样本,验证 AV 工具对开源恶意包的检测率普遍偏低,Java 生态表现最差

生态系统

未检测(U)

检测为恶意(M)

类型不支持(TU)

分析失败(F)

超时(T)

RubyGems

60.4%

17.6%

21.1%

0.3%

0.6%

PyPI

76.0%

2.0%

21.3%

0.2%

0.5%

npm

77.1%

0.7%

21.3%

0.3%

0.5%

Maven Central

78.9%

3.0%

16.7%

0.3%

1.0%

此外,278 个恶意包已存在超 2 年、45 个超 5 年,仍未被 AV 识别,凸显静态检测手段的迫切需求。

三、核心检测指标设计(RQ1 解答)

论文从 “常量池” 和 “字节码指令” 两大维度,提炼出 6 类有效恶意指标,具体如下:

3.1 常量池分析:识别可疑字符串

恶意行为的关键线索,通过 3 种方法过滤无效信息、聚焦可疑字符串:就是常量池存储 Java 类的硬编码字符串(如命令、URL、材料路径),

分析方法

核心逻辑

优势

局限性

香农熵分析(Shannon Entropy)

混淆字符串(如 base64)熵值更高(例:bash熵 = 2,base64 编码YmFzaA==熵 = 2.75);取类级别第 3 四分位数为阈值(SHc),过滤低熵正常字符串

实用识别混淆内容

短字符串 / 小字符集(如 base16)熵值低,易漏检

语言过滤(LC)

用 Compact Language Detector 2(CLD2)检测字符串是否为自然语言(如日志),过滤自然语言字符串

排除正常日志 / 提示信息,支持多语言

含英文单词的 URL(如whatismyip.org)可能被误过滤

敏感关键词匹配

从攻击手册中整理 178 个关键词(如bash、/etc/passwd、http://),覆盖反向 Shell、资料泄露场景;协助多编码(base64/32/16)和反向(如hsab)

直接定位恶意行为相关字符串

需持续更新关键词库以覆盖新攻击手法

最优组合:SHc + LC + 敏感关键词,可减少 99.8% 的无效字符串,且不遗漏恶意线索(如 P1 的 base64 命令、P2 的恶意 URL)。

3.2 字节码指令分析:识别恶意行为模式

通过分析字节码指令,捕捉恶意代码的执行逻辑特征,核心指标包括:

(1)敏感 API 检测

基于 BKC 样本和 Java SE 文档,整理 6 类与恶意行为强相关的原生 API(如表 7),检测其调用情况(如invokespecial、invokevirtual指令):

API 类别

核心作用

示例 API

对应恶意行为

执行 API

运行 Shell 命令 / 脚本

Runtime.exec()、ProcessBuilder.start()

反向 Shell、挖矿

连接 API

建立网络连接

Socket()、URL.openConnection()

反向 Shell、Dropper 下载载荷

动态编程 API

运行时加载类 / 执行方法(反射)

ClassLoader.loadClass()、Method.invoke()

隐藏恶意代码执行逻辑

编码 / 加密 API

混淆恶意字符串

Base64.Decoder.decode()

规避 AV 检测

环境读取 API

获取系统信息(如环境变量、主机名)

System.getEnv()、InetAddress.getHostName()

数据泄露

文件 I/O API

读写本地材料

FileOutputStream.write()、Files.readAllBytes()

Dropper 存储载荷、数据泄露

注意:需结合库的功能特性判断 API 合法性(如h2database合法使用exec(),而mockito-core中出现exec()则为异常)。

(2)空 Catch 块检测

恶意代码常将核心逻辑放入try块,搭配空 Catch 块(不抛异常、不打印日志),避免执行失败时暴露痕迹(如 Listing 1 的恶意doGet方法)。

检测逻辑:先定位空 Catch 块,再检查其关联try块是否含有敏感 API 或可疑字符串,可减少 97% 的无效审查量(如 P1 和 P3 的空 Catch 块均被精准识别,P2 无空 Catch 块则不触发)。

(3)过程内数据流分析

依据 ASM 程序模拟 JVM 栈,追踪敏感 API 的输入参数来源,验证是否为常量池中的可疑字符串(如Runtime.exec()的参数是否为 base64 命令)。

优势:覆盖无空 Catch 块的恶意代码(如 P2),可减少 73%-75% 的无效线索;局限:仅支持过程内分析(恶意载荷分散在多方式时失效)。

四、实验设计与结果(RQ2 解答)

4.1 实验 setup

  1. 实验对象:从选取 Top10 热门 Java 库(如 junit、guava、spring-core、lombok);
  1. 恶意载荷注入:将 3 个源自 BKC 的恶意逻辑(P1-P3)编译为字节码,随机注入库的类方法中,生成 30 个感染版本(10 库 ×3 载荷),加 10 个原始版本共 40 个样本;

载荷

核心行为

空 Catch 块

敏感 API 类型

P1

Runtime.exec()执行 base64 解码的 bash 命令

执行 API、编码 API

P2

反射加载远程恶意类()

动态编程 API、连接 API

P3

下载 Groovy 脚本()并执行

连接 API、文件 I/O API、执行 API

  1. 评估指标:precision(精准度)、recall(召回率)、balanced accuracy(平衡准确率)。

4.2 关键实验结果

(1)常量池过滤性能

不同过滤组合对恶意字符串的识别能力对比(以 30 个感染样本平均数据为例):

过滤组合

P1(1 个恶意字符串)

P2(3 个恶意字符串)

P3(2 个恶意字符串)

核心结论

仅 LC

P=0.003, R=1.0

P=0.006, R=0.667

P=0.006, R=1.0

召回率高但精准度极低

仅 SHc

P=0.013, R=1.0

P=0.013, R=0.333

P=0.013, R=0.5

精准度提升,但 P2 漏检严重

SHc + KL(阈值 10)

P=0.239, R=1.0

P=0.239, R=0.5

P=0.239, R=0.5

精准度提升,但 P2 的 URL 被误过滤

SHc + LC

P=0.453, R=1.0

P=0.453, R=0.5

P=0.453, R=0.5

平衡精准度与召回率,最优基础组合

SHc + LC + 关键词

P=0.999, R=1.0

P=0.664, R=0.5

P=0.748, R=0.5

精准度大幅提升,P2 仍漏检 1 个 URL

结论:SHc + LC + 敏感关键词是常量池分析的最优方案,可高效定位恶意字符串。

(2)字节码指标性能

  1. 敏感 API 检测
    • 原始库中存在少量合法敏感 API(如h2database含exec()),需结合库功能判断;
    • 感染样本中,P1 新增执行 API、P2 新增动态编程 API、P3 新增资料 I/O API,均能被识别,但需排除合法 API 干扰(如mockito-core原始版本含 68 个敏感 API,需进一步过滤)。
  1. 空 Catch 块 + 敏感 API
    • 对 P1 和 P3(有空 Catch 块),仅需审查 2%-3% 的try块即可定位恶意代码(rf=97%-98%),且召回率 100%;
    • 对 P2(无空 Catch 块)无效,需结合数据流分析。
  1. 数据流分析
    • 覆盖 P2 等无空 Catch 块的场景,可减少 73%-75% 的无效线索(如 P2 的反射 API 输入参数被验证为恶意 URL);
    • 过程内分析局限:若恶意载荷分散在多方法(如参数传递),则无法追踪。

(3)综合指标性能

最优检测流程

  1. 常量池过滤(SHc + LC + 关键词)→ 定位可疑字符串;
  1. 字节码检测(空 Catch 块 + 敏感 API)→ 筛选高风险try块;
  1. 数据流分析 → 验证敏感 API 输入是否为可疑字符串。

该流程对 P1 和 P3 的召回率 100%,精准度超 95%;对 P2 的召回率 50%(漏检 1 个 URL),精准度 66.4%,可支持人工审查(需审查的线索减少 99% 以上)。

五、研究局限性

  1. 静态分析固有局限:无法检测动态生成的恶意代码(如运行时拼接命令),且恶意行为判定属于 “不可判定问题”,必然存在误报;
  1. 恶意类型覆盖不足:仅聚焦反向 Shell、Dropper 等 5 类行为,未覆盖 “隐藏凭证”“删除安全检查” 等攻击;
  1. 数据流分析局限:仅支持过程内分析,无法追踪跨方法的恶意载荷传递;
  1. 字符串熵分析局限:短字符串(如bash)或小字符集(如 base16)的熵值低,易漏检;
  1. 样本稀缺:依赖人工注入载荷,真实 Java 恶意样本(仅 4 个)不足,实验结果的泛化性需验证。

六、结论与未来工作

6.1 核心结论

  1. 有效指标
    • 常量池:SHc(类级别香农熵) + LC(语言过滤) + 敏感关键词可高效筛选恶意字符串;
    • 字节码:空 Catch 块结合敏感 API 可大幅减少审查量,数据流分析覆盖无空 Catch 块场景。
  1. 实用价值:可将指标集成到包仓库(如 Maven Central)的 vetting 流程,或下游用户的依赖检查程序,支撑 “自动化初筛 + 人工审查” 的高效检测模式。

6.2 未来工作

  1. 扩展数据流分析至过程间追踪,覆盖跨办法的恶意载荷;
  1. 分析 Maven Central 生态的 API 应用规律,建立 “正常 API 调用基线”,通过异常检测识别恶意;
  1. 基于本文指标构建机器学习分类模型(如异常检测),解决 Java 恶意样本稀缺问题;
  1. 扩展关键词库和敏感 API 库,覆盖新型攻击手法(如 Log4j 漏洞相关的恶意调用)。

七、综合应用建议与延伸洞察

7.1 实际检测流程建议(面向包仓库 / 企业)

阶段

核心操作

工具支撑

目标

1. 预筛选

对上传 JAR 进行常量池分析(SHc + LC + 关键词),标记含可疑字符串的包

自定义 ASM 插件

排除 99% 以上无风险包

2. 深度检测

对预筛选包进行字节码分析:1)定位空 Catch 块 + 敏感 API;2)数据流验证敏感 API 输入

ASM(字节码解析)+ 数据流引擎

定位高风险代码块

3. 人工审查

仅审查深度检测标记的代码块(通常 < 1%),结合库功能判断是否为恶意

代码审查工具(如 JD-GUI)

最终确认恶意行为

7.2 与其他生态检测方法的差异

Java 生态的检测需重点关注 “字节码层面的静态分析”,与其他生态形成鲜明对比:

生态

主流检测方法

Java 生态差异点

npm/PyPI

对比源码与包的差异(如 LastPyMile)

开发者常使用预编译 JAR,源码不可得

JavaScript

AST 分析 + 动态沙箱(如 Ohm et al.)

Java 字节码需结合常量池特性,静态分析更高效

Android

Dalvik 字节码 + 权限分析

Java 库无权限机制,需聚焦 API 和字符串

7.3 研究不足的补充思考

  1. 样本泛化性:人工注入的载荷可能无法完全模拟真实攻击(如真实攻击可能更隐蔽,如通过配置文件加载恶意字符串),未来需联合安全厂商积累真实 Java 恶意样本;
  1. 误报处理:部分合法场景可能触发指标(如日志框架含http://关键词、工具类含Base64解码),需结合 “库功能画像”(如logback含http关键词属正常)降低误报;
  1. 性能优化:常量池分析和数据流分析对大型 JAR(如 spring-core)可能耗时较长,需优化字节码解析效率(如增量分析仅变更类)。

posted @ 2025-10-25 21:20  ycfenxi  阅读(1)  评论(0)    收藏  举报