Windows文件系统驱动开发挑战:NTFS安全描述符继承漏洞解析
一条来自@jonasLyk的推文让我想起了几个月前在NTFS中发现的一个漏洞,经核实该漏洞在Windows 10 2004版本中仍然存在。虽然这个漏洞不能直接用于绕过安全机制,但很可能被利用在攻击链中。NTFS很好地展示了在Windows上编写文件系统驱动程序的复杂性,因此随着时间的推移出现各种奇怪的边界情况并不令人意外。
这个问题的核心在于创建新目录时的默认安全描述符(SD)分配机制。如果你了解Windows安全描述符,就会知道可以通过CONTAINER_INHERIT_ACE
和/或OBJECT_INHERIT_ACE
标志来指定继承规则。这些标志决定了当新条目是目录或文件时,是否应该从父目录继承ACE。
让我们看看NTFS用于为新文件分配安全性的代码,看看你能否发现这个bug:
|
|
这段代码使用SeAssignSecurityEx
基于父SD和调用者提供的显式SD来创建新的安全描述符。要使继承生效,不能指定显式SD,因此我们可以忽略这一点。SeAssignSecurityEx
是否应用目录或文件的继承规则取决于IsDirectoryObject
参数的值。如果向NtCreateFile
传递了FILE_DIRECTORY_FILE
选项标志,则该参数设置为TRUE。看起来没问题:如果不指定FILE_DIRECTORY_FILE
标志,就无法创建目录;如果不指定任何标志,默认会创建文件。
但等等,这完全不对。如果你指定了形如ABC::$INDEX_ALLOCATION
的名称,那么无论指定什么标志,NTFS都会创建一个目录。因此,这个bug就是:如果你使用$INDEX_ALLOCATION
技巧创建目录,新的安全描述符将按照文件而不是目录的方式继承。我们可以在命令提示符下验证这种行为:
|
|
首先我们创建一个目录ABC并授予两个ACE:一个用于INTERACTIVE组将在目录上继承,另一个用于NETWORK将在文件上继承。
|
|
然后我们使用$INDEX_ALLOCATION
技巧创建子目录XYZ。我们可以确定它成功了,因为CMD在尝试将"Hello"写入目录对象时打印了"Incorrect function"。
|
|
转储XYZ子目录的安全描述符,我们看到ACE是基于文件而不是目录继承的,因为我们看到了NETWORK的ACE而不是INTERACTIVE的ACE。最后我们列出ABC来确认它确实是一个目录:
|
|
这个漏洞有用吗?老实说可能没什么用。我能想象的唯一场景是:如果你可以向系统服务指定一个路径,该服务在某个位置创建文件,其中继承的文件访问权限会授予访问权,而继承的目录访问权限不会。这将允许你创建一个可以控制的目录,但说实话这似乎有点牵强。如果有人能想到这个漏洞的好用途,请告诉我或微软:-)
尽管如此,有趣的是这是另一个案例,说明在确定对象是目录还是文件时,$INDEX_ALLOCATION
没有被正确验证。另一个很好的例子是CVE-2018-1036,你可以在只有FILE_ADD_FILE
权限的情况下创建新目录。为什么在设计上决定在使用流类型时自动创建目录,这一点尚不清楚。我想我们可能永远不会知道。