我正在使用一些通常编写和解析良好的 java 代码,但是我的代码扫描工具抛出了一些奇怪的东西。
我知道空指针取消引用可能会使程序崩溃,但是假设编写代码是为了捕获和管理所有异常,那么有人知道可以使用此问题的真正攻击吗?
非常感谢收到代码片段:-)
我正在使用一些通常编写和解析良好的 java 代码,但是我的代码扫描工具抛出了一些奇怪的东西。
我知道空指针取消引用可能会使程序崩溃,但是假设编写代码是为了捕获和管理所有异常,那么有人知道可以使用此问题的真正攻击吗?
非常感谢收到代码片段:-)
从理论上讲,Java 中任何类型的空指针取消引用都会触发 a NullPointerException,这可以在 Java 中像任何其他异常一样处理。这并不意味着这是好的:在实践中,很难从这样的异常中恢复,除非删除有故障的部分(即让调用线程死掉,或者回到一个包罗万象的子句)。跟随空指针类似于溢出缓冲区:它仍然是一个错误;Java 和不受保护的语言(例如 C)之间的区别在于 Java 对错误的后果更加优雅:特别是,异常将传播回调用堆栈,释放监视器(synchronized关键字)并执行finally子句,只有故障线程会受到影响。
然而,在实践中,可能会出现一些问题。JVM 如何捕获空指针取消引用取决于 JVM 实现;但是实现通常会做以下事情:它们只是跟随指针。如果指针是null,那么这将导致在内存的第一页中进行内存访问,这是操作系统禁止访问的。操作系统(通过 MMU)捕获事件并以相对粗暴的方式通知应用程序(在类 Unix 系统上,这是一个SIGSEGV信号)。JVM 接收信息,并将其转换为NullPointerException.
从信号到异常的转换是一件复杂的事情,因为 JVM 只接收有问题的操作码地址,该地址位于字节码解释器或 JIT 生成的二进制代码中。JVM 必须定位方法和线程堆栈。这与操作系统如何将事物首先放入内存有一些很好的交互。如今,在主流平台上,此类代码非常稳定。然而,在一个不太常见的组合上(Sun 的 JDK 移植到 FreeBSD),我有时会遇到 JVM 无法找到调用者堆栈的空指针取消引用(因为 JVM 代码针对 Linux 而不是针对 FreeBSD 进行了调整,并且显然正在使关于堆栈应该在哪里的假设,FreeBSD 上并不总是满足的假设)。结果是以最不优雅的方式立即终止 JVM。
另一个可能的问题是空指针取消引用被捕获,因为访问位于“禁止”页面的某个位置;即地址空间的第一页。但是,当访问实例字段时,JVM 通常会直接访问正确的数据元素:如果引用在本机代码级别是指向地址x的指针,并且该字段位于对象结构中的偏移量n处,那么代码将读取地址x+n处的字节(这实际上取决于 JVM 如何在内部表示对象,但类似 C 的结构很常见)。如果类有很多字段,那么n可能大于页面的大小,在这种情况下,读取访问权限不会落在第一页,而是第二页。在这种情况下会发生什么取决于操作系统。
数组不会出现“高偏移字段”的情况,因为数组访问是长度检查的,“长度”通常是一种靠近对象头的字段。另外,Java类中的字段数量是有限制的(类文件格式有绝对限制为65535,实际上比这个要低,因为每个字段都必须有名称和类型,这也在类中文件格式,并且会比这更快地达到其他限制)。因此问题不会出现在“普通”系统上,例如运行 Sun/Oracle VM 的 Linux。这主要是 VM 实现者必须意识到的。
所以我的建议是将其视为NullPointerException一个严重的错误,就像缓冲区溢出(IndexOutOfBoundsException在 Java 中)一样。VM 安全将帮助您调试代码(堆栈跟踪非常方便),如果您在部署之前没有进行足够的调试,它可能会节省您的皮肤。但是一个错误就是一个错误。
如果您尝试使用为空的指针,Java 将抛出NullPointerException。由于这是一个 RuntimeException,因此您不必捕获它,但您可以。所以例如
String iAmNull = null;
iAmNull.trim();
将抛出 NullPointException 并退出程序。但是,如果你抓住它
try {
String iAmNull = null;<br>
iAmNull.trim();<br>
} catch (NullPointerException e) {
log.warn("Null pointer in method x")
}
它将继续运行并简单地记录错误(如果您当然设置了记录器)。或者,也可以捕获Exception e。
Java中基于空指针的攻击理论上是不可能的,因为Java虚拟机处理所有指针,所以如果你的代码中有一个NullPointer应该不是问题。
CWE-476: NULL Pointer Dereference - 指出代码执行在非常罕见的情况下是可能的,并且环境是可能的。然而,这并不是 Java 特有的。我已经检查了所有我能想到的漏洞利用网站,看看是否有任何基于空指针引用的 Java 漏洞利用,但找不到任何漏洞。
但是在环顾四周时,我在 Cert 网站上看到了这个页面 - EXC15-J。不要捕获 NullPointerException。他们指出,捕获 NullPointerException 充其量是次优的,并且代替添加检查以避免异常的速度要慢得多。因此,根据您的应用程序,这可能是您想要考虑的事情。
null在 Java 代码中取消引用 any将导致 NPE。与 C 不同,没有办法在映射内存中添加偏移量。NPE 要么被 catch 捕获,要么传递给线程的未捕获异常处理程序。
Java 中实际漏洞的一个原因是null在不应该出现的地方接受 s。跳过空变量的代码实际上比继续和 NPEing 更危险。例如,ClassLoader引用是能力,但最重要的类加载器(引导类加载器)通常由null(如果提供的类加载器引用是,一些 Java API 添加额外的安全检查null)。