Windows 服务的账户选定——LocalSystem、虚拟账户与 gMSA 的取舍
· 更新日期: · Go Komura · Windows, Windows 服务, 服务账户, gMSA, LocalSystem, 虚拟账户, 安全, Active Directory, 最小权限
更新记录(仅首版,2026年08月20日 发布)
- 首次发布
引用本文(DOI(已登记存档): 10.5281/zenodo.22176397)
以下 DOI 指向先前登记的存档,内容可能与当前正文不同。引用当前正文时,请使用本页网址。
Go Komura(2026)。《Windows 服务的账户选定——LocalSystem、虚拟账户与 gMSA 的取舍》。小村软件有限公司。 https://comcomponent.com/zh-CN/blog/windows-service-accounts-gmsa-guide/
- DOI(已登记存档)
- 10.5281/zenodo.22176397
- DOI(上次登记版本)
- 10.5281/zenodo.22176398
“以 LocalSystem 运行的服务,在审计中被指出权限过大。该改成什么?”“为了连接共享文件夹而使用域用户,但密码过期会让服务停掉。”——这两类是典型的咨询,都出现在服务的运行账户不是设计决策,而是被“碰巧能跑的配置”固定下来的时候。
选择运行账户时,要把在本机内能做什么、从目标端看被识别为谁、密码由谁管理分开考虑。把本地权限调强,和能够通过身份验证连上共享文件夹,并不是一回事。12
本文的结论是:在单台机器内完成处理的业务服务以虚拟账户为第一候选,域内需要服务专属身份时以 gMSA 为第一候选。把“不让服务持有人用密码”的配置作为基本做法,域用户作为最后手段。不过不要把既有服务一律立刻变更,而要确认所需权限和迁移时的影响。34
本文面向中小企业的信息系统负责人和 Windows 应用开发者。原文基于 2026 年 8 月时点的 Microsoft Learn,本文按选定 → 本地权限 → 网络身份 → 引入 gMSA → 切换与审计的顺序整理。服务本身怎么做,请参阅“Windows 服务的创建与运维”。
1. 先做选择:6 种账户和 4 个问题
1.1 比较的维度是“权限、身份、密码管理”
服务启动时,服务控制管理器(SCM)以配置的账户登录。登录成功后会把访问令牌指派给服务进程,此后对文件和管道的访问,都靠这个令牌与访问控制列表(ACL)的比对来判定。所谓选择运行账户,就是决定交给服务的令牌里有什么。1
| 账户 | 本地权限 | 网络身份 | 密码管理 | 主要适用场景 |
|---|---|---|---|---|
| LocalSystem | 几乎不受限制(SYSTEM + Administrators) | 计算机账户(PC$) | 不需要使用者配置 | 与操作系统一体运行、必须具备强特权的例外服务 |
| LocalService | 最小(相当于 Users) | 匿名 | 不需要 | 不需要网络身份的本地处理 |
| NetworkService | 最小(相当于 Users) | 计算机账户(PC$) | 不需要 | 低权限、只要有机器级身份就够用的处理 |
虚拟账户 NT SERVICE\<名称> |
最小 + 在 ACL 中逐项授予 | 计算机账户(PC$) | 不需要(自动管理) | 单台服务器上运行的业务服务的默认解 |
| 域用户 | 只有授予的那部分 | 该用户本身 | 手动。需要管理有效期、泄露和轮换 | 应用不支持 gMSA 又需要独有身份时的最后手段 |
| gMSA | 只有授予的那部分 | 该 gMSA 本身 | 由 AD 自动生成并自动轮换 | 域环境中需要服务专属身份,或多台服务器需要共同身份时 |
表中以 PC$ 进行的网络身份验证以域环境为前提。工作组中无法使用同样的方法。另外,LocalSystem 也有 WRP 保护区域等限制。请不要把“几乎不受限制”理解成字面意义上的无限制。5627
使用 LocalSystem、LocalService、NetworkService、虚拟账户时,使用者不需要为服务设置和管理密码。而使用域用户或本地用户的配置中,保存在 SCM 里的密码的有效期和变更由人来管理。gMSA 虽然密码本身存在,但把密码的管理交给了 AD。18
1.2 选定按 4 个问题推进
首先确认是否要通过 Windows 身份验证连接其他机器,如果需要,再依次判断是否加入域、机器级身份是否够用、应用是否支持 gMSA。
flowchart TB
accTitle: 运行账户的判断流程
accDescr: 依次回答是否有网络访问、是否加入域、机器级身份是否够用、是否支持 gMSA 这 4 个问题来决定运行账户
q1{"要通过 Windows 身份验证连接其他机器吗?"} -->|不需要| va["虚拟账户"]
va -.-> sys["必须有特权时用 LocalSystem"]
q1 -->|需要| q2{"加入域了吗?"}
q2 -->|否| cred["保护并保存凭据"]
q2 -->|是| q3{"机器级身份够用吗?"}
q3 -->|是| pcacl["虚拟账户 + 允许 PC$"]
q3 -->|否| q4{"应用支持 gMSA 吗?"}
q4 -->|是| gmsa["gMSA"]
q4 -->|否| du["专用用户 + 缓解措施"]
图 1:在本地就能完成的用虚拟账户。域内 PC$ 的粒度不够时,进一步走向 gMSA。工作组中要另行设计凭据。
| 想做的事、遇到的问题 | 最初的判断 | 详细阅读 |
|---|---|---|
| 在单台机器上运行普通的业务服务 | 选择虚拟账户,并授予必要的 ACL | 第 2 章 |
| 想从 LocalSystem 改掉 | 先确认是否真的需要强本地特权 | 2.3、第 7 章 |
| 想连接域内的共享文件夹或数据库 | 机器级身份够用时,考虑虚拟账户等 + 在目标端允许 PC$ | 第 3 章 |
| 想在目标端区分服务,或多台服务器使用同一身份 | 确认 gMSA 的要求以及应用是否支持 | 第 4、5 章 |
| 应用不支持 gMSA 但需要独有身份 | 把专用域用户和缓解措施组合起来 | 第 6 章 |
| 更改账户后无法启动、读不到配置 | 分开确认登录权利、ACL、配置文件和 DPAPI | 第 7 章 |
既有的由 LocalService 承担的本地处理,以及由 NetworkService 承担的机器级访问,没有理由就不必全部替换。新做选择时,以能兼顾低权限和按服务隔离的虚拟账户为基本。
图中实线表示始终成立的关系,虚线表示带条件的关系(成立条件写在详情页各关系的说明中)。关系的完整列表(共 19 条,附依据与确信度)以及主要概念的定义,汇总在知识地图详情页(日文)。数据:JSON-LD / Turtle
2. 决定机内的权限:以虚拟账户为基本
2.1 LocalService 和 NetworkService 的网络身份不同
LocalService 和 NetworkService 是为低权限服务准备的内置账户。两者在本地都以大致相当于 Users 组成员的最小权限运行。不同之处在于向远程出示的凭据。63
| 账户 | 名称与 SID | 与远程的连接 |
|---|---|---|
| LocalService | NT AUTHORITY\LOCAL SERVICE、S-1-5-19 |
使用匿名凭据。不适合访问需要身份验证的资源 |
| NetworkService | NT AUTHORITY\NETWORK SERVICE、S-1-5-20 |
使用计算机的凭据。在域内显示为 DOMAIN\计算机名$ |
不走网络、或者对方不要求身份时用 LocalService;域内需要机器身份时用 NetworkService,这就是两者的分工。
不过要注意,两者都是多个服务共用同一个账户。只要 ACL 授予的是这个共用账户,就无法按服务加以区分。如果有 5 个服务以 LocalService 运行,那么授予该账户的资源,这 5 个都能访问。SQL Server 不支持 Local Service 的原因,也是共用账户无法与其他服务隔离。3
2.2 虚拟账户可以按服务授予 ACL
虚拟账户是从 Windows Server 2008 R2 / Windows 7 起可用的受管理的本地账户。名称是 NT SERVICE\<服务名>。不需要创建账户,也不需要设置密码,每个服务都有独有的身份。域环境中的网络访问,使用计算机账户的凭据。2
也就是说,它保留了 LocalService、NetworkService“不需要管理密码”的优点,同时消除了账户被共用这个弱点。SQL Server 安装程序默认使用 NT SERVICE\MSSQLSERVER 之类的账户,用的也是这个思路。3
实际使用中的好处是可以在 ACL 中直接指定该服务。不必增加组的创建和密码管理,就能做到“把这个数据文件夹的修改权限授予这个服务”。
下面是把既有的 MyAppService 切换到虚拟账户的例子。执行前请先确认第 7 章的登录权利、数据存放位置和 DPAPI,并在验证环境确认启动和主要功能。
# 把服务的登录账户改为虚拟账户
# obj= 的值是“NT SERVICE\服务名”。不指定密码
sc.exe config MyAppService obj= "NT SERVICE\MyAppService"
# 确认配置(查看 SERVICE_START_NAME)
sc.exe qc MyAppService
# 只把数据文件夹的修改权限授予这个服务
icacls "C:\ProgramData\MyApp" /grant "NT SERVICE\MyAppService:(OI)(CI)M"
在 GUI 中,打开 services.msc 的服务属性 →“登录”选项卡,把账户名填成 NT SERVICE\服务名,并让密码栏保持为空。虚拟账户和 MSA 不指定密码。更改在重启服务后生效。3
即使在本地拥有独有的身份,也不等于在网络另一端能区分服务。这个限制将在第 3 章说明。
2.3 LocalSystem 不能因为“能跑”就选,要按所需特权判断
LocalSystem(NT AUTHORITY\SYSTEM,显示名为本地系统)是 SCM 使用的预定义账户。令牌中包含 NT AUTHORITY\SYSTEM 和 BUILTIN\Administrators 的 SID,拥有广泛的本地权限。SeDebugPrivilege、SeTcbPrivilege 等强特权默认也是启用的。5
这种强大同时也意味着被攻破时的损失规模。如果以 LocalSystem 运行的服务存在任意代码执行漏洞,就可能成为读取和篡改所有用户文件、读取其他进程内存、窃取凭据并横向移动的起点。在 NTFS 上,SYSTEM 默认拥有完全控制权限。6 凭据窃取与横向移动的关系,在“图解 NTLM 与 Kerberos”“Windows LAPS 实务指南”中也有讨论。
即便如此,LocalSystem 仍被持续选用,是因为它是 sc.exe create 省略 obj= 时的默认值,而且在老的示例代码和安装程序模板中大量残留。开发过程中不容易遇到权限错误,容易变成“能跑就先这样”。但 Microsoft 也说明,绝大多数服务并不需要这种特权级别,不需要时应考虑 LocalService 或 NetworkService。95
即使是 LocalSystem,也不是什么都能无条件更改。Windows Vista 之后的 Windows 资源保护(WRP)把重要系统文件、文件夹和注册表项的更改限制给 TrustedInstaller(Windows Modules Installer 服务)。即使是 SYSTEM 或管理员,常规的改写也会被拒绝访问。“需要来自 TrustedInstaller 的权限”就是这个机制。7
即便有这个限制,LocalSystem 对业务服务来说权限过大这一点也没有改变。合理的例外是与设备驱动程序紧密配合、操作操作系统的安全基础、管理其他服务或会话等所需特权本来就超出管理员级别的处理。备份代理和 EDR 之类就存在这种必要性。
即使属于例外,也要确认是否真的存在使用特权的代码路径,能否只把必要的部分分离出来。判断方法请参阅“Windows 什么时候需要管理员权限”。
3. 决定目标端看到的身份:PC$ 是否够用
3.1 如果只是连接共享文件夹,多数情况不需要域用户
在已加入域的机器上,使用 LocalSystem、NetworkService、虚拟账户的服务,对远程会以 DOMAIN\计算机名$ 通过身份验证。服务访问不了共享文件夹,有时只是因为目标端的 ACL 没有允许这个 PC$。52
这里需要做的不是把服务的本地权限调强,而是在目标端允许正确的身份。共享文件夹上要同时设置共享权限和 NTFS 权限。
下面是在文件服务器一侧,给 APPSV01 上的服务授予修改权限的例子。在 GUI 中选择账户时,要在“对象类型”中包含“计算机”。
# 文件服务器一侧:给 APPSV01 上的服务授予共享文件夹的修改权限
# 共享权限和 NTFS 权限两边都需要授予
Grant-SmbShareAccess -Name "AppData" -AccountName "CORP\APPSV01$" -AccessRight Change -Force
icacls "D:\Shares\AppData" /grant "CORP\APPSV01$:(OI)(CI)M"
在 SQL Server 上,把计算机账户注册为 Windows 登录名的思路也一样。连接字符串使用 Integrated Security=true,服务一侧不必持有域用户的密码就能连接。
-- 数据库服务器一侧:允许来自 APPSV01 上服务的 Windows 集成身份验证
CREATE LOGIN [CORP\APPSV01$] FROM WINDOWS;
这只是在数据库服务器一侧创建 Windows 登录名的那部分示例。在目标端授予必要的访问权限,这条原则和共享文件夹没有区别。
3.2 用 PC$ 无法做到按服务授权和审计
虚拟账户的身份是机器本地的,域并不认识它。走到网络上会汇聚成 PC$,因此仅凭账户无法区分请求来自同一台机器上的哪个服务。104
flowchart TB
accTitle: 虚拟账户的身份在机器外会收缩
accDescr: 机器内按服务独有的虚拟账户,在网络上会收缩成计算机账户,远程端分不出是哪个服务
vaa["虚拟账户 A"] --> pc["计算机账户 PC$"]
vab["虚拟账户 B"] --> pc
pc --> remote["远程端看到的身份"]
remote -.-> nodist["分不出是哪个服务"]
图 2:即使机器内能按服务隔离,在目标端看到的也是同一个 PC$。本地的隔离和网络上的隔离是两个不同的判断。
这种方式有两个局限。
| 局限 | 做不到什么 | 接下来选择的处理 |
|---|---|---|
| 身份变成机器级 | 无法在目标端对同一台 PC 上 LocalSystem、NetworkService、虚拟账户的服务逐个授权和审计 | 需要服务专属身份时考虑 gMSA |
| 以域为前提 | 工作组中没有 AD 的计算机账户,用不了 PC$ 身份验证 | 另行设计为保护并显式使用凭据,或考虑加入域 |
想在多台服务器之间共用同一身份时,各台机器不同的 PC$ 或虚拟账户同样不够用。域内一旦需要服务专属、多台服务器共通的身份,就先于域用户考虑 gMSA,这是本文的方针。gMSA 同样不能在工作组中使用。
4. gMSA 的作用:拥有独有身份,把密码管理交给 AD
4.1 把密码的生成、分发、更新与人分离
gMSA(组托管服务账户)是把密码管理交给域控制器的域账户。域控制器从 KDS(密钥分发服务)的根密钥计算密码,只有获准的主机才能取得并用于服务。8
flowchart TB
accTitle: gMSA 的密码管理机制
accDescr: 域控制器从 KDS 根密钥计算密码,只有获准的主机取得并用于运行服务,密码默认每 30 天自动轮换
kds["KDS 根密钥"] --> dc["DC 计算密码"]
dc --> host["获准的主机取得"]
host --> svc["用于运行服务"]
dc -.-> rot["默认每 30 天自动轮换"]
图 3:即使人不知道密码,也能用获准主机取得的、自动更新的凭据来运行服务。
| 效果 | 在运维上的意义 |
|---|---|
| 240 字节的随机生成密码 | 暴力破解和字典攻击不再现实,抵抗 Kerberoasting 的能力大幅提升 |
| 默认每 30 天自动轮换 | 管理员不必计划变更,也不必为更新密码而停止服务 |
| 可在多台服务器之间共用同一身份 | 即使是负载均衡下的服务器场,也能以同一主体相互进行身份验证 |
| 可以简化 SPN 管理 | 简化服务主体名称的注册与管理,还可以委派管理权 |
这些就是相比手动管理的域用户更优先选择 gMSA 的理由。11 如果把 Windows LAPS 理解为把本地管理员密码的管理自动化,而 gMSA 承担服务账户的密码管理,就容易理解两者的定位。两者是针对不同对象的机制。
4.2 不要省略应用的支持确认
gMSA 广泛支持 Windows 服务、IIS 应用程序池、任务计划程序等通过标准机制配置登录身份的场景。但是,并非所有应用都能使用。内部要求输入密码的实现无法使用,故障转移群集本身也不支持 gMSA,诸如此类的限制都存在。10
一旦把它列为候选,就要在投入生产之前在测试环境确认“能以 gMSA 启动”和“能访问必要的资源”。这也是 Microsoft 要求的步骤。11
相关的选项还有面向单台服务器的 sMSA(独立托管服务账户),以及 Windows Server 2025 引入的 dMSA(委派托管服务账户)。dMSA 把身份验证与设备识别绑定,用于对抗凭据窃取。新建配置以 gMSA 为基本,并根据需求一并考虑这些选项。2
5. 引入 gMSA:从前提确认到服务配置
5.1 先要确认的要求
| 确认项 | 要求与注意事项 |
|---|---|
| 域 | 必须是 Active Directory 域环境。工作组中不能使用 |
| 功能级别 | 域和林的功能级别必须是 Windows Server 2012 以上 |
| KDS 根密钥 | 必须已创建。新建之后要预留复制的等待时间 |
| gMSA 名称 | 不仅在域内,在林内也要唯一 |
| 密码更改间隔 | 只能在创建时设置,所以要在创建前定好 |
| 应用 | 验证能否以 gMSA 启动并访问资源(4.2) |
gMSA 名称和更改间隔也是引入前要定下的事项。等账户建好再考虑,就得重新创建。10
5.2 确认 KDS 根密钥,没有就创建
创建 KDS 根密钥在一个林中只需做一次。先确认已有的密钥,只在尚未创建时再添加。
# 以域管理员身份,在域控制器(或装有 AD PowerShell 模块
# 的管理终端)上执行
# 确认有无 KDS 根密钥,没有就创建(一个林只做一次)
Get-KdsRootKey
Add-KdsRootKey -EffectiveImmediately # 实际可用最多要等 10 小时之后
即使指定了 -EffectiveImmediately,也不一定创建后立刻就能用。因为要等待复制到所有域控制器,创建后最多有 10 小时的等待时间,其间无法创建 gMSA。这是为了避免在复制尚未完成时就去取密码而出问题。请把这段时间也算进引入计划。12
5.3 收紧允许取得密码的主机,并配置 gMSA
步骤分 4 个阶段。前半是 AD 一侧的配置,后半是运行服务的各台服务器一侧的操作。10
| 阶段 | 操作 | 需要确认的内容 |
|---|---|---|
| ① 创建允许取得密码的组 | 把目标服务器的计算机账户加进去 | 加入组后重启服务器,让成员身份生效 |
| ② 创建 gMSA | 用 New-ADServiceAccount 指定允许取得密码的组 |
名称和 DNS 名、允许的主机范围是否一致 |
| ③ 在各台服务器上安装 | 执行 Install-ADServiceAccount |
Test-ADServiceAccount 返回 True |
| ④ 设为服务的运行账户 | 指定 DOMAIN\名称$ 并重启服务 |
密码栏留空。同时确认登录权利和资源一侧的 ACL |
执行下面的示例之前,还要配置 7.1 的“作为服务登录”权利。sc.exe config 执行成功,和服务能够登录,是两回事。
# ① 创建允许取得密码的安全组,
# 并把运行服务的服务器的计算机账户加进去
New-ADGroup -Name "GG-SvcBatchHosts" -GroupScope Global
Add-ADGroupMember -Identity "GG-SvcBatchHosts" -Members "APPSV01$", "APPSV02$"
# 组成员身份在计算机登录时评估,
# 因此加入之后重启目标服务器更可靠
# ② 创建 gMSA
New-ADServiceAccount -Name "svc-batch" `
-DNSHostName "svc-batch.corp.example.com" `
-PrincipalsAllowedToRetrieveManagedPassword "GG-SvcBatchHosts"
# ③ 在运行服务的各台服务器上安装并验证 gMSA
Install-ADServiceAccount -Identity "svc-batch"
Test-ADServiceAccount -Identity "svc-batch" # 返回 True 就说明能取到密码
# ④ 设为服务的运行账户。名称末尾加 $,不指定密码
sc.exe config MyBatchService obj= "CORP\svc-batch$"
Restart-Service MyBatchService
在 services.msc 中,账户名同样写成 CORP\svc-batch$ 这样末尾带 $,并让密码栏保持为空。MSA 系列账户不能用于交互式登录。3
在目标端的共享文件夹和 SQL Server 上,用 CORP\svc-batch$ 代替 PC$ 授予必要的访问权限。这样就构成了人不管理密码、以服务专属身份进行网络访问的配置。不要只做 Test-ADServiceAccount 的取得确认就收工,请一直验证到服务的实际主要功能。
6. 域用户是最后手段:要用就把缓解措施配齐
6.1 为避免过期,反而把另一种风险固化下来
把域用户或本地用户指派给服务后,SCM 会保存密码,并在每次启动时用它登录。但是,SCM 不管理有效期。保存的密码一旦过期,登录就会失败,服务将无法启动。1
由此开始出现恶性循环:为了防止过期出问题而改成永不过期,同一个密码以明文留在多台服务器的操作手册、脚本和任务里,最后因为“不知道改了之后哪里会停”,即使有人离职也无法更改。
Microsoft 也指出,在服务中使用域账户的配置,密码和 SPN 的手动管理会消耗运维工时,而维护作业本身可能导致服务停止。仅仅设为永不过期,并不能消除管理上的问题。3
6.2 拥有 SPN 的账户也会成为 Kerberoasting 的目标
接受 Kerberos 身份验证的服务,会在运行账户上注册 SPN(服务主体名称)。域内任何已通过身份验证的用户都能请求该服务票据,因此攻击者取得票据后在离线状态下尝试暴力破解密码,这就是 Kerberoasting。
对策不是依赖人定的 10 到 16 个字符左右的密码,而是使用长的随机生成密码。Microsoft 也列举了强制使用长密码,以及使用由机器生成超长随机值的 gMSA。13
同一份文档提到的 Kerberos 铠装(FAST),保护的是预身份验证数据以及对 KDC 假冒的抵抗能力。它并不阻止已通过身份验证的用户向 SPN 请求服务票据,因此不能替代服务账户的密码强度。SPN 与 Kerberos、以及回退到 NTLM 的条件,请参阅“图解 NTLM 与 Kerberos”。
6.3 应用不支持时,把专用账户和运维措施成套落实
如果因为应用不支持 gMSA 等原因,不得不使用专用域用户,就要把下面这些缓解措施全部落实。
| 项目 | 需要落实的内容 |
|---|---|
| 密码 | 使用 25 个字符以上的随机生成密码。除密码管理工具外,不写进操作手册、脚本和共享的 Excel |
| 账户用途 | 不与人用账户共用,只供服务使用。按服务分开 |
| 登录限制 | 拒绝交互式登录和远程桌面,只允许“作为服务登录” |
| 权限 | 把所属组和访问权限降到最小。不要加入 Domain Admins |
| 更新与台账 | 建立定期轮换的步骤,把变更会波及的服务器、服务、任务等登记成台账 |
把服务的身份与人的账户分离,也是重要的原则。4 与其让人持续做这些管理,不如把支持的服务迁到 gMSA,这样更安全、运维也更轻,这就是优先选择 gMSA 的理由。
7. 切换与审计:不是改个账户名就完事
7.1 确认“作为服务登录”权利
要作为服务启动,账户需要具备 SeServiceLogonRight(作为服务登录)。LocalSystem、LocalService、NetworkService 内置就有,用其他账户运行时,则要确认这项权利的分配。14
| 配置方式 | 对权利的处理 | 运维中需要确认的内容 |
|---|---|---|
services.msc 的“登录”选项卡 |
管理单元会自动授予该权利 | 应用策略之后必要的权利是否仍被保留 |
CreateService / ChangeServiceConfig、sc.exe config |
不验证账户是否拥有该权利 | 另外补上授予权利的步骤 |
| 用 GPO 配置 | 本地的授予可能在应用策略时被覆盖 | 在组织一侧的策略中也包含目标账户 |
要在部署步骤中写明通过本地安全策略(secpol.msc)或 GPO、Intune 配置权利。不依赖工具的副作用很重要。对服务专用账户,还要同时拒绝交互式登录。
7.2 确认配置文件目录下的数据和 ACL
SCM 在服务启动时会加载该账户的用户配置文件。因此 %TEMP%、%APPDATA%、HKEY_CURRENT_USER 的实体因账户而异。切换之后配置和缓存看起来像“消失了”,是因为引用的是与旧账户不同的配置文件。1
对策是把服务的数据放到 C:\ProgramData\<应用名> 这样明确的路径上,并对运行账户授予 ACL。只要脱离按账户区分的配置文件,下次更改账户时就不必再挪一次存放位置。已经保存在配置文件目录下的数据,请把迁移纳入切换计划。
不仅是必要的文件夹,注册表等的访问权限也要确认。把账户改成低权限之后,要验证原本以 LocalSystem 权限为前提的处理是否会失败。
7.3 DPAPI 保护的数据,仅靠搬文件继承不过来
用用户范围的 DPAPI(CryptProtectData、.NET 的 ProtectedData 等)保护的数据,原则上只有用保护时的同一个账户才能解密。一旦更改运行账户,保存的连接字符串和 API 密钥就读不出来了。
因此,除了配置文件的文件迁移之外,还要准备切换后重新录入机密信息的步骤。即使这是 DPAPI 正确保护的结果,没有事先准备也会变成服务故障。存放位置的设计请参阅“Windows 应用的敏感信息存储”。
如果用 gMSA 或 PC$ 的 Windows 集成身份验证就能完成连接,那么保存机密信息这件事本身就可以取消。先想“能不能不保存”,再想“保存到哪里”,顺序是这样的。
另外,想“以调用方用户的权限来处理”时,不要把服务的运行账户调强,而应考虑模拟(impersonation)。详情在“正确处理 Windows 的模拟令牌”中说明。
7.4 用服务列表盘点,用日志确认启动时的身份
最初的盘点,可以统计服务列表中的运行账户。下面的示例按账户统计数量,并找出路径不在 Windows 文件夹内的 LocalSystem 服务。
# 统计哪些服务以哪个账户运行
Get-CimInstance Win32_Service |
Group-Object StartName |
Sort-Object Count -Descending |
Select-Object Count, Name
# 找出以 LocalSystem 运行的非标准服务(用路径区分自研或第三方产品)
Get-CimInstance Win32_Service |
Where-Object { $_.StartName -eq 'LocalSystem' -and $_.PathName -notlike '*\Windows\*' } |
Select-Object Name, DisplayName, PathName
如果业务服务以 LocalSystem 或域用户运行,就回到第 1 章的判断,确认所需特权和目标端需要的身份。按路径筛选只作为发现候选的线索,最终要按服务的实际用途和处理内容来判断。
服务的启动可以通过安全事件日志的事件 ID 4624、登录类型 5(Service)确认。它表示 SCM 启动服务时的登录。“虚拟账户”字段表示该次登录是否来自 MSA 或虚拟账户,因此也可以用于监视受管理账户的使用情况。15
7.5 汇总生产切换前的确认
| 确认对象 | 切换前后要确认的内容 |
|---|---|
| 本地权限 | 必要的特权,以及对文件夹、注册表等的 ACL 是否齐备 |
| 网络身份 | 是否已在目标端给 PC$ 或 gMSA 等预期身份授予访问权限 |
| 登录权利 | 是否已分配“作为服务登录”,且不会因策略而丢失 |
| 存放位置 | 是否确认了配置文件、TEMP、HKCU 的变化以及既有数据的迁移 |
| DPAPI | 是否有以用户范围保护的凭据等的重新录入步骤 |
| 运行与审计 | 在验证环境确认启动和主要功能,并在切换后确认运行账户与日志 |
无论是从 LocalSystem 迁移,还是引入 gMSA,都要做完这些确认再切换生产环境。把最小权限化和必要功能持续可用成套确认,这是迁移的要点。
8. 总结
选定服务账户时,要把本地权限、网络身份、密码管理分开考虑。LocalSystem 是默认值,但这并不构成使用它的理由。普通的业务服务以虚拟账户为基本,并授予必要的 ACL。只有在确实需要强特权时,才考虑 LocalSystem。53
如果域内的目标端只要有机器级身份就够用,那么虚拟账户等加上对 PC$ 的访问权限往往就够了。需要服务专属身份,或多台服务器需要共通身份时,就选择 gMSA,把密码管理交给 AD。工作组中 PC$ 和 gMSA 都不能用,需要另一套处理凭据的设计。210
需要域用户时,就把专用账户、长的随机密码、登录限制、最小权限、轮换与台账配齐。切换时不仅要改账户名,还要确认登录权利、配置文件和 DPAPI。
下次配置服务时要问的是:“这个服务应该以谁的身份、能访问到哪里?”请按这个答案选择账户,不要把“碰巧能跑的配置”固定下来。
相关文章
- Windows 服务的创建与运维 ── 从任务计划程序的取舍到 BackgroundService 服务化
- Windows 什么时候需要管理员权限 - UAC、保护区域与设计上的辨别方式
- 正确处理 Windows 的模拟令牌 ── 线程级权限借用与安全的还原方式
- 图解 NTLM 与 Kerberos ── 为什么身份验证会“回退”到 NTLM
- Windows LAPS 实务指南 ── 告别全部 PC 通用的本地管理员密码
- Windows 应用的敏感信息存储 - 用 DPAPI 摆脱明文配置
相关咨询领域
小村软件合同会社承接 Windows 服务和常驻应用的运行账户设计与最小权限化、把以 LocalSystem 为前提开发的既有服务迁移到虚拟账户和 gMSA,以及更改账户引发的拒绝访问、DPAPI、配置文件相关故障的调查。从“审计被指出了问题,但不知道该从哪里入手”这个阶段开始也可以。
参考链接
-
Microsoft Learn, Service User Accounts. 关于服务在用户账户的安全上下文中运行、SCM 在启动时登录到该账户并把访问令牌关联到服务进程、SCM 会加载用户配置文件,以及 SCM 不管理密码有效期、密码过期时登录失败使服务无法启动。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Service accounts. 关于虚拟账户是自动管理的本地账户、不需要管理密码,名称为 NT SERVICE<SERVICENAME> 形式,在域环境中以计算机账户(
\ ↩ ↩2 ↩3 ↩4 ↩5 ↩6$)的凭据访问网络,以及 sMSA、gMSA、dMSA 和虚拟账户的取舍标准。 -
Microsoft Learn, Configure Windows service accounts and permissions. 关于 SQL Server 的默认服务账户是虚拟账户(NT SERVICE\MSSQLSERVER 等)、指定虚拟账户或 MSA 时密码栏要留空、MSA 的名称末尾带 $ 且不能用于交互式登录、Local Service 是共用账户因而无法隔离所以 SQL Server 不支持、使用域账户时密码和 SPN 的手动管理会消耗工时且维护作业可能导致服务停止,以及应始终以最小权限的账户运行服务。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Securing on-premises service accounts. 关于本地服务的优先顺序是首选 gMSA、不能用则 sMSA、其次是计算机账户、最后才是用户账户,使用计算机账户时无法判别是哪个服务在用该账户因而无法审计变更,以及服务账户的作用(识别服务、身份验证、启动服务)。 ↩ ↩2 ↩3
-
Microsoft Learn, LocalSystem Account. 关于 LocalSystem 在本地计算机上拥有广泛特权、令牌中包含 NT AUTHORITY\SYSTEM 和 BUILTIN\Administrators 的 SID、没有密码、对远程服务器出示计算机的凭据、包含 SE_DEBUG_NAME 和 SE_TCB_NAME 在内的特权清单,以及绝大多数服务不需要这种特权级别、应考虑使用 LocalService/NetworkService。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Local accounts. 关于 SYSTEM(S-1-5-18)在 NTFS 卷上默认拥有完全控制权限、NETWORK SERVICE(S-1-5-20)对远程服务器出示计算机的凭据,以及 LOCAL SERVICE(S-1-5-19)在本地只有最小特权、对网络出示匿名凭据。 ↩ ↩2 ↩3
-
Microsoft Learn, About Windows Resource Protection. 关于 Windows 资源保护(WRP)阻止替换重要的系统文件、文件夹和注册表项,对受 WRP 保护资源的完全访问权限被限制给 TrustedInstaller、只能通过 Windows Modules Installer 服务提供的受支持替换机制进行更改,以及试图修改受保护资源的应用程序会被拒绝访问。 ↩ ↩2
-
Microsoft Learn, Group Managed Service Accounts overview. 关于 gMSA 是把密码管理交给 Windows 的域账户,域控制器从密钥分发服务(kdssvc.dll)的共享机密计算密码,成员主机向域控制器查询以取得当前和上一个密码,以及可以让服务器场中以同一主体进行相互身份验证。 ↩ ↩2
-
Microsoft Learn, sc.exe config. 关于用 obj= 参数指定服务的运行账户、其默认值是 LocalSystem,以及使用 LocalSystem 以外的用户账户时的 password= 参数。 ↩
-
Microsoft Learn, Manage group Managed Service Accounts. 关于 gMSA 的前提条件(域/林功能级别 2012 以上、创建 KDS 根密钥)、gMSA 名称必须在林内唯一、密码更改间隔只能在创建时设置、用 New-ADServiceAccount 的 -PrincipalsAllowedToRetrieveManagedPassword 指定允许取得密码的组、Install-ADServiceAccount/Test-ADServiceAccount 的步骤、虚拟账户的身份是机器本地的而域无法识别、故障转移群集不支持 gMSA,以及 SCM、IIS 应用程序池、任务计划程序支持用 gMSA 配置登录。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Secure group managed service accounts. 关于 gMSA 的密码是 240 字节随机生成、不易受暴力破解和字典攻击,Windows 操作系统每 30 天更改一次密码因而不需要管理员计划变更或停止服务,向服务器场部署以及简化 SPN 管理,服务不支持 gMSA 时使用 sMSA、连 sMSA 也不行时使用配合强密码管理的标准用户账户,以及应在投入生产前于测试环境确认以 gMSA 的运行情况。 ↩ ↩2
-
Microsoft Learn, Create a Key Distribution Service (KDS) root key. 关于域控制器要开始生成 gMSA 密码需要根密钥、用 Add-KdsRootKey -EffectiveImmediately 创建的步骤、创建后最多 10 小时内因为要等待 AD 复制收敛而无法创建 gMSA,以及复制未完成时取得密码可能失败。 ↩
-
Microsoft Learn, Protect SMB traffic from interception. 关于作为服务账户保护措施的 gMSA(由于使用机器生成的超长随机密码,用暴力破解和字典攻击破解密码不再现实)、强制使用长密码、提及 Kerberos 铠装(FAST)等建议事项。 ↩
-
Microsoft Learn, Policy CSP - UserRights: LogOnAsService. 关于“作为服务登录”权利让安全主体能够作为服务登录、Local System 和 Local Service、Network Service 内置具有该权利、以其他账户运行的服务需要分配该权利,以及在组策略中的配置路径。 ↩
-
Microsoft Learn, 4624(S): An account was successfully logged on. 关于事件 4624 在创建登录会话时记录在被访问的计算机上、登录类型 5 表示服务(SCM 启动服务),以及可以通过“Virtual Account”字段识别 MSA 和虚拟账户的登录、用于监视受管理的服务账户。 ↩
相关文章
共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。
Windows LAPS 实务指南——告别全部 PC 通用的本地管理员密码
全部 PC 通用的本地管理员密码,是一台失陷就波及全部设备的 Pass-the-Hash 攻击温床。本文讲解已成为 OS 标准功能的 Windows LAPS 如何自动轮换,如何配置保存到 AD/Entra ID,以及运维中的陷阱。
SMB 签名与 LDAP 通道绑定——在实务中收紧 NTLM 对策的“另一半”
在停用 NTLM 之前,抑制中继攻击危害的防御手段是 SMB 签名与 LDAP 签名、通道绑定。本文从实务角度梳理各操作系统的默认值、审计事件的解读方法、推进到强制的步骤,以及业务应用和设备的修复方法。
图解 NTLM 与 Kerberos——认证为什么会“回退”到 NTLM
用图解梳理 NTLM 与 Kerberos 的区别。依据官方文档讲解挑战/响应、TGT 与服务票据、SPN 解析不出来时 Negotiate 回退到 NTLM 的条件、中继攻击与 Pass-the-Hash 成立的原因,直至 NTLMv1 被移除。
NTLM 停用会导致业务应用停止运行吗——审计日志的采集方法与消除依赖的顺序
围绕 NTLM 停用,整理出梳理本公司 Windows 环境与业务应用在何处依赖 NTLM 的步骤:审计策略、NTLM/Operational 日志中事件 8001~8004 的追踪方法、回退到 NTLM 的典型模式与修复方式,以及 SMB 的 NTLM 阻止。
命名管道实务 ── 从设计到安全,吃透 Windows 进程间通信的标准方案
以实务视角讲解 Windows 进程间通信的标准方案——命名管道。依据一手资料梳理字节模式与消息模式的取舍、同时接纳多个客户端的服务器结构、ACL 与模拟的安全设计,以及 .NET 的命名管道流。
相关主题
与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。
Windows 技术主题
汇整 KomuraSoft LLC 关于 Windows 开发、故障调查与既有资产活用文章的主题中心。
常见问题
汇总了咨询这一主题时常见的问题。
- 暂时用 LocalSystem 运行的服务,应该立刻改掉吗?
- 一律立刻变更未必就是正确答案。首先确认该服务是否真的需要 LocalSystem 级别的本地权限(超出管理员的强特权)。如果只是文件读写和网络通信,第一候选是改到虚拟账户(NT SERVICE\服务名)。迁移时要确认对必要文件夹和注册表项的访问权限授予、依赖配置文件或 DPAPI 的数据如何处理,以及是否具备“作为服务登录”权利。请先在验证环境确认启动和主要功能,再切换生产环境。
- 虚拟账户和 NetworkService 应该选哪一个?
- 新选择时建议用虚拟账户。两者在网络上都表现为计算机账户(DOMAIN\计算机名$),本地权限小这一点也相似。但是 NetworkService 由多个服务共用同一个账户,无法用 ACL 做到“只允许这个服务”。虚拟账户每个服务都有独有的身份,可以在 ACL 中直接指定 NT SERVICE\服务名。SQL Server 等近年的 Microsoft 产品的默认值也是虚拟账户。
- gMSA 在工作组环境(没有域)也能用吗?
- 不能。gMSA 是由 Active Directory 域控制器生成并管理密码的机制,前提是有域并创建了 KDS 根密钥。在工作组环境中,基本做法是用虚拟账户或 LocalService/NetworkService 把本地处理做完。如果需要访问其他机器,就要改成显式使用目标端准备好的账户凭据等另外的设计。以计算机账户(PC$)进行网络访问,同样只在域环境中成立。
- 更改了服务的运行账户之后,保存的配置和凭据读不出来了。这是为什么?
- 因为每个运行账户都绑定着各自独有的用户配置文件、%TEMP%、HKEY_CURRENT_USER 和 DPAPI 密钥。特别是用 DPAPI(CryptProtectData 等)做用户范围保护的数据,原则上只有用保护时的同一个账户才能解密。此外,保存在配置文件目录下(AppData 等)的文件,从新账户看是另一条路径。切换账户之前,请规划好 DPAPI 保护数据的重建步骤(重新输入 API 密钥等)以及配置文件目录下文件的迁移。
- 如果只是想让服务访问共享文件夹,需要域用户吗?
- 多数情况下不需要。在域环境中,以 LocalSystem、NetworkService、虚拟账户运行的服务,对远程会以计算机账户(DOMAIN\计算机名$)通过身份验证。只要把该 PC$ 加入共享文件夹的共享权限和 NTFS 权限,就能读写。如果想以服务专属的身份做访问控制,或者多台服务器需要同一个身份,请考虑 gMSA 而不是域用户。