悬空指针可能不会像以前那样产生那么多的安全问题,但这种常见的编程错误仍然可能导致系统崩溃并构成严重威胁。
十几年前,悬空指针被认为是质量控制问题,而不是安全问题。例如,在 2005 年,Microsoft 收到 Internet Information Services 5.1 中一个悬空指针的警报,但它在两年内一直没有打补丁。
随着越来越多的应用程序连接到互联网,悬空指针问题也随之增加。
然而,今天,大多数现代软件应用程序是使用使用自动内存管理来防止悬空指针的编程语言开发的,比如c#、Java和Ruby。然而,许多用旧语言编写的遗留系统仍然连接到互联网,如果软件中的编码错误产生悬浮指针,它们仍有受到攻击的风险。
什么是悬空指针,它是如何发生的?
指针是编程语言中的一个变量,用于存储另一个值的内存地址。它引用或指向另一个内存地址。
当程序员在内存中创建、使用并释放对象,但不相应地更改对象的指针值时,就会发生悬空指针 -- 在本例中,指向 null 指针。相反,指针错误地引用了已释放内存的内存位置。指针被认为是“悬空的”,因为它指向可能不再包含有效对象的内存。由于内存可能包含完全不同的数据,因此当程序员错误地取消引用指针以访问对象时,可能会导致不可预知的行为。
下面是创建悬空指针的代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 2: void main()
{
char* name = (char *) malloc(20);
execute some code
free(name);
}
第 5 行声明了一个char类型的指针“name”,该指针指向可以存储 20 个字符的内存块。在第 7 行,它指向的内存块被释放,使指针悬空。这是因为它不再指向有效的内存位置,该位置可能用于其他目的。
请注意,不仅仅是不正确的释放会导致悬空指针;其他编码错误,例如过早释放和返回非静态变量的函数,也会造成错误。
2007 年,在线风险管理公司 Watchfire(现为 IBM 的一部分)的专家找到了一种方法,可以控制悬空的指针并将它们指向特定的内存位置。通过向服务器发送特制的URL,研究人员Jonathan Afek和Adi Sharabani发现,他们可能会使目标机器崩溃,并在其上运行自己的shellcode。使用此方法,攻击者可以远程控制或感染在其应用程序中有一个悬空指针的任何计算机,其方式与攻击者利用缓冲区溢出漏洞的方式大致相同。
缓冲区溢出攻击具有严重的破坏性和有效性。当攻击者干预计算机内存时,可能会导致数据结构损坏、信息泄漏、特权升级和恶意代码的执行。
悬空指针可能在大多数成熟的应用程序中找到,但攻击者会专注于任何连接到互联网的应用程序,以提供访问敏感数据的潜在途径或被招募到僵尸网络中。
如何避免悬空指针
悬空指针并不是编程语言的固有错误,但它们很难定位,因为它们经常破坏不相关的数据,或者在创建后很长一段时间内导致系统不稳定。
这些错误在一些语言中经常出现,例如 C 和 C++。在语言如 Java 和 C#中,不会出现悬空指针。在这里,指针是自动管理的,并且在消除对象时会发生隐式垃圾回收。使用没有某种形式的指针自动处理的语言的开发人员需要重新评估其应用程序开发过程。使用后需要将所有指针设置为空指针。
智能指针是常用的数据类型,可以更好地管理内存。智能指针通常使用引用计数来回收对象。引用计数机制会计算引用同一对象的智能指针,一旦计数等于零,该对象就会被删除。
其他一些防御措施包括墓碑方法和锁钥法。一旦对象失效,关联的逻辑删除就可以自动使引用它的任何指针无效。在锁-键方案中,指针访问是通过比较一对有序键的两个值来确定的。
悬空指针不是一个良性问题。开发人员应该调整其软件开发过程,以纳入静态代码分析工具和内存分析器的使用,以识别未初始化的指针和其他可能不正确的内存管理技术,并帮助防止悬空指针到达生产代码。
由于问题可能会变得过于严重,不能留到质量控制阶段,因此在开发生命周期的早期采取保护措施。
参读链接: