“nfs”文件系统的mount()系统调用存在双重获取漏洞。
理论上,Double Fetch是一个有条件的竞争漏洞,这是一场内核模式和用户模式之间的数据访问的较量。Double fetch类型漏洞产生于多线程数据访问时,并且没有做必要的安全同步措施。多线程时,对同一数据一个线程读一个线程写,可能引起数据访问异常,而这个异常如果能被利用,这就是一个漏洞。在现代操作系统(如linux和BSD衍生产品)中,虚拟内存位置通常是在内核空间和用户空间之间进行分区的。有关双重获取漏洞的更多信息请点击这里。
第一次获取发生在“this ”实例中。在这个示例中,将在NFS中解析外部数据表示(XDR)变量。你现在可能在想XDR到底是什么?外部数据表示(XDR)是一种只能用于描述数据的数据格式描述语言。它根本不是一种编程语言。这种语言允许你以清晰和简洁的方式描述复杂的数据格式。XDR“编程”语言类似于C编程语言,NFS和其他协议使用XDR来描述其数据的格式。
因此,本质上,他们从用户区复制所有XDR变量的长度,然后对刚从用户区复制的arglength变量进行大小检查:
所以显然 argslength 不能大于 (16*1024 = 16384);。这很好,它很可能只是一个标准。之后它会四舍五入 argslength 并分配一个 xdrbuf:
因此,在分配这个缓冲区后,他们尝试从用户空间的第1920行复制所有XDR参数:
这会将所有参数从 data 复制到 argslength 到新分配的 xdrbuf。完成后,这将传递给 mountnfs 函数:
好,我们来看看mountnfs函数!它接受研究人员们的xdrbuf作为参数。
在这个块中,它将使用xb_init_buffer函数初始化xb。因此,xb 属于 struct xdrbuf 类型。让我们先看一下这个定义的上下文。
研究人员们可以看到,这个结构将在xb_init_buffer中初始化,所以让我们也来看看:
所以这个 bzero 是整个 xdrbuf 结构并将类型设置为 XDRBUF BUFFER,然后它将缓冲区的基地址设置为从用户空间复制的 xdrbuf,将缓冲区的大小和数据的长度设置为 XDRword 的 2 倍,它等于 8,它初始化了一些指向研究人员的 xdrbuf 的指针。一旦 xdrbuf 结构被初始化,他们将继续使用 xb_get_32 从结构的指针中获取一些 32 位数据到研究人员的 xdrbuf。他们将使用它来获取版本和 argslength。请注意,这个 argslength 是 xdrbuf 中的一个 XDR 变量,它在第二次 copyin 调用期间被复制到内核空间中。这表明恶意线程可以在第 1902 行的第一次获取和第 1920 行的第二次获取之间操作用户空间中的 argslength 变量。
之后,他们将使用 xb_init_buffer 以研究人员在用户空间中更改的恶意大小重新初始化 xdrbuf 结构,尽管自使用 xb_malloc 分配以来 xdrbuf 的实际大小没有改变。然后恶意攻击者可以利用它来导致内存损坏错误。
现在研究人员们知道了漏洞是如何运作的,那这个漏洞是如何解决的?研究人员检查了第二次获取的arglength是否与第一次复制的arglength相同。在这种情况下,研究人员认为这是一个可行的解决方案。
目前研究人员已经将该漏洞的修复信息反馈给了苹果公司,并希望苹果能改变他们处理这类漏洞的方式。在研究人员看来,苹果管理此类漏洞的方式是人们考虑将漏洞出售给像Zerodium这样的第三方供应商的主要原因。