《深入解析Android 虚拟机》——第2章,第2.3节JVM的安全性

2.3 JVM的安全性
除了平台无关性以外,Java还必须解决的另一个技术难题就是安全。因为网络运行多台计算机共享数据和分布式处理,所以它提供了一条侵入计算机系统的潜在途径,使得其他人可能窃取信息、改变或破坏信息、盗取计算资源等。因此,将计算机联入网络产生了很多安全问题。为了解决由网络引起的安全问题,Java体系结构采用了一个扩展的内置安全模型,这个模型随着Java平台的主要版本而不断发展。在本节的内容中,将简要讲解JVM安全性的基本知识,为读者步入本书后面知识的学习打下基础。

2.3.1 JVM的安全模型
Java安全模型侧主要用于保护终端用户免受从网络下载的、来自不可靠来源的、恶意程序的侵犯。为了达到这个目的,Java提供了一个用户可配置的“沙箱”,在沙箱中可以放置不可靠的Java程序。沙箱对不可靠程序的活动进行了限制,程序可以在沙箱的安全边界内做任何事,但是不能进行任何跨越这些边界的举动。例如,原来在版本1.0中的沙箱对很多不可靠Javaapplet的活动做了限制,主要包括:

对本地硬盘的读写操作;
进行任何网络连接,但不能连接到提供者applet的源主机;
创建新的进程;
装载新的动态连接库。
由于下载的代码不可能进行这些特定的操作,这使得Java安全模型可以保护终端用户避免受到有漏洞的代码的威胁。在沙箱内有严格的限制,其安全模型甚至规定了对不可靠代码能做什么、不能做什么,所以用户可以比较安全地运行不可靠代码。但是对于1.0系统的程序员和用户来说,这个最初的沙箱限制太过严格,善意的代码常常无法进行有效的工作。所以在后来的1.1版本中,对最初的沙箱模型进行了改进,引入了基于代码签名和认证的信任模式。签名和认证使得接收端系统可以确认一系列class文件已经由某一实体进行了数字签名(有效,可被信赖),并且在经过签名处理以后,class文件没有改动。这使得终端用户和系统管理员减少了对某些代码在沙箱中的限制,但这些代码必须已由可信任团体进行数字签名。

虽然1.1版本的安全API包含了对认证的支持,但是其实只是提供了完全信任和完全不信任策略。Java 1.2提供的API可以帮助建立细粒度的安全策略,这种策略是建立在数字签名代码的认证基础上的。Java安全模型的发展经历了1.0版本的基本沙箱,然后是1.1版本的代码签名和认证,最后是1.2版以后的细粒度访问控制。

2.3.2 沙箱模型的4种组件
在计算机系统中,个人电脑中运行一个软件的前提是必须信任它。普通用户只能通过小心地使用来自可信任来源的软件来达到安全性,并且定期扫描,检查病毒来确保安全性。一旦某个软件有权使用我们的系统,那么它将拥有对这台电脑的完全控制权。如果这个软件是恶意的,那么它就可以为所欲为。所以在传统的安全模式中,必须想办法防止恶意代码有权使用你的计算机。

沙箱安全模型使得工作变得容易,即使某个软件来自我们不能完全信任的地方,通过沙箱模型可以使我们接受来自任何来源的代码,而不是要求用户避免将来自不信任站点的代码下载到机器上。当运行来自不可靠来源的代码时,沙箱会限制它进行任何可能破坏系统的动作指令。并且在整个过程中,无需指出哪些代码可以信任,哪些代码不可以信任,也不必扫描查找病毒。沙箱本身限制了下载的任何病毒或其他恶意的,有漏洞的代码,使得它们不能对计算机进行破坏。

如果你还有疑问,在确信它能保护你之前,用户必需确认沙箱没有任何漏洞。为了保证沙箱没有漏洞,Java安全模型对其体系结构的各方面都进行了考虑。如果在Java体系结构中有任何没有考虑到安全的区域,恶意的程序员很可能会利用这些区域来绕开沙箱。因此,为了对沙箱有一个了解,必须先看一下Java体系结构的几个不同部分,并且理解它们是怎样一起工作的。

下面列出了组成Java沙箱的基本组件。

类加载体系结构。
class文件检验器。
内置于Java虚拟机(及语言)的安全特性。
安全管理器及Java API。
Java的上述安全模型的前3个部分——类加载体系结构、class文件检验器、Java虚拟机(及语言)的安全特性一起达到一个共同的目的:保持JVM的实例和它正在运行的应用程序的内部完整性,使得它们不被下载的恶意代码或有漏洞的代码侵犯。相反,这个安全模型的第四个组成部分是安全管理器,它主要用于保护虚拟机的外部资源不被虚拟机内运行的恶意或有漏洞的代码侵犯。这个安全管理器是一个单独的对象,在运行的Java虚拟机中,它在对于外部资源的访问控制起中枢作用。

2.3.3 分析Java的策略机制
沙箱安全模型的最大优点之一是可以是用户自定义的,通过从Java1.1版本就已经引入的代码签名和认证技术,使正在运行的应用程序可以对代码区分不同的信任度。通过自定义沙箱,被信任的代码可以比不可靠的代码获得更多的访问系统资源的权限。这就防止了不可靠代码访问系统,但是却允许被信任的代码访问系统并进行工作。Java安全体系结构的真正好处在于,它可以对代码授予不同层次的信任度来部分地访问系统。

Microsoft提供了ActiveX控件认证技术,它和Java的认证技术相类似,但是ActiveX控件并不在沙箱中运行。这样使用了ActiveX,一系列移动代码要么是被完全信任的,要么是完全不被信任的。如果一个ActiveX控件不被信任,则它将被拒绝执行。虽然这对于没有认证来说是一个很大的提高,但是如果一些恶意的或是有漏洞的代码得到了认证,这段危险的代码将拥有对系统的完全访问权。Java的安全体系结构的优点之一就是,代码可以被授予只对它需要的资源进行访问的有限权限。即使一些恶意的或者有漏洞的代码得到了认证,它也很少有机会进行破坏。例如,一段恶意的或者有漏洞的代码可能只能删除一个固定目录下的为它设置的文件,而不是在本地硬盘上的所有文件。

从1.2版本开始的安全体系结构的主要目标是建立(以签名代码为基础的)细粒度的访问控制策略,这样不但过程更为简单而且更少出错。为了将不同的系统访问权限授予不同的代码单元,Java的访问控制机制必须能确认应该给每个代码段授予什么样的权限。为了使这个过程变得容易,载入1.2版本或其他虚拟机的每一个代码段(每个class文件)将和一个代码来源关联。代码来源主要说明了代码从哪里来,如果它被某个人签名担保的话,是从谁那里来。在1.2版本以后的安全模型中,权限(系统访问权限)是授给代码来源的。因此如果代码段请求访问一个特定的系统资源,只有当这个访问权限是和那段代码的代码来源相关联时,Java虚拟机才会把对那个资源的访问权限授予这段代码。

在1.2版本的安全体系结构中,对应于整个Java应用程序的一个访问控制策略是由抽象类java.security.Policy的一个子类的单个实例所表示的。在任何时候,每一个应用程序实际上都只有一个Policy对象。获得许可的代码可以用一个新的Policy对象替换当前的Policy对象,这是通过调用Policy.setPolicy()并把一个新的Policy对象的引用传递给它来实现的。类装载器利用这个Policy对象来帮助它们决定,在把一段代码导入虚拟机时应该给它们什么样的权限。

安全策略是一个从描述运行代码的属性集合到这段代码所拥有的权限的映射。在1.2版本的安全体系结构中,描述运行代码的属性被总称为代码来源。一个代码来源是由一个java.security.CodeSource对象表示的,这个对象中包含了一个java.net.URL,它表示代码库和代表了签名者的零个或多个证书对象的数组。证书对象是抽象类java.security.Certificate的子类的一个实例,一个Certificate对象抽象表示了从一个人到一个公钥的绑定,以及另一个为这个绑定作担保的人(以前提过的证书机构)。CodeSource对象包含了一个Certificate对象的数组,因为同一段代码可以被多个团体签名(担保)。这个签名通常是从Jar文件中获得的。

从1.2版本开始,所有和具体安全管理器有关的工具和访问控制体系结构都只能对证书起作用,而不能对公钥起作用。如果附近没有证书机构,可以用私钥对公钥签名,生成一个自签名的证书。当使用keytool程序生成密钥时,总是会产生一个自签名的证书。例如在上一节的签名例子中,keytool不仅产生了“公钥/私钥”对,而且还为别名friend和stranger产生了自签名的证书。

权限是用抽象类java.security.Permission的一个子类的实例表示的。一个Permission对象有3个属性,分别是类型、名字和可选的操作。权限的类型是由Permisstion类的名字指定的,例如java.io.FilePermission、java.net.SocketPermission和java.awt.AWTPermission。权限的名字是封装在Permission对象内的。例如某个FilePermission的名字可能是“/my/finances.dat”,某个SocketPermission的名字可能是“applets.artima.com:2000”,某个AWTPermission的名字可能是“showWindowWithoutBannerWarning”。Permission对象的第3个属性是它的动作。并不是所有的权限都有动作。例如,FilePermission的动作是“read, write”,SocketPermission的动作是“accept, connect”。如果一个FilePermission的名字为“/my/finances.dat”,并且有动作“read, write”,那么它就表示对文件“/my/finance.dat”可以进行读写操作。名字和动作都是由字符串来表示的。

Java API有一个很大的权限层次结构,在里面表示了所有可能潜在危险的操作。可以根据自己的目的创建自己的Permission类来表示自定义的权限,例如可以创建一个Permission类来表示对属性数据库的特定记录的访问权限。定义自定义的Permission类也是一种扩展版本1.2的安全机制类满足自己需要的方法。如果创建了自己的Permission类,可以像使用Java API中的Permission类一样来使用它们。

在Policy对象中,每一个CodeSource是和一个或多个Permission对象相关联的。和一个CodeSource相关联的Permission对象被封装在java.security.PermissionCollection的一个子类实例中。类装载器可以调用Policy.getPolicy()来获得一个当前有效的Policy对象的引用。然后它们可以调用Policy对象的getPermission()方法,传入一个CodeSource,从而得到和那个CodeSource对应的Permission对象的PermissionCollection。然后类装载器可以使用这个从Policy对象中得到的PermissionCollection来帮助判断应该给导入的代码授予什么权限。

时间: 2024-10-31 17:41:07

《深入解析Android 虚拟机》——第2章,第2.3节JVM的安全性的相关文章

《深入解析Android 虚拟机》——第2章,第2.1节虚拟机的作用

第2章 Java虚拟机基础 深入解析Android 虚拟机 Java虚拟机和Android虚拟机十分相似,所以在本书中将以Java虚拟机开始,逐步引领广大读者步入Android虚拟机的世界.在本章的内容中,将简要讲解Java虚拟机技术的基本知识,为读者步入本书后面知识的学习打下基础. 2.1 虚拟机的作用 虚拟机(Virtual Machine)这一概念最初由波佩克与戈德堡定义,是指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统.由此可见,虚拟机是跟特定硬件无关的

《深入解析Android 虚拟机》——第2章 Java虚拟机基础 2.1虚拟机的作用

2.1 虚拟机的作用 虚拟机(Virtual Machine)这一概念最初由波佩克与戈德堡定义,是指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统.由此可见,虚拟机是跟特定硬件无关的一个系统.在现实应用中,虚拟机最常见的情形便是双系统.例如计算机原装系统是Windows,为了在这台机器上能够体验Linux系统,可以安装一个虚拟机环境,在这个虚拟机环境中运行Linux系统,这样就实现了"一机双系统"的功效.在现实应用中,通过虚拟机软件可以在一台物理计算机上

《深入解析Android 虚拟机》——导读

前言 Android虚拟机技术--Dalvik VM是通往Android高级开发的必备技术!为了让广大读者深入理解Android系统,不再停留在抽象的原理和概念之上,本书对Android虚拟机方面的知识进行了细致分析,这样做的目的是"提炼"出Android系统的本质,了解Android系统究竟是如何运作的,进程和线程之间是如何协调并进的,内存之间是如何分配并存的.并以此为基础,详细讲解了内存优化.垃圾收集和系统优化方面的基本原理和具体实现. Android系统从诞生到现在的短短几年时间

《深入解析Android 虚拟机》——2.3 JVM的安全性

2.3 JVM的安全性 除了平台无关性以外,Java还必须解决的另一个技术难题就是安全.因为网络运行多台计算机共享数据和分布式处理,所以它提供了一条侵入计算机系统的潜在途径,使得其他人可能窃取信息.改变或破坏信息.盗取计算资源等.因此,将计算机联入网络产生了很多安全问题.为了解决由网络引起的安全问题,Java体系结构采用了一个扩展的内置安全模型,这个模型随着Java平台的主要版本而不断发展.在本节的内容中,将简要讲解JVM安全性的基本知识,为读者步入本书后面知识的学习打下基础. 2.3.1 JV

《深入解析Android 虚拟机》——第1章 获取并编译Android源码 1.1获取Android源码

第1章 获取并编译Android源码 在本章中,将详细讲解获取并编译Android源码的基本知识,介绍各个目录中主要文件的功能,为读者步入本书后面知识的学习打下基础. 1.1 获取Android源码 要想研究Android系统的源码,需要先获取其源码.目前市面上主流的操作系统有Windows.Linux.Mac OS的操作系统,由于Mac OS源自于Linux系统,因此本书将讲解分别在Windows系统和Linux系统中获取Android源码的知识. 1.1.1 在Linux系统获取Androi

《深入解析Android 虚拟机》——第2章,第2.4节网络移动性

2.4 网络移动性 长久以来,如何开发网络软件是Java开发人员所面临的最大挑战之一.在网络领域需要实现平台无关性,因为同一网络中通常连接了多种不同的计算机和设备.除此之外,安全模式也是一个挑战,因为网络可以方便地传输病毒和其他形式的恶意代码.在本节将详细讲解Java如何把握网络所带来的巨大机遇,为步入本书后面知识的学习打下基础. 2.4.1 现实需要网络移动性 当个人计算机互联成网变得越来越普遍的时候,另一种软件模式日益重要起来,即"客户机/服务器"模式."客户机/服务器&

《深入解析Android 虚拟机》——第1章,第1.4节编译Android Kernel

1.4 编译Android Kernel 编译Android Kernel代码就是编译Android内核代码,在进行具体编译工作之前,需要先了解在Android开源系统中包含的以下3部分代码. 仿真器公共代码:对应的工程名是kernel/common.get. MSM平台的内核代码:对应的工程名是kernel/msm.get. OMAP平台的内核代码:对应的工程名是kernel/omap.get. 在本节的内容中,将详细讲解编译上述Android Kernel的基本知识. 1.4.1 获取Gol

《深入解析Android 虚拟机》——第2章,第2.5节内存异常和垃圾处理

2.5 内存异常和垃圾处理 对于C和C++的开发人员来说,在内存管理领域应该能够游刃有余.在计算机系统中,内存负责维护每一个对象生命的从开始到终结.Java内存分配与管理是Java的核心技术之一,通常Java在内存分配时会涉及到以下区域. 寄存器:在程序中无法控制. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中. 堆:存放用new产生的数据. 静态域:存放在对象中用static定义的静态成员. 常量池:存放常量. 非RAM存储:硬盘等永久存储空间. 2.5.1 内存

《深入解析Android 虚拟机》——第1章,第1.2节分析Android源码结构

1.2 分析Android源码结构获得Android源码后,可以将整个源码分为如下3个部分. Core Project:核心工程部分,这是建立Android系统的基础,被保存在根目录的各个文件夹中.External Project:扩展工程部分,可以使其他开源项目具有扩展功能,被保存在"external"文件夹中.Package:包部分,提供了Android的应用程序.内容提供者.输入法和服务,被保存在"package"文件夹中.无论是Android 1.5还是An