深入解析被误解的SeRelabelPrivilege权限
基于我之前的博客文章,我最近与一位朋友(也是著名的Windows安全研究员)讨论了令牌权限。具体来说,我在思考SeTrustedCredmanAccessPrivilege为何不是“上帝”权限。经过一番交流后,我们发现彼此的理解存在偏差。我认为“上帝”权限是指内核认为会使令牌提升的权限(参见《绕过UAC的阅读方法(第三部分)》),因此不会提供给任何完整性级别低于高的令牌。而对方则认为,这种权限是启用后可以直接危害资源或整个操作系统的权限,这可能包括从内核角度严格来说不是“上帝”但仍允许系统被攻破的权限。
意识到这一误解后,我仍然惊讶地发现,对方列表中的某个权限并未被视为“上帝”权限,特别是SeRelabelPrivilege。似乎对于这个权限实际允许的操作存在一些混淆,因此我认为有必要澄清一下。
技术细节说明
首先,我认为说资源具有完整性级别是不准确的。相反,资源有一个强制标签,存储在SACL的ACE中。该ACE包含一个SID,映射到完整性级别和一个存储在访问掩码中的强制策略。完整性级别和策略的组合决定了授予的访问权限(尽管不能通过策略授予“写”权限)。另一方面,令牌确实具有完整性级别和单独的强制策略,这与ACE中的策略不同。奇怪的是,在调用SetTokenInformation时,使用TOKEN_MANDATORY_LABEL结构指定该值,这确实令人困惑。
SeRelabelPrivilege的官方文档
与许多不常使用的权限一样,官方文档并不完善。你可以在MSDN找到相关文档。该页面比通常更糟,因为它似乎是在Vista/Longhorn开发期间编写的,当时强制完整性控制(MIC)(或称为Windows完整性控制(WIC))功能仍在变化中。例如,它提到了一个高于系统的完整性级别,称为Installer。推测Installer是最初阻止管理员修改系统文件的想法,后来被TrustedInstaller SID作为所有者所取代(参见之前的博客文章)。Vista中有一个高于系统的级别,称为受保护进程,但由于受保护进程使用不同的机制实现,因此不可用。
SeRelabelPrivilege的实际功能
从文档中提炼出该权限的功能,它允许两个操作。首先,它允许你将强制标签ACE中的完整性级别设置为高于调用者令牌的完整性级别。通常,只要授予你对资源的WRITE_OWNER访问权限,你就可以将标签的完整性级别设置为小于或等于调用者完整性级别的任何值。
例如,如果你尝试将资源的标签设置为系统,但调用者仅处于高完整性级别,则操作将失败,并返回STATUS_INVALID_LABEL错误。如果启用SeRelabelPrivilege,则此操作将成功。
注意,该权限不允许你提升令牌的完整性级别,你需要SeTcbPrivilege来实现这一点。即使将完整性级别提升到小于或等于调用者完整性级别,如果没有SeTcbPrivilege,操作也只能降低令牌中的级别。
第二个操作是你可以降低标签。通常,你可以在没有该权限的情况下降低标签,除非资源的标签高于调用者。例如,你可以将标签设置为低,无需任何特殊权限,只要你对句柄具有WRITE_OWNER访问权限且当前标签小于或等于调用者的标签。然而,如果标签是系统且调用者是高完整性级别,则他们无法降低标签,此时需要该权限。
文档的混淆之处
文档中有这样一段话(强调是我的):“如果恶意软件被设置为提升的完整性级别,如Trusted Installer或系统,管理员账户没有足够的完整性级别来从系统中删除程序。在这种情况下,需要使用修改对象标签权限来重新标记对象。但是,重新标记必须通过使用与您尝试重新标记的对象相同或更高完整性级别的进程来进行。”
这是一个非常令人困惑的段落。首先,它表明管理员无法删除具有Trusted Installer或系统完整性标签的资源,因此需要该权限来重新标记。然后它说,进行重新标记的进程必须具有更高或相等的完整性级别才能进行重新标记。如果是这种情况,你就不需要该权限。也许强制标签的原始设计更加严格,比如无论当前值如何,你总是需要SeRelabelPrivilege来降低标签?
默认权限分配与实际影响
无论如何,默认获得SeRelabelPrivilege的唯一用户是SYSTEM,其默认完整性级别为系统,这已经是允许的最高级别,因此该权限的行为似乎几乎无关紧要。无论如何,由于它是“上帝”权限,如果令牌的完整性级别低于高,它将被禁用,因此这种降低操作很少有用。
这引出了最被误解的部分,如果你仔细看,可能会从权限的文档中 grasp 到。降低资源标签的能力主要取决于调用者是否能获得对资源的WRITE_OWNER访问权限。然而,WRITE_OWNER访问权限通常是通用映射中GENERIC_ALL的一部分,这意味着无论DACL如何或他们是否是所有者,它都不会授予给完整性级别较低的调用者。
SeRelabelPrivilege的独特之处
该权限带来的有趣之处在于,它允许调用者绕过对WRITE_OWNER的MIC检查。这使得调用者可以打开具有更高标签的资源以进行WRITE_OWNER,然后将其标签更改为任何级别。这与SeTakeOwnershipPrivilege的工作方式相同,因为它授予WRITE_OWNER而不检查DACL。然而,如果你使用SeTakeOwnershipPrivilege,它仍然会受到MIC检查,如果标签高于调用者的完整性级别,则不会授予访问权限。
设计问题与总结
该权限的问题在于MIC的设计,特别是WRITE_OWNER被重载以允许设置资源的强制标签,同时也用于设置所有者的传统用途。一旦访问被授予,内核无法区分这两种操作(或者至少它没有尝试区分)。
当然,对可以授予WRITE_OWNER访问权限的资源类型是否有限制?没有,似乎即使调用者对资源没有任何访问权限,它仍然会被授予WRITE_OWNER访问权限。这使得SeRelabelPrivilege与SeTakeOwnershipPrivilege完全相同,但增加了绕过MIC检查的功能。总结来说,启用SeRelabelPrivilege的令牌可以获取任何它想要的资源的所有权,即使该资源的标签高于调用者。
验证与实例
你当然可以自己验证这一点,这里有一些使用NtObjectManager的PowerShell脚本,你应该以管理员身份运行。该脚本创建一个不授予SYSTEM任何访问权限的安全描述符,然后尝试在没有和有SeRelabelPrivilege的情况下请求WRITE_OWNER。
|
|
实际应用场景
如果你读到这里,这个权限有什么实际有用的场景吗?通常具有提升标签的资源是进程和线程。你已经可以使用SeDebugPrivilege绕过MIC检查。当然,该权限的使用可能被严密监控,因此你可以滥用此权限通过更改所有者为调用者并降低标签来获得对提升进程的完全访问权限。一旦你成为所有者且标签较低,你就可以修改DACL以直接授予完全访问权限,而无需SeDebugPrivilege。
然而,由于只有SYSTEM默认获得该权限,你需要模拟令牌,这可能只是允许你访问进程。因此,除非你查看的系统已将其授予服务账户,从而可能为逃逸到SYSTEM打开一扇门,否则它大多是一个无用的特性。