完整教程: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 获取依赖),从两大维度设计检测指标:
- 常量池分析:提取字符串特征(如混淆字符串、敏感关键词);
- 字节码指令分析:识别敏感 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
- 实验对象:从选取 Top10 热门 Java 库(如 junit、guava、spring-core、lombok);
- 恶意载荷注入:将 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 |
- 评估指标: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)字节码指标性能
- 敏感 API 检测:
- 原始库中存在少量合法敏感 API(如h2database含exec()),需结合库功能判断;
- 感染样本中,P1 新增执行 API、P2 新增动态编程 API、P3 新增资料 I/O API,均能被识别,但需排除合法 API 干扰(如mockito-core原始版本含 68 个敏感 API,需进一步过滤)。
- 空 Catch 块 + 敏感 API:
- 对 P1 和 P3(有空 Catch 块),仅需审查 2%-3% 的try块即可定位恶意代码(rf=97%-98%),且召回率 100%;
- 对 P2(无空 Catch 块)无效,需结合数据流分析。
- 数据流分析:
- 覆盖 P2 等无空 Catch 块的场景,可减少 73%-75% 的无效线索(如 P2 的反射 API 输入参数被验证为恶意 URL);
- 过程内分析局限:若恶意载荷分散在多方法(如参数传递),则无法追踪。
(3)综合指标性能
最优检测流程:
- 常量池过滤(SHc + LC + 关键词)→ 定位可疑字符串;
- 字节码检测(空 Catch 块 + 敏感 API)→ 筛选高风险try块;
- 数据流分析 → 验证敏感 API 输入是否为可疑字符串。
该流程对 P1 和 P3 的召回率 100%,精准度超 95%;对 P2 的召回率 50%(漏检 1 个 URL),精准度 66.4%,可支持人工审查(需审查的线索减少 99% 以上)。
五、研究局限性
- 静态分析固有局限:无法检测动态生成的恶意代码(如运行时拼接命令),且恶意行为判定属于 “不可判定问题”,必然存在误报;
- 恶意类型覆盖不足:仅聚焦反向 Shell、Dropper 等 5 类行为,未覆盖 “隐藏凭证”“删除安全检查” 等攻击;
- 数据流分析局限:仅支持过程内分析,无法追踪跨方法的恶意载荷传递;
- 字符串熵分析局限:短字符串(如bash)或小字符集(如 base16)的熵值低,易漏检;
- 样本稀缺:依赖人工注入载荷,真实 Java 恶意样本(仅 4 个)不足,实验结果的泛化性需验证。
六、结论与未来工作
6.1 核心结论
- 有效指标:
- 常量池:SHc(类级别香农熵) + LC(语言过滤) + 敏感关键词可高效筛选恶意字符串;
- 字节码:空 Catch 块结合敏感 API 可大幅减少审查量,数据流分析覆盖无空 Catch 块场景。
- 实用价值:可将指标集成到包仓库(如 Maven Central)的 vetting 流程,或下游用户的依赖检查程序,支撑 “自动化初筛 + 人工审查” 的高效检测模式。
6.2 未来工作
- 扩展数据流分析至过程间追踪,覆盖跨办法的恶意载荷;
- 分析 Maven Central 生态的 API 应用规律,建立 “正常 API 调用基线”,通过异常检测识别恶意;
- 基于本文指标构建机器学习分类模型(如异常检测),解决 Java 恶意样本稀缺问题;
- 扩展关键词库和敏感 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 研究不足的补充思考
- 样本泛化性:人工注入的载荷可能无法完全模拟真实攻击(如真实攻击可能更隐蔽,如通过配置文件加载恶意字符串),未来需联合安全厂商积累真实 Java 恶意样本;
- 误报处理:部分合法场景可能触发指标(如日志框架含http://关键词、工具类含Base64解码),需结合 “库功能画像”(如logback含http关键词属正常)降低误报;
- 性能优化:常量池分析和数据流分析对大型 JAR(如 spring-core)可能耗时较长,需优化字节码解析效率(如增量分析仅变更类)。
浙公网安备 33010602011771号