《2022年Java服务器端编程安全必读Java教程.docx》由会员分享,可在线阅读,更多相关《2022年Java服务器端编程安全必读Java教程.docx(8页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、2022年Java服务器端编程安全必读Java教程概述和溢出一、概述编写平安的Internet应用并不是一件轻而易举的事情:只要看看各个专业公告板就可以找到连绵不断的平安漏洞报告。你如何保证自己的Internet应用不象其他人的应用那样满是漏洞?你如何保证自己的名字不会出现在令人尴尬的重大平安事故报道中?假如你运用Java Servlet、JavaServer Pages(JSP)或者EJB,很多难以解决的问题都已经事先解决。当然,漏洞仍有可能出现。下面我们就来看看这些漏洞是什么,以及为什么Java程序员不必担忧部分C和Perl程序员必需面对的问题。C程序员对平安漏洞应当已经很熟识,但象Ope
2、nBSD之类的工程供应了处理此类问题的平安系统。Java语言处理这类问题的阅历要比C少20年,但另一方面,Java作为一种客户端编程语言诞生,客户端对平安的要求比服务器端苛刻得多。它意味着Java的发展有着一个稳固的平安性基础。Java原先的定位目标是阅读器。然而,阅读器本身所带的Java虚拟机虽然很不错,但却并不完备。Sun的Chronology of security-related bugs and issues总结了运行时环境的漏洞发觉历史。我们知道,当Java用作服务器端编程语言时,这些漏洞不行能被用作攻击手段。但即使Java作为客户端编程语言,重大平安问题的数量也从1996年的6个
3、(其中3个是相当严峻的问题)降低到2000年的1个。不过,这种平安性的相对提高并不意味着Java作为服务器端编程语言已经肯定平安,它只意味着攻击者能够运用的攻击手段越来越受到限制。那么,原委有哪些地方简单受到攻击,其他编程语言又是如何面对类似问题的呢?二、缓存溢出在C程序中,缓存溢出是最常见的平安隐患。缓存溢出在用户输入超过已安排内存空间(专供用户输入运用)时出现。缓存溢出可能成为导致应用被覆盖的关键因素。C程序很简单出现缓存溢出,但Java程序几乎不行能出现缓存溢出。从输入流读取输入数据的C代码通常如下所示:char buffer1000;int len = read(buffer);由于缓
4、存的大小在读入数据之前确定,系统要检查为输入保留的缓存是否足够是很困难的。缓存溢出访得用户能够覆盖程序数据结构的关键部分,从而带来了平安上的隐患。有阅历的攻击者能够利用这一点干脆把代码和数据插入到正在运行的程序。在Java中,我们一般用字符串而不是字符数组保存用户输入。与前面C代码等价的Java代码如下所示:String buffer = in.readLine();在这里,“缓存”的大小总是和输入内容的大小完全一样。由于Java字符串在创建之后不能变更,缓存溢出也就不行能出现。退一步说,即运用字符数组替代字符串作为缓存,Java也不象C那样简单产生可被攻击者利用的平安漏洞。例如,下面的Jav
5、a代码将产生溢出:char bad = new char;bad = 50;这段代码总是抛出一个java.lang.ArrayOutOfBoundsException异样,而该异样可以由程序自行捕获:try {char bad = new char;bad = 50;}catch (ArrayOutOfBoundsException ex) {. }这种处理过程恒久不会导致不行预料的行为。无论用什么方法溢出一个数组,我们总是得到ArrayOutOfBoundsException异样,而Java运行时底层环境却能够爱护自身免受任何侵害。一般而言,用Java
6、字符串类型处理字符串时,我们无需担忧字符串的ArrayOutOfBoundsExceptions异样,因此它是一种较为志向的选择。Java编程模式从根本上变更了用户输入的处理方法,避开了输入缓存溢出,从而使得Java程序员摆脱了最危急的编程漏洞。 竞争和执行过程 三、竞争状态竞争状态即Race Condition,它是其次类最常见的应用平安漏洞。在创建(更改)资源到修改资源以禁止对资源访问的临界时刻,假如某个进程被允许访问资源,此时就会出现竞争状态。这里的关键问题在于:假如一个任务由两个必不行少的步骤构成,不管你多么想要让这两个步骤一个紧接着另一个执行,操作系统并不保证这一点。例如,在数据库中
7、,事务机制使得两个独立的事务“原子化”。换言之,一个进程创建文件,然后把这个文件的权限改成禁止常规访问;与此同时,另外一个没有特权的进程可以处理该文件,欺瞒有特权的进程错误地修改文件,或者在权限设置完毕之后仍接着对原文件进行访问。一般地,在标准Unix和NT环境下,一些高优先级的进程能够把自己插入到任务的多个步骤之间,但这样的进程在Java服务器上是不存在的;同时,用纯Java编写的程序也不行能修改文件的许可权限。因此,大多数由文件访问导致的竞争状态在Java中不会出现,但这并不意味着Java完全地摆脱了这个问题,只不过是问题转到了虚拟机上。我们来看看其他各种开发平台如何处理这个问题。在Uni
8、x中,我们必需确保默认文件创建模式是平安的,比如在服务器启动之前执行“umask 200”这个吩咐。有关umask的更多信息,请在Unix系统的吩咐行上执行“man umask”查看umask的man文档。在NT环境中,我们必需操作ACL(访问限制表,Access Control List)的平安标记,爱护要在它下面创建文件的书目。NT的新文件一般从它的父书目继承访问许可。请参见NT文档了解更多信息。Java中的竞争状态大多数时候出现在临界代码区。例如,在用户登录过程中,系统要生成一个唯一的数字作为用户会话的标识符。为此,系统先产生一个随机数字,然后在散列表之类的数据结构中检查这个数字是否已经
9、被其他用户运用。假如这个数字没有被其他用户运用,则把它放入散列表以防止其他用户运用。代码如Listing 1所示:(Listing 1)/ 保存已登录用户的IDHashtable hash;/ 随机数字生成器Random rand;/ 生成一个随机数字Integer id = new Integer(rand.nextInt();while (hash.containsKey(id){id = new Integer(rand.nextInt();}/ 为当前用户保留该IDhash.put(id, data);Listing 1的代码可能带来一个严峻的问题:假如有两个线程执
10、行Listing 1的代码,其中一个线程在hash.put(.)这行代码之前被重新调度,此时同一个随机ID就有可能被运用两次。在Java中,我们有两种方法解决这个问题。首先,Listing 1的代码可以改写成Listing 2的形式,确保只有一个线程能够执行关键代码段,防止线程重新调度,避开竞争状态的出现。其次,假如前面的代码是EJB服务器的一部分,我们最好有一个利用EJB服务器线程限制机制的唯一ID服务。(Listing 2)synchronized(hash){/ 生成一个唯一的随机数字Integer id =new Integer(rand.nextInt();while (h
11、ash.containsKey(id){id = new Integer(rand.nextInt();}/ 为当前用户保留该IDhash.put(id, data);}四、字符串说明执行在有些编程语言中,输入字符串中可以插入特别的函数,欺瞒服务器使其执行额外的、多余的动作。下面的Perl代码就是一个例子:$data = mail body;system(/usr/sbin/sendmail -t $1 < $data);明显,这些代码可以作为CGI程序的一部分,或者也可以从吩咐行调用。通常,它可以根据如下方式调用:perl script.pl honest它将把一个邮件(即“mail body”)发送给用户honest。这个例子虽然简洁,但我们却可以根据如下方式进行攻击:perl script.pl honest;mailcheat < /etc/passwd这个吩咐把一个空白邮件发送给honest,同时又把系统密码文件发送给了cheat。假如这些代码是CGI程序的一部分,它会给服务器的平安带来重大的威逼。Perl程序员经常用外部程序(比如sendmail)扩充Perl的功能,以避开用脚原来实现外部程序的功能。然而,Java有着相当完善的API。比
限制150内