为什么我会听到如此多的 Java 不安全感?其他语言更安全吗?

信息安全 开发 爪哇
2021-08-30 01:58:54

我真的很喜欢 Java 编程语言,但我不断听说它有多不安全。谷歌搜索“java 不安全”或“java 漏洞”会出现多篇文章,讨论为什么应该卸载或禁用 Java 以保护您的计算机。Java 经常一次发布大量安全补丁,但仍有大量漏洞需要修补。

我知道软件中总会有错误,但 Java 存在的漏洞数量似乎并不正常(或者我是在想象吗?)。更令人困惑的是,如果有一个单一的架构决策导致了这些漏洞,为什么不改变这个设计呢?有很多其他编程语言没有这个问题,所以必须有更好的方法来解决 Java 做错的任何事情。那么为什么Java仍然如此不安全呢?

4个回答

如果您像大多数其他编程语言一样使用 Java,例如编写独立的应用程序,它的安全性不亚于其他语言,并且比 C 或 C++ 更安全,因为没有缓冲区溢出等。

但是Java 经常被用作Web 浏览器中的插件,例如类似于Flash。因为在这种情况下,用户在没有显式安装的情况下运行不受信任的代码,所以我们的想法是让代码在有限的沙箱中运行,它不应该以某种方式对系统或用户采取行动(例如读取本地文件并发送他们到网站,扫描本地网络等)。这就是Java近年来失败的地方,例如,有时每天都会出现新的错误,从而允许从沙箱中逃脱。

此外,有时字节码解释器或本机库中的错误会导致缓冲区溢出并可能危及系统,但在这方面通常认为 Flash 更糟。

至于其他更好的语言:这些通常甚至不能作为不受信任的代码在沙箱中运行(JavaScript 和可能是 Flash 除外),因此它们会更糟,因为没有固有的方法来限制它们与系统的交互.

报告的安全漏洞与 Java(编程语言)无关,由于 JVM 强制执行内存安全,Java 实际上比 C 或 C++ 等语言更健壮,其中缓冲区溢出和缓冲区过度读取仍然是一个威胁,并且可能会导致像 Heartbleed 这样的混乱。

相反,报告的漏洞位于 Java Sandbox 中,它试图强制执行允许安全执行不受信任代码的特权模型,并且最着名的是用于允许在浏览器中自动执行 Java Applet。那个沙箱上布满了漏洞。此外,Oracle 每年仅发布 4 次补丁(“关键补丁更新”)。不用说,浏览器供应商对此并不满意。例如,Firefox 从 Firefox 26开始需要用户授权才能启动 Java Applet 。

新闻报道没有做出这种区分的原因是甲骨文将“Java”商标用于编程语言和运行小程序的浏览器插件事实上,如果普通用户遇到Java商标,很可能是指后者。

沙盒究竟为何仍然脆弱,这在某种程度上是推测性的。如果你问我,一个原因是在有和没有沙箱的情况下使用相同的 API,并且大多数 Java 代码在没有沙箱的情况下运行(因为代码是可信的)。因此,开发人员很可能在更改 Java API 或其实现时忘记那个晦涩的特性,不小心暴露了应该保护的东西(为了说明这有多容易,请看冗长的 Java SE 安全编码指南)。另一个相关的原因是 Java API 的庞大规模(Java SE 6 有 5800 个类和近 50,000 个方法)。

有很多其他编程语言没有这个问题,所以必须有更好的方法来解决 Java 做错的任何事情。

这是一个相当高的要求,你从哪里得到这样的印象?有“大量其他编程语言”没有经过与 Java 相同的步伐,或者被广泛使用。

原则上,有这么多安全补丁的原因是因为 Java 被设计为安全的,具有许多其他语言所没有的以安全为中心的特性。

Java 语言环境

1.2.2 稳健且安全

Java 技术旨在在分布式环境中运行,这意味着安全性至关重要。通过在语言和运行时系统中设计的安全特性,Java 技术允许您构建无法从外部入侵的应用程序。在网络环境中,用 Java 编程语言编写的应用程序可以防止未经授权的代码试图进入幕后制造病毒或入侵文件系统。

如果您的编程语言规范中没有包含“安全”,那么您将很少需要发布安全补丁。另一方面,如果这是您既定的目标之一,您将很难不这样做

就其本身而言,Java 具有很好的安全性,即其固有的对缓冲区溢出和内存管理错误的抵抗力:

  • 所有数组访问都根据分配的数组长度进行检查。因此,缓冲区溢出被可靠地捕获,并触发异常,这更好(这将远程代码执行漏洞转变为纯粹的拒绝服务)。

  • 内存分配是通过垃圾收集器管理的,它可以防止释放后使用和双重释放错误。此外,GC 允许更轻松地处理字符串(字符串在 Java 中是不可变的),这消除了大多数情况下的缓冲区溢出错误。

  • 强制输入严格;代码无法访问它们不是的数据字节。这再次防止了漏洞(数据类型被违反的错误将在编译时报告,或者在最坏的情况下,作为运行时报告ClassCastException)。

这使得 Java在安全性方面比许多编程语言(尤其是地狱般的 C/C++)强大得多。

然而,Java 设计者试图利用这种增强的安全性来制作一些困难的东西,例如applet问题是攻击面:由于小程序是潜在的恶意代码,它所做的一切都必须受到控制。但是恶意代码必须能够使用“标准 Java 类”才能执行任何操作,因此必须在每个单独的标准 Java 类上强制执行“控制点”。因此,攻击面由数百个包含数千个方法的类组成,并且所有这些类都必须强制执行足够的检查。

Java 设计者因野心而犯了罪:在不搞砸任何检查的情况下实现数千次检查的难度比他们想象的要高得多。所有的“Java bug”都来自这个事实。

我们可以在这里比较 Java 和 Javascript;例如,Java 允许访问磁盘上的文件,但不得将这种权利授予小程序,除非小程序要求并且用户同意(这涉及整个小程序签名业务)。Javascript,不那么雄心勃勃,只是缺少任何文件访问方法:如果函数实际上不存在,则无法正确实现函数的访问控制!

总结一下: Java 很好而且很安全。Java小程序意味着一个巨大的攻击面,其安全性很难保证。但是,对于独立的应用程序和服务器,如果您需要安全性,使用 Java 是一个好主意(这同样适用于 C#)。