PrivEsc Abusing the Service Control Manager for Stealthy & Persistent LPE
利用系统自带工具
本周早些时候,Grzegorz Tworek[1]发布了一个非常巧妙的建立持久性本地权限提升的方法,这种方法我此前从未在野外见过[2]。通过一个(已被入侵的)特权账户,我们可以滥用服务控制管理器,使用sdset
向服务控制管理器提供过度宽松的访问控制列表(ACL),从而允许任意非管理员用户在机器上持续拥有完整的SYSTEM权限。
一些背景知识
要理解这种攻击方式,需要简单了解sdset[3]以及微软的安全描述符定义语言(SDDL[4])。简而言之,安全描述符字符串包含用于表示安全描述符四个主要组成部分的标记:所有者(O:)、主要组(G:)、DACL(D:)、SACL(S:),以及访问控制实体的标记。安全描述符可以包含这些标记的任意组合,并且如下文所示,并非所有标记都是必需的。
根据推文所述,我们只需要在提升权限的 Windows 命令行(即具有本地管理员权限的命令行)中运行sc.exe sdset scmanager D:(A;;KA;;;WD)
。在演示整个攻击过程之前,让我们先深入分析一下这个命令。
D:(A;;KA;;;WD) ... 这是什么?
如果你和我一样,对这些微软 SDDL 标记的工作原理或每个部分代表的含义知之甚少,我们应该花点时间来深入了解。(你知道的,学习新知识总是好事)
那么这个字符串究竟代表什么?让我们逐个分析各个组成部分。首先,我们应该了解访问控制条目的基本语法:
ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;(resource_attribute)
-
D: 自由访问控制列表(DACL) -
DACL 标识允许或拒绝访问对象的用户和组。 -
A; 允许访问( ace_type
) -
这第一段表示访问控制条目(ACE[5])的开始。ACL 包含 ACE 列表。ACE 为特定用户或组定义对对象的访问权限,或定义为特定用户或组生成系统管理消息或警报的访问类型。用户或组由安全标识符(SID)标识。 -
ace_flags
为空 -
KA; KEY_ALL_ACCESS( rights
) -
在 SID 上下文中使用时,这个标记也可以指代域密钥凭据管理员,这确实有点令人困惑。我们只需要知道这赋予了与 SDDL 相关的所有注册表键的访问权限。 -
object_guid
为空 -
inherit_object_guid
为空 -
WD - Everyone 安全主体( account_sid
) -
下面你会找到一个表格,列出了 SDDL 字符串中可以引用的一些常见安全主体。
ACE 安全主体
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
简而言之
简单来说,这个命令授予了所有人对服务控制管理器的所有权限。这意味着,我(作为非特权用户)可以创建一个服务,由于scmanager
在SYSTEM上下文中运行,该服务将允许我以 SYSTEM 权限执行任意命令。如果你想了解更多技术细节,可以阅读这样的文章[6]。
攻击流程示例
检查普通用户的权限
首先,我们使用一个非特权账户并输出用户信息。这里我只是演示我们将要进行权限提升的账户没有管理员权限。
通过 SDSET 修改 SCMANAGER 的权限
接下来,我们从提升权限的命令提示符执行命令来修改scmanager
ACL。这必须使用管理员账户(已被入侵的账户)来完成:
检测机会
对服务控制管理器的 ACL 修改应该受到严格审查。以下是用于检测本文 POC 行为的示例 sigma 规则:
title: DACL Modification of Service Control Manager via sdset
id: 8998782b-66de-44e7-8335-305e2dd431b3
status: experimental
description: This rule detects usage of sdset to modify the DACL of the service-control manager service, scmanager.
references:
- https://twitter.com/0gtweet/status/1628720819537936386?cxt=HHwWhIC87Ze9sJotAAAA
tags:
- attack.persistence
- attack.privilege_escalation
author: Gabriel De Jesus (0xv1n)
date: 2023/02/28
logsource:
product: windows
category: process_creation
detection:
selection:
Image|endswith:
-'sc.exe'
CommandLine|contains|all:
-' sdset '
-' scmanager '
-' D:(A;;KA;;;WD) '
condition: selection
fields:
- Image
- CommandLine
falsepositives:
-Unknown
level: high
确认更改已生效
通过操作系统返回的反馈,我们知道命令执行成功了,但如果我们想要检查服务的安全描述符,可以使用 sdshow <service_name>
命令。在这个案例中,我们确认 scmanager
确实已经具有了新的安全描述符。
此外(感谢 Grzegorz!),我们可以运行 sc.exe sdshow scmanager showrights
来枚举服务的权限。这实际上是将令牌映射到它们的安全描述符,让我们能够更容易地理解特定服务所具有的权限:
创建恶意服务以实现持久化的本地权限提升
现在我们可以从我们的非特权账户创建一个服务,将我们的账户添加到这台机器的本地管理员组中:
sc create LPE displayName= "LPE" binPath= "C:WindowsSystem32net.exe localgroup Administrators nonpriv-user /add" start= auto
重启机器
此时,我们只需要重启机器,让服务控制管理器以SYSTEM权限执行我们的新服务。一旦机器重新上线,我们应该可以看到我们的账户已被添加到本地管理员组中。
这种机制最好的部分在于,即使一个聪明的管理员删除了账户的本地管理员权限,我们仍然保留着这个服务。如果管理员删除了这个服务,我们依然有能力创建一个新的。要修复这种持久化,需要将scmanager
的 DACL 恢复到加固状态。
持久化的本地权限提升
现在,我们随时都可以以管理员权限启动任意进程:
希望这些内容对你有帮助!
参考资料
Grzegorz Tworek: https://twitter.com/0gtweet
[2]非常巧妙的建立持久性本地权限提升的方法,这种方法我此前从未在野外见过: https://twitter.com/0gtweet/status/1628720819537936386?cxt=HHwWhIC87Ze9sJotAAAA
[3]sdset: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc742037%28v=ws.11%29
[4]SDDL: https://go.microsoft.com/fwlink/?LinkID=570
[5]ACE: https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/ace
[6]这样的文章: https://learn.microsoft.com/en-us/windows/win32/secauthz/ace-strings
原文始发于微信公众号(securitainment):滥用服务控制管理器实现隐蔽和持久的本地权限提升
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论