由于这篇有关内核地址空间布局随机化(KASLR)的文章不仅涉及对该功能本身的评论,而且还涉及对商业防御安全状态以及安全社区和最终用户如何对其进行评估的评论,因此我问PaX团队为讨论提供了一些有价值的内容。作为2001年ASLR的创建者,他分享了当时ASLR的一些历史和动机。他的漏洞利用向量分类和ASLR分析涵盖了“绕过”弹幕中丢失的重要细微差别和基本真相。在行业中。稍后,我将在标题“为什么KASLR失败”下更深入地继续。
在谈论KASLR之前,似乎该重新回顾一下有关ASLR本身的一些历史了。大约12年前,PaX已经证明实际上存在一种防止代码注入攻击的实用方法,这是当时针对内存破坏bug的流行攻击技术(甚至在今天,由于JIT编译器引擎的广泛使用)。同样清楚的是,双方的下一步都将集中在执行已经存在的代码上,尽管顺序不是被开发的应用程序的程序员所希望的(市场名称是ROP / JOP / etc)。那时的相关性要差得多,但是总有可能仅通过更改数据而不直接干扰程序逻辑来利用这些错误(仅数据攻击,[1] [2])。预见到实用漏洞利用技术的这些未来发展,使我思考,是否有某种通用的方法可以防止它们,或者至少降低其有效性,直到可以针对其余漏洞利用技术开发出特定的可靠和实用的防御措施(很明显,此类防御措施不会&# 39; t与不可执行的页面一样容易获得,而且,可惜的是,在2013AD,没人能展示更多内容。换句话说,ASLR一直被认为是一种临时措施,它的生存期对它的有用性远不及我们无法采取集体行动并开发/部署针对其余漏洞利用技术的实际防御措施要重要得多。
无论如何,ASLR的概念因此而诞生,最初被称为(可能整整一个星期;)用于地址空间随机化的ASR(概念实现的第一个证据实际上是对每个mmap调用进行了随机化,因为这是最简单的实现)。
这个概念真的很简单:通过在每个进程的基础上随机分配内存地址,我们会将需要硬编码地址的所有其他可靠漏洞利用变成了概率漏洞,其中成功的机会部分由防御方控制。尽管ASLR在概念和实现上都很简单,但它并非没有条件,让我们简要地了解一下它们。为了使ASLR成为有效的预防措施,必须满足以下条件:
1.漏洞利用程序必须从被利用的进程中知道地址(此处只有一点点灰色阴影,因为根据情况的不同,对部分地址的了解可能就足够了(请考虑部分或不对齐的覆盖,堆喷射), “地址”旨在涵盖“完整”和“部分”条件),
2.漏洞利用程序一定不能发现此类地址(通过让被漏洞利用的应用程序泄漏这些地址或通过暴力枚举所有可能的地址)
在某些情况下,这些条件并非一成不变,但在实践中,我们可以采用一些启发式方法:
1.远程攻击:按设计,这是ASLR的主要保护域,因为如果攻击完全需要地址,这将使攻击者获得最少的先验信息。它还在攻击方的信息泄露错误以及在防御方的信息泄漏和强力防止机制方面给予了很高的重视。
-内核错误:比起攻击用户态,通常最好攻击内核(沙盒的广泛使用通常使之成为阻力最小的路径),而用户态ASLR仅扮演次要角色。特别是,只有在利用内核漏洞需要用户域内存参与的情况下,它才面临挑战。由于Intel(Haswell)和ARM(v6 +)CPU允许有效的用户域/内核地址空间分离,该技术的生命周期大大缩短。
-信息泄漏:生活中一个可悲的事实是,当代的操作系统具有设计上的全部功能,这些功能可提供漏洞利用程序所需的地址信息,并且它几乎是一种mol鼠游戏,试图找到并消除它们。即使已经修复了这种有意的泄漏,或者至少在附近解决了这些漏洞,仍然存在内核错误,这些内核错误将内核或用户域地址泄漏回了攻击者。消除这些问题尚未得到很多研究,最先进的技术是grsecurity,但是在这一领域还有许多工作要做。
那么,KASLR与这一切有何关系?首先,名称本身有点不幸,因为被随机分配的名称与用户区中所发生的并不完全相同。对于一个用户来说,ASLR可以说是一成不变的。也就是说,正确的ASLR实现会随机化所有内存区域,并且会对每个新进程进行不同的处理。因为内核一旦启动,就不会更改其在内存中的位置,也不存在等效的内核机制,而且在每个系统调用或其他更粗粒度的边界上对其进行重新随机化在实践上都是可行的。换句话说,就好像在用户国中,我们将ASLR应用于单个进程并无限期地运行它,以希望不会发生任何不良情况。以这种速度,我们也可以调用Linux KASLR中已存在很久的可重定位内核功能,因为在启动时在其中随机指定一个新的随机选择的加载地址很简单。
其次,由于地址空间大小和内存管理硬件限制,可应用于内核映像基址的随机化量非常小,良好的userland ASLR实现至少提供了我们在KASLR中看到的熵的两倍。实现。为了平衡这种缺陷,通常已经存在某种形式的无意蛮力阻止,因为大多数内核通常无法从失败的利用尝试的副作用中恢复(Linux及其oops机制在这里是一个例外)。
第三,可能也是KASLR的最大问题是它对最小量信息泄漏的敏感性,所有内核中存在的大量信息泄漏错误以及几乎完全没有针对此类泄漏的预防机制。
之所以会出现这种情况,是因为从历史上看,直到最近才对发现此类bug毫无兴趣,更不用说系统地消除它们或防止它们的影响了(除了在诸如grsecurity之类的加固系统上,尽早认识到这一事实是我们一直在努力的原因。在这个问题空间上已有很多年了)。根据我们在Linux上的经验,这将是一场旷日持久的艰苦战斗,直到找到此类错误或至少在基于KASLR的内核中消除这些错误为止。
Warning: Can only detect less than 5000 characters
在[10] [11]之前,我们已经看到了这种货物崇拜的安全性,它假定将复制技术复制到不同的环境中,并通过一种事后,人为错误的逻辑谬误进行复制,假设该技术在其新环境中将提供同样的安全性。 kptr_restrict sysctl当前存在于上游Linux内核和大多数现代发行版中。它源自我的GRKERNSEC_HIDESYM功能,由Dan Rosenberg上游提交[12]。该功能的目的是不通过/ proc接口,符号列表等将内核指针泄漏给用户区。尽管GRKERNSEC_HIDESYM的配置帮助明确提到了三件事,要使该功能完全有用,必须保持正确,其中包括如果内核不是由发行版编译的,并且磁盘上的内核和相关模块等对非特权用户不可见,您将注意到,在提交消息或kptr_restrict的内核文档中没有任何地方提及其功效的资格。那么,作为结果,我们会看到什么呢?以Ubuntu [13]:
当攻击者尝试开发“在任何地方运行”时,利用内核漏洞,他们经常需要知道内部内核结构的位置。通过将内核地址视为敏感信息,常规本地用户看不到那些位置。从Ubuntu 11.04开始,/ proc / sys / kernel / kptr_restrict设置为" 1"。阻止报告已知内核地址泄漏。此外,只有root用户才能读取各种文件和目录:/boot/vmlinuz*、/boot/System.map*
所有这些文件都完全无用,因为任何文件(包括攻击者)都可以公开使用。虚假的安全性也随之蔓延。
KASLR是一个易于理解的隐喻。甚至非技术用户也可以理解移动目标难以攻击的概念。但是,由于在任何上下文中都没有使用首字母缩写词并考虑了其局限性,因此我们看不到这个移动目标仅移动一次并且很容易发现的事实。我们忘记了,ASLR的吸引力在于其成本/收益比,不是因为它的高收益,而是因为它的成本低。当我们考虑所有弱点(包括引发了整个辩论的论文中提到的旁道攻击[14])时,花费并不会太低,由于各种原因,本文中未涉及到这些攻击,主要是因为我没有这样做不想让许多乐观主义者从坚定的信念中跳出来,他们认为这些是此类问题中唯一可以解决的问题[15]。 KASLR更像是一种营销工具(很像行业其他部门的关注重点),而不是真正的防御手段。存在许多其他策略来处理KASLR声称要解决的问题。要使用PaX团队的一些措辞,推理的路线是:我们需要做些事情。 KASLR是什么。让我们做KASLR。 "加大攻击力度"不是对辩护的有效描述。这也总比没有好。在安全领域中可以接受的借口。如果是这样,那么我们需要放弃门面,承认这些从根本上破坏了的伪缓解仅是混淆,旨在使公众有安全感,同时确保各种漏洞利用交易者仍然可以从中获利。许多弱点。
考虑一下我们的情况,我告诉过你了。我们希望您会在接下来的几年里记得,因为KASLR已被“打破”。一次又一次地。再说一次,在这个以进攻为导向的行业中,钱就在那儿,不是吗?