全面保护你的Java程序安全(上)
2008-04-09 03:59:57来源:互联网 阅读 ()
本文出自:http://www.computerworld.com.cn 作者: 野风 编译
第一部分:Java的安全基础——虚拟机和字节码安全
概论:安全问题对很多数人来说都非常重要。从其历史看,Java安全主要意味着虚拟机和字节码安全。然而这个看法忽略了两个重要方面—应用程序和网络安全。在下面一系列文章中,Todd Sundsted讲解了JAVA虚拟机安全,应用程序安全,网络安全,解释了应该采取什么样的措施来全面巩固你的Java安全。在这第一部分,他向我们解释了Java安全的基础:虚拟机和字节码安全。
“似乎还没有人曾因为写出了不安全的Java代码而遭解雇”。这句话是我对那句流行语“没人曾因购买了IBM而遭解雇”的修正版本。那些更关心网络速度和那些更有兴趣为简历添加更多有价值项目的雇员常常犯下安全问题。
再来看看另一个令人担心的现象:在我同管理人员和工程技术人员谈论安全问题时,我常常发现他们对自己的行为存在一些误解,他们认为不必考虑安全问题,因为“Java本身就等于安全”。在这样错误观念的指引下,工程师们没有去考虑以下三个方面的安全问题:虚拟机安全,应用程序安全,网络安全。
在以下一系列文章中,我会尽力修正这种错误见解。接下来,我将就三方面的问题来对Java安全进行讨论,并举列说明一般安全问题是怎样窃入的。另外我也会介绍一些办法来创建安全的应用程序。
·三种安全问题:
在Java初次露面时,开发者,研究人员,新闻媒体界对其安全问题就反响剧烈。在早前的时候,Java安全就是意味着字节码安全和虚拟机安全。由于Java过去主要是作为下载到本地执行的小应用程序开发语言,下载下来的代码的安全性和执行环境就是异常重要的事情。这种情况下的安全意味着正确安装类装载器和安全管理器以及验证下载的代码。
在我以前开发C/C 程序的数年里,我从没担心过虚拟机安全问题—这个问题完全是随着Java而成了人们关注的中心。谈到安全问题,我担心的总是应用程序漏洞或是危及程序或系统安全的执行情况。在C 领域,应用程序上的安全包括限制“setuid”代码范围(在Unix环境,setuid代码是作为另外的用户进程来运行—典型的情况是超级用户)并力图避免缓冲溢出及其它类型的堆栈问题。
而分布式应用程序的引入则带来了另外一些方面的问题。正如其名字所示,分布式程序由多个部分组成,每个部分都驻留在它自己的机器上,并通过公共网络和其它部分通信。一个Web应用就是典型的列子。在网络意义上的安全则意味着签名,授权,应用程序组件,加密通信管道等。
许多开发人员并不清楚以上几方面的不同,并以为Java在虚拟机一层安全了,那么整个应用程序就安全了。我很希望改变这种观念。下面就开始来讨论Java的虚拟机安全。
·安全基础:虚拟机安全
虚拟机安全,长期以来一直是开发人员注意的焦点,几乎直到现在也还是没有结果。
我最初对讨论虚拟机安全感到有兴趣是在转向应用程序和网络安全之前。我决定给予它同另两个部分同样公平的时间来讨论,这出于两个理由:首先,优秀的编程教材因该包含过去6年来发现过的大量漏洞,第二,很多安全问题跨越了我要讨论的三个方面。为了能透彻理解,你必须要全面熟悉三个方面,包括Java虚拟机安全。
如果你检查过去6年发现的各种安全问题(看http://www.javaworld.com/javaworld/jw-06-2001/jw-0615-howto.html#resources的官方清单),你将发现它们被分成一系列目录。就所关注的虚拟机安全来讲,最重要的两种安全漏洞都是围绕着未被验证和可能非法的字节码以及Java类型系统破坏来展开。在实际开发中,这两者经常是关联在一起
·未验证代码探秘
在JVM通过网络从服务器上下载类代码时,它并没有办法知道这些字节码是否能安全执行。安全的字节码永不会指示虚拟机执行让Java运行时处于不懈调和无效的状态。
通常,Java编译器可以确保创建的类文件里的字节码是安全的。然而也可以手工写出Java编译器不允许的字节码。Java校验器以一系列极富想像力的方法检查所有这样的字节码并验证那些不合规范的代码。一旦校验完成,JVM便知道程序代码是安全的—只要校验器正常工作。
下面让我们来看看一个列子,以更好的理解校验器所扮演的角色,并看看一旦校验器失效会产生什么后果。
考虑一下下面这个类:
public class Test1
{
public static void main(String [] arstring)
{
Float a = new Float(56.78);
Integer b = new Integer(1234);
System.out.println(a.toString());
}
}
当你写完它并运行,程序将向屏幕打印出字符串“56.78”。这是个在类里分配的一个浮点型变量。我们即将修改一处代码,欺骗虚拟机在整型变量上激活toString()方法而不是浮点型变量(你可以从网址下载并修改源代http://www.javaworld.com/javaworld/jw-06-2001/jw-0615-howto.html#resources)。
再来看看这段经反编译后的代码的输出:
Method void main(java.lang.String[])
0 new #3
3 dup
4 ldc2_w #13
7 invokespecial #8
10 astore_1
11 new #4
14 dup
15 sipush 1234
18 invokespecial #9
21 astore_2
22 getstatic #10
25 aload_1
26 invokevirtual #12
29 invokevirtual #11
32 return
上面的代码包含了main()函数的反编译输出。在这个方法的地址偏移量25处,虚拟机载入于偏移0到10处创建的浮点型变量的一个引用。这就是我们要修改的地方。
下面就是经修改后的反编译代码:
Method void main(java.lang.String[])
0 new #3
3 dup
4 ldc2_w #13
7 invokespecial #8
10 astore_1
11 new #4
14 dup
15 sipush 1234
18 invokespecial #9
21 astore_2
22 getstatic #10
25 aload_2
26 invokevirtual #12
29 invokevirtual #11
32 return
这个类在偏移量25处的字节码是完全相同的,载入一个整型变量的引用。
注意看看,修改后的代码仍然是安全的,这非常重要,这意味着JVM仍然将执行代码而不会崩溃或是将错误代码隔离开。然而校验器仍然能分辨出这些变化。在我的系统里,在我运行这片代码时,出现错误:
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:Java源码:Socket编程
下一篇:Java源码:URL编程
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash