小研究 - JVM 逃逸技术与 JRE 漏洞挖掘研究(二)

news2024/9/28 3:26:59

Java语言是最为流行的面向对象编程语言之一, Java运行时环境(JRE)拥有着非常大的用户群,其安全问题十分重要。近年来,由JRE漏洞引发的JVM逃逸攻击事件不断增多,对个人计算机安全造成了极大的威胁。研究JRE安全机制、JRE漏洞及其挖掘、JVM逃逸攻防技术逐渐成为软件安全领域的热门研究方向。

针对Java层API与原生层API, JRE安全机制分别包括JRE沙箱与JVM 类型安全机制。本文针对JRE沙箱组件及其工作原理进行剖析,总结其脆弱点;分析调研JVM安全机制,提出其脆弱点在于Java原生层漏洞,为JRE漏洞挖掘工作提供理论基础。

对于JRE漏洞,本文进行漏洞分类研究,提取Java API设计缺陷、Java原生层漏洞两种JRE漏洞类型的典型漏洞进行分析,总结漏洞特征,为漏洞挖掘工作建立漏洞模型。

根据JRE漏洞分析中建立的漏洞模型,本文采用源代码审计的方法开展Java API设计缺陷类型的漏洞挖掘工作,发现了数个Oracle JRE、OpenJDK和Apple JRE 的 Java API 设计缺陷问题。在 Java原生层漏洞挖掘工作中,出于Java原生层漏洞的特殊性,本文基于程序分析领域的符号执行技术提出一种寄存器符号化监控方法,选取开源符号执行平台S2E作为漏洞挖掘工具,并且基于其实现了针对JRE原生层漏洞挖掘的辅助插件 SymJava 和 SymRegMonitor,基于 OpenJDK 和 Oracle JRE逆向代码进行源代码白盒审计并构建了用于进行漏洞挖掘的 Java 测试用例,最后对36个调用Java原生层API的Java测试用例进行实际测试发现了共计6 个 JRE原生层安全隐患,其中2 个可被攻击者恶意利用,并给出漏洞分析和 PoC。

针对 JVM 逃逸攻防问题,本文分别从攻击和防御角度,提出 JVM逃逸攻击的5 个关键元素,针对每个元素进行攻防技术研究,并通过绕过杀毒软件静态检测的实验证明了本文提出的 JVM 逃逸攻击技术。最后,本文从多角度给出JVM逃逸攻击的防御策略。

目录

2  Java 安全机制研究

2.1  JRE 沙箱组件研究

2.1.1  类装载器

2.1.2  安全管理器

2.1.3  权限提升代码块

2.1.4  Java 反射机制

2.2  JVM 安全机制研究

2.3  本章小结


2  Java 安全机制研究

为了更好地进行JRE漏洞分析与挖掘工作,更好地理解JVM逃逸攻击的流程,探究Java的安全机制就显得至关重要。以Oracle JRE为例, Java API分为Java层和原生层,其中Java层由Java语言本身编写,原生层主要由C语言编写,是一些与操作系统接合较为紧密的底层API封装,在Windows系统中编译为动态链接库("*.dll”文件),作为JRE的重要组成部分而存在。Java层中存在着可以自定义安全规则的沙箱(Sandbox),在分析JRE漏洞和进行漏洞挖掘工作之前,探究沙箱组件以及原理显得极为重要。原生层由于跟操作系统接合紧密,且由C语言编写,所以会存在如缓冲区溢出、整数溢出等二进制层面的漏洞。针对JRE原生层,本章重点研究原生层API调用机制, JVM的安全特性,以及原生层潜在安全问题等等。

2.1  JRE 沙箱组件研究

Java应用程序大多为本地应用,即部署于本地操作系统上,由本地JRE加载并执行的Java应用程序。本地应用程序拥有JRE的最高权限,可以对本地操作系统的大部分资源进行控制和操作,如执行shell/cmd 命令等。所下图示是一段在Windows下执行cmd命令的Java本地应用程序,其执行效果是打开Windows系统自带的计算器程序calc.exe。

import java.io.IOException;
public class Example1 {
    public static void main(String[] args) {
        try {
            Runtime.getRuntime().exec("calc.exe");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

核心代码原封不动地迁移到 Applet 程序开发中,如下所示。使用 html 页加载该 Java Applet,发现 Windows 计算器并没有被打开,也就意味着 cmd 命令执行失败,此时打开JRE的控制台,可以看到带有“access denied”字样的异常信息,提示权限检查未通过。

import java.applet.Applet;
import java.io.IOException;

public class Example2 extends Applet{
    public void init() {
        try {
            Runtime.getRuntime().exec("calc.exe");
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
}

由图2-1的方框标示部分可知, JRE限制了本地文件的“可执行” (execute)权限,这是与执行本地Java应用完全不同的一种安全策略。在JRE中,由众多安全组件组成的系统称为JRE沙箱(JRE Sandbox),负责限制类似Applet这样来自互联网的不可信Java程序在执行中的权限。

自互联网的Java Applet下载到本地JRE中加载执行时,会判断该Applet是否可信(如是否具备可信的数字签名,等等),若可信,则该Applet可以执行任意代码,接触到操作系统中的所有可获取的资源;若不可信,则只能在沙箱中以较低的权限执行,且不能任意获取操作系统的本地资源。
JRE沙箱限制非可信Applet获取的权限有很多,与安全相关性较大的主要有以下几种:

1.本地文件操作。本地文件读取、写入,可执行文件的执行权限的限制。

2. 网络连接操作。建立自定义socket通信,发起自定义的http请求,等等。

3.系统属性读取。禁止使用读取系统属性的API,如System.getProperty.

4.加载动态链接库。禁止使用加载外部动态链接库的API,如System.loadLibrary

JRE沙箱的存在一定程度上提高了JRE的安全性,但由于JRE漏洞的存在,攻击者可以利用JRE漏洞突破沙箱,在目标计算机上执行恶意代码。因此无论攻击者还是防御者,都必须探究JRE沙箱的安全机制及其安全相关组件。下文分小节介绍本文对JRE沙箱各安全相关组件的研究。

2.1.1  类装载器

首先探究JVM 加载运行 Java 程序的过程。Java 不是一门像 Python 那样的纯解释型语言, JVM可以加载执行的是一段字节码,也就是后缀名为class的文件。class文件是一组以字节为基础单位的二进制流,其内容主要包括:Magic Number(文件开头4字节,必须为OxCAFEBABE),版本号,常量池,访问标志,字段表,方法表,属性表等等。各个数据项严格按照顺序紧凑地排列在class文件之中,中间没有添加任何分割符,使得整个 class 文件中存储内容几乎全部都是程序运行的必要数据。

这样一个class文件,从被加载到JVM中开始直到卸载,其生命周期要经过七个阶段:加载、验证、准备、解析、初始化、使用、卸载。那么顾名思义,从安全角度来考虑, class文件的加载和校验环节是比较重要的。一般来说,只要顺利通过了这两个环节,一个 class 直到它运行之前都不会有安全检查了。

类的加载是由Classloader来完成的,以Hotspot虚拟机为例(最常见的一种Java 虚拟机), Classloader可划分为两大类:第一类是 Bootstrap Classloader,是由C++语言实现的;第二类则独立于Java虚拟机之外,且全部继承自抽象类java.lang.Classloader,也就是说,它们全部都是由Java语言实现的。

在类加载的过程中还涉及到一个命名空间的问题。以Oracle官方的JRE为例,除第三方扩展包以外,所有的Java API都存在于<JAVA_HOME>Vlibirt.jar这个压缩包里。

以Java语言中常见的java.lang.System类来举例,如果开发者自己创建一个名叫"System"的类,如表2-3所示:

注意这个类是属于自定义的 test 包中,类中同样有一个 out 对象,一个静态的println方法,可以注意到,在自定义的printn方法中实际上调用的还是方法java.lang.System.out.println。再创建一个类去调用test.System类,如表2-4所示。

编译、运行,控制台输出:

helloworld!

My System Class:helloworld!

可见即使类名相同,命名空间(也就是包名)的不同也就保障了不会引起Java类混淆。但若是开发者自己定义一个java.lang.System类如何呢?把上面定义的test.System类改为java.lang.System,同样运行Example3,发现控制台输出了异常信息, 自己定义的java.lang.System类不会得到调用。这种手段可以在很大程度上防止Java虚拟机加载恶意的混淆类,但值得一提的是,任何一个类一旦由Bootstrap Classloader加载,那么它将拥有Java API级别的权限,完全被Java虚拟机所信任。从攻击者的角度讲,寻找可以调用Bootstrap Classloader的脆弱点是一个很好的利用思路。
Class文件的验证过程同样也是保障Java虚拟机安全的一个重要环节。验证环节主要有四个步骤,分别是:文件格式验证、类型数据语义检查、字节码验证和符号引用验证,其顺序如图6所示。

2.1.2  安全管理器

安全管理器即JRE中的SecurityManager,通俗来讲,其功能是当调用Java API进行一些“不安全”操作(如本地文件读写,网络通信,系统属性读取等等)时,SecurityManager会被调用,来执行一些相关的权限检查。如果执行“不安全”操作的这次调用拥有相应的权限,那么它将会实际执行这个操作;如果没有执行这些操作的权限, Java主进程会抛出异常,终止该行为。

public static void setSecurityManager(final SecurityManager s) {
    setSecurityManager0(s);
}
private static synchronized void setSecurityManager0(final SecurityManager s) {
    SecurityManager sm = getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new RuntimePermission ("setSecurityManager"));
    }
    if ((s != null) && (s.getClass().getClassLoader() != null)) {
        ……
    }
    security = s;
}
2.1.3  权限提升代码块

在Java 6与Java 7当中,权限检查的工作交给了AccessController类,每当触发权限检查时, AccessController会对方法调用栈上的所有方法进行检查。所谓方法调用栈,可以参考本章的图2-1,控制台打印的异常信息就恰好反馈了异常方法的部分调用栈。以表2-2中的Applet类Example2为例,调用栈的顶端是AccessController.checkPermission方法,该方法会自顶向下地检查整个调用栈上的类和方法是否都是受信任的,一旦发现有一个不受信任的方法调用,JVM就会抛出异常,程序终止执行。

AccessController.doPrivileged(new PrivilegedAction<SomeClass>() {
        public SomeClass run() {
            try {
                …… // Some dangerous function
            } catch (SecurityException e) {
                assert false;
            } catch (NoSuchFieldException e) {
                assert false;
            }
            return null;
        }//run
});
2.1.4  Java 反射机制

Java反射机制(Reflection)是Java程序开发语言的重要特性,它为Java提供了在运行过程中动态获取及调用一个类及其方法和变量的功能,从编程的表现形式来讲,可以理解为通过间接的方式去调用一些API。一般来说,要调用一个类的某个方法,先要使用new关键字创建一个对象出来,此时JVM完全知晓这个对象是什么类的对象;而通过反射机制,在真正执行这个方法前,可以不用声明这个对象, JVM会自动匹配这个方法的全限定名,并定位到它所在的类。以上文中提到的System.setSecurityManager方法,是一个静态方法,直接调用代码是:

System.setSecurityManager(null);

 

由表2-8 可知,java.lang.Class 类中的反射 API 可以获取到一个类的所有关键元素:类对象本身、所有定义的方法(无论公有私有)、构造函数、所有定义的公有私有域(也就是该类的全局变量)。这些 API 还只能获取到这些元素,另外,java.lang.reflect包中对应有Field、Constructor、Method类,提供了一些可以操作这些元素的 API,分别如表2-9、2-10 和2-11 所示。

关于反射机制的使用,这里举一个简单例子,假设实现如表2-12所示的类,其构造函数和eprint方法只实现一些打印指定字符串的功能,使用new关键字调用eprint方法的代码如表2-13所示。使用表2-8, 2-9, 2-10, 2-11中的反射API,调用代码示例如表2-14所示。经过编译运行测试可知,这两种调用方式,其执行效果是完全一样的。

方法句柄 MethodHandle 可以用于获取域、方法或构造函数,要得到方法句柄MethodHandle类,可以通过MethodHandles.Lookup类中提供的API来获得,如表2-15 所示。

再拿表2-12中的Example4做例子,使用Java 7提供的新反射API,调用形式如表2-16所示。

2.1.5  包访问限制

包访问限制(Package Access)是 JRE 沙箱安全机制的重要组成策略。它的实现原理也非常简单,通过阅读OpenJDK源代码可知,几乎所有敏感API,在调用前都会加一个checkPackageAccess方法,其功能是检查当前类是否具有访问、调用某些包的权限。

 

2.2  JVM 安全机制研究

除了2.1.1小节中提到的四趟class文件校验机制以外, JVM在执行class文件中的字节码时还内置了一些其他的安全机制。这些安全机制有力的维护了Java程序的健壮性,是 Java 语言类型安全特性的基础。比较主要的安全特性有以下几点:

1. 类型安全的引用转换;

2. 结构化的内存访问;

3. 自动化的垃圾回收;

4,数组边界检查;

5,空引用检查。

2.3  本章小结

本章主要总结了 Java安全机制的两大模块:JRE 沙箱和 JVM 安全。在第一小节,本文介绍了JRE沙箱的主要安全相关的组件或策略:类装载器、安全管理器、权限提升代码块、反射机制以及包访问限制策略。在第二小节,本文简要介绍了JVM的类型安全等机制,还有Java原生层API及其潜在安全问题。通过型对Java安全机制的研究,可以更好地理解JRE 漏洞成因,同时,该研究工作也是 JRE漏洞挖掘工作的基础研究。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/934206.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

libdrm全解析二十三 —— 源码全解析(20)

接前一篇文章&#xff1a;libdrm全解析二十二 —— 源码全解析&#xff08;19&#xff09; 本文参考以下博文&#xff1a; DRM 驱动程序开发&#xff08;VKMS&#xff09; 特此致谢&#xff01; 前一篇文章已提到&#xff0c;drmModeGetResources函数值得深入地进行讲解。本回…

C语言练习题Day1

从今天开始分享C语言的练习题&#xff0c;每天都分享&#xff0c;差不多持续16天&#xff0c;看完对C语言的理解可能更进一步&#xff0c;让我们开始今天的分享吧&#xff01; 题目一 执行下面的代码&#xff0c;输出结果是&#xff08;&#xff09; int x5,y7; void swap()…

Vue2向Vue3过度核心技术自定义指令

目录 1 自定义指令1.指令介绍2.自定义指令3.自定义指令语法4.指令中的配置项介绍5.代码示例6.总结 2 自定义指令-指令的值1.需求2.语法3.代码示例 3 自定义指令-v-loading指令的封装1.场景2.需求3.分析4.实现5.准备代码 1 自定义指令 1.指令介绍 内置指令&#xff1a;v-html、v…

基于JSP+Servlet+mysql学生宿舍管理系统

基于JSPServletmysql学生宿舍管理系统 一、系统介绍二、功能展示四、其它1.其他系统实现五.获取源码 一、系统介绍 项目类型&#xff1a;Java web项目 项目名称&#xff1a;基于JSPServlet的学生宿舍管理系统[sushe] 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java…

免费开源跨平台视频下载器 支持数百站点视频和音频下载-ytDownloader

ytDownloader&#xff1a; ytDownloader是一款免费开源跨平台视频下载器&#xff0c;帮助用户从数百个网站下载不同格式的视频和提取音频&#xff0c;使用简单&#xff0c;复制视频链接粘贴即可下载&#xff0c;支持4K画质视频下载&#xff0c;支持Linux、Windows 和 macOS平台…

DBO优化SVM的电力负荷预测,附MATLAB代码

今天为大家带来一期基于DBO-SVM的电力负荷预测。 原理详解 文章对支持向量机(SVM)的两个参数进行优化&#xff0c;分别是&#xff1a;惩罚系数c和 gamma。 其中&#xff0c;惩罚系数c表示对误差的宽容度。c越高&#xff0c;说明越不能容忍出现误差,容易过拟合。c越小&#xff0…

基于Java+SpringBoot+Vue前后端分离图书电子商务网站设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

大数据(二)大数据行业相关统计数据

大数据&#xff08;二&#xff09;大数据行业相关统计数据 目录 一、大数据相关的各种资讯 二、转载自网络的大数据统计数据 2.1、国家大数据政策 2.2、产业结构分析 2.3、应用结构分析 2.4、数据中心 2.5、云计算 一、大数据相关的各种资讯 1. 据IDC预测&#xff0…

软件工程(十五) 行为型设计模式(一)

1、责任链模式 简要说明 通过多个对象处理的请求,减少请求的发送者与接收者之间的耦合。将接受对象链接起来,在链中传递请求,直到有一个对象处理这个请求。 速记关键字 传递职责 类图如下 由类图可以比较容易的看出来,其实就是自己关联自己,形成了一个链,并且自己有…

开源与区块链:去中心化的未来

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

基于Java+SpringBoot+Vue前后端分离人力资源管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【Linux操作系统】Linux系统编程中的互斥锁

文章目录 1. 互斥锁的原理2. 互斥锁的相关函数3. 互斥锁的例子总结 1. 互斥锁的原理 在Linux系统编程中&#xff0c;互斥锁&#xff08;Mutex&#xff09;是一种用于保护共享资源的同步机制。它可以确保在任意时刻只有一个线程可以访问被保护的资源&#xff0c;从而避免了多个…

软件工程(十四) 设计模式之结构型模式(二)

1、组合模式 简要说明 将对象组合成树形结构以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。 速记关键字 树形目录结构 类图如下 由类图其实可以看出,组合模式就是将具有父子关系的结构,组装形成一棵树,并且根据规范,树干节点和叶子节…

大数据Flink(六十八):SQL Table 的基本概念及常用 API

文章目录 SQL & Table 的基本概念及常用 API 一、​​​​​​​一个 Table API\SQL任务的代码结构

tomcat高可用和nginx高可用

tomcat高可用和nginx高可用 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.什么是高可用&#xff1f; 高可用HA&#xff08;High Availability&#xff09;是分布式系统架构设计中必须考虑的因素之一&#xff0c;它通常是指&#xff0c;通过设计减少系统不能提供服务…

大数据(三)大数据相关的职位

大数据&#xff08;三&#xff09;大数据相关的职位 本文目录&#xff1a; 一、写在前面的题外话 二、2022年就业状况 2.1、不同企业性质高校毕业生 CIER 指数 2.2、不同企业规模高校毕业生 CIER 指数 2.3、高校毕业生供求 TOP15 城市 2.4、一季度景气指数较高和较低的行…

CodeLlama本地部署的实战方案

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【四】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【四】&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章…

Shell脚本的超详细讲解

目录 一、Shell脚本简介1.1 什么是shell?1.2 什么是shell脚本1.3 shell脚本的意义 二、Shell解析器三、Shell脚本入门四、Shell中的变量4.1 系统变量4.2 自定义变量4.3 特殊变量&#xff1a;$n4.4 特殊变量&#xff1a;$#4.5 特殊变量&#xff1a; $*、$4.6 特殊变量&#xff…

本地部署 CodeLlama 并在 VSCode 中使用 CodeLlama

本地部署 CodeLlama 并在 VSCode 中使用 CodeLlama 1. CodeLlama 是什么2. CodeLlama Github 地址3. 下载 CodeLlama 模型4. 部署 CodeLlama5. 在 VSCode 中使用 CodeLlama 1. CodeLlama 是什么 Code Llama 是一个基于 Llama 2 的大型代码语言模型系列&#xff0c;在开放模型、…