NULL 取消引用的安全隐患

信息安全 应用安全 攻击 源代码 C
2021-09-07 21:53:57

假设我们有这样的代码:

struct somedata {
   int a;
   int b;
};
struct somedata *data;
/* ... */
data = malloc(sizeof(struct somedata));
data->a = something;

现在,如您所见,缺少 NULL 指针检查。问题是 - 如果 malloc 失败,这是否有安全隐患?让我们假设在这种情况下,在 SEGV 上退出的进程本身不是问题。从安全的角度来看,还有其他方法可以解决这个问题吗?包含此代码的应用程序不是 SUID 或具有任何提升的权限,但确实处理外部输入,因此其内存的某些部分可以由用户控制。

PS我知道CWE-476,但安全隐患以非常模糊的方式描述(“在非常罕见的情况和环境中,代码执行是可能的” - 哪些情况?哪些环境?多么罕见 - 流星击中你 -头脑中的稀有还是一年一次的稀有?)我想看到一些关于威胁是什么的更具体的信息。

2个回答

“在这种情况下,在 SEGV 上退出的进程本身不是问题”:这已经是一个很大的假设。无论进程在做什么都不会完成;调用者得到一个错误代码;如果进程创建了临时文件,那么这些文件不会被删除。确保确实没有问题是棘手的。

此外,创建 SEGV 的是对操作系统故意标记为无效的内存区域的访问;即,地址空间的第一个“页面”(PC 上的页面为 4096 字节)。考虑以下:

data = malloc(1000000 * sizeof(struct somedata));
data[800000].a = something;

如果struct somedata长度为 8 字节,并且分配失败,则代码将尝试在地址 +6400000 处写入内容。即使操作系统没有映射前 4096 个字节,地址 6400000 也很可能是有效的并用于其他东西,它会被静默地覆盖。到那时,任何事情都会发生。同样,要知道返回的给定 NULLmalloc()是否意味着立即的段错误或静默损坏可能很困难。

如果进程没有特殊权限并且攻击者已经有能力以相同的权限运行可执行文件,那么不检查返回的值malloc()并不会发现新的安全问题。这只是草率。

在内核代码中,这个错误是一个严重的漏洞用户代码可以请求重新映射从地址 0 开始的页面,并且该映射也将应用于内核代码。因此,如果发生这种情况,内核现在正在读取(或写入)用户控制的内存,而不是内核控制的内存,这可能会违反内核计算的完整性(或机密性)。例如,如果内核从这个页面读取一个指针,然后取消引用它,就会发生非常糟糕的事情。因此,这种错误可以实现权限提升,使恶意的非 root 用户进程能够攻击内核并做不应该被允许做的事情。

在用户级应用程序代码中,此错误通常不是安全问题,因为如果没有应用程序的合作,攻击者无法重新映射零页。(例外:有一些应用程序会故意重新映射从地址 0 开始的页面。例如,我在想 Wine。我不知道这些特殊应用程序是否存在任何安全隐患。)

感谢@this.josh 提供了内核级代码漏洞解释的链接。