Windows 服务帐户选定 ── LocalSystem、虚拟帐户与 gMSA

· · Windows, Windows 服务, 服务帐户, gMSA, LocalSystem, 虚拟帐户, 安全, Active Directory, 最小权限

“我们‘暂时’用 LocalSystem 跑的内部服务,在安全审计被点名‘权限过大’。该改成什么?”“服务访问不到共享文件夹,所以用域用户在跑。密码到期服务就停,于是设成永不到期,还把明文写进操作手册。”── 客户 Windows 服务相关咨询里,这两则是固定班底。

两边现场的共通点是:服务的登录帐户被冻成“碰巧能跑的设置”,而不是设计决策。Windows 服务一定在某个帐户的安全上下文中运行,那个帐户决定它本地能做什么、从网络另一端看起来是谁、密码由谁管理。把这里留在默认值,单个服务的弱点就直接变成整台机器被接管,明文密码也散进操作手册与脚本。

登录帐户决定的三件事服务一定在某个帐户的安全上下文中运行,该帐户决定本地能做什么、从网络另一端看起来是谁、密码由谁管理服务的登录帐户本地能做什么从网络另一端看起来是谁密码由谁管理

图 1: 选定登录帐户是同时决定本地权限、网络身份与密码管理的设计决策。

实务上有六种选择 ── LocalSystem、LocalService、NetworkService、虚拟帐户(NT SERVICE\<服务名称>)、域用户,以及 gMSA(组托管服务帐户)。本文面向中小企业信息化人员与 Windows 应用程序开发者,把这六种的权限、网络身份与密码管理整理成一张表,并依 2026 年 8 月当下的 Microsoft Learn 一手资料整理到判断流程。

服务本身怎么做(与任务计划程序的取舍、用 .NET Worker Service 实现)见“Windows 服务的创建与运维”。本文集中在出事最多的“登录帐户”。

1. 先讲结论

  • 拿不定主意时,在单台机器内做完的服务以虚拟帐户为第一候选;要以服务专属身份访问域内资源的服务以 gMSA 为第一候选。 Microsoft 也指导尽可能使用托管帐户(MSA / 虚拟帐户)。12
  • 不要因为“能跑”就选 LocalSystem。 令牌含 SYSTEM 与 BUILTIN\Administrators,并持有 SeDebugPrivilege 等强特权,被接管就几乎失去该机器上的一切。sc.exe create 默认是 LocalSystem,正是这类事故的温床。34
  • LocalService 与 NetworkService 的差别是网络身份。 本地权限两者都最小,但对远程来说 LocalService 是匿名,NetworkService 是计算机帐户。5
  • **虚拟帐户(NT SERVICE\<服务名称>)是现代默认:不必管密码,又能按服务分开身份。** 可在 ACL 上直接指定“NT SERVICE\\服务名称”,SQL Server 的默认服务帐户也是这个。[^understand-service-accounts][^sql-service-accounts]
  • LocalSystem、NetworkService 或虚拟帐户走到网络上时,会变成计算机帐户(DOMAIN\计算机名$)。 在共享文件夹或 SQL Server 的 ACL 授予 PC$,常常就能不用域用户。36
  • 把域用户用在服务上,会在密码运营与 Kerberoasting 两边都变成负债。 SCM 用保存的密码登录,到期就启动失败;为了避开而采用“永不到期 + 明文备忘”等于送给攻击者。78
  • gMSA 由 Active Directory 自动生成并轮换密码。 要件是域与 KDS 根密钥,服务设成“DOMAIN\帐户名$”且密码栏留空。有些应用程序不支持,需事先验证。910
  • 改帐户会改掉配置文件、%TEMP%、DPAPI 的前提。 旧帐户 DPAPI 保护的数据,新帐户解不开。
  • 现况盘点可由服务列表的登录帐户,以及事件 ID 4624(登录类型 5)确认。11

一句话总结,本文结论是:把“不把人类密码交给服务”的配置(内置帐户、虚拟帐户、gMSA)当默认,域用户当最后手段

2. 选项全貌 ── 六种登录帐户一张表

先复习一层前提。服务启动时,服务控制管理器(SCM)以配置的帐户登录,成功后创建访问令牌并指派给服务进程。之后文件、管道等一切资源访问,都靠这个令牌与 ACL 比对来判定。7 所以选定登录帐户就是 决定交给服务进程的令牌内容的设计。以下列出六种选择。

服务启动时 SCM 做的事SCM 以配置的帐户登录,成功后创建访问令牌并指派给服务进程,之后资源访问由令牌与 ACL 比对决定SCM以配置的帐户登录创建访问令牌指派给服务进程访问文件或管道ACL 允许吗?访问成功访问被拒

图 2: 服务的每一次资源访问,都由启动时 SCM 创建的令牌与 ACL 比对决定。

帐户 本地权限 网络身份 密码管理 典型用途
LocalSystem 几乎无限制(SYSTEM+Administrators) 计算机帐户(PC$) 不需要(无密码) 与操作系统一体运行的例外服务
LocalService 最小(Users 级) 匿名 不需要 不需要网络身份的本地处理
NetworkService 最小(Users 级) 计算机帐户(PC$) 不需要 机器级身份就够用的低权限处理
虚拟帐户 NT SERVICE\<名称> 最小 + 在 ACL 个别授予 计算机帐户(PC$) 不需要(自动管理) 跑在单台服务器上的业务服务默认
域用户 只限你授予的 该用户本身 手动(到期、泄露、轮换都交给人) 不支持 gMSA 的应用程序的最后手段
gMSA 只限你授予的 该 gMSA 本身 AD 自动生成并轮换 域环境需要服务专属身份时

LocalSystem、LocalService、NetworkService、虚拟帐户都 完全没有密码这个概念。用 SCM 保存的密码登录(= 可能到期与泄露)的只有域用户与本地用户。73

下面按行逐一深入。

3. LocalSystem 有什么问题

3.1. 比“以管理员身份运行”更强

LocalSystem(显示名称 Local System,NT AUTHORITY\SYSTEM)是 SCM 使用的预定义帐户,在本地计算机持有广泛权限。令牌含 NT AUTHORITY\SYSTEMBUILTIN\Administrators 的 SID,可访问系统上大多数对象。此外,可调试其他进程的 SeDebugPrivilege,以及作为操作系统一部分运行的 SeTcbPrivilege,默认就已启用。3

这份强大等同于被接管时的伤害规模。以 LocalSystem 运行的服务只要有一个任意代码执行弱点,攻击者一口气就能读改该机器上所有用户的文件(SYSTEM 在 NTFS 默认具有完全控制5)、用 SeDebugPrivilege 读其他进程内存,再从那里窃取凭据并横向移动(Pass-the-Hash 等的起点)。凭据窃取与横向移动的链条见“图解 NTLM 与 Kerberos”与“Windows LAPS实务指南”。

LocalSystem 服务被接管时的伤害以 LocalSystem 运行的服务只要有一个任意代码执行弱点,攻击者就能读改所有用户文件、读其他进程内存,并窃取凭据后横向移动一个任意代码执行弱点攻击者取得 SYSTEM 权限读取与篡改文件读其他进程内存窃取凭据横向移动到另一台机器

图 3: LocalSystem 服务的一个弱点,就能一口气走到整机接管与横向移动的起点。

3.2. 为什么还是被选

理由很单纯:它是默认值,而且不会出现访问被拒sc.exe create 省略 obj= 时默认是 LocalSystem,4 许多旧示例代码与安装程序模板仍假设 LocalSystem。开发期间可以远离权限错误,于是大量产出“能跑就先这样”的结构。Microsoft 自己的文档也写道,多数服务不需要这么高的权限级别,若不需要就应考虑 LocalService 或 NetworkService。3

LocalSystem 持续被选的结构sc.exe create 默认是 LocalSystem,旧示例与模板也假设 LocalSystem,开发时不会出现访问被拒,于是大量产出能跑就先这样的配置sc.exe create 的默认建成 LocalSystem旧示例与模板开发时没有访问被拒能跑就先这样权限过大的服务被量产

图 4: 默认值加上“没有访问被拒”的开发体验,量产了冻在 LocalSystem 的服务。

3.3. 与 TrustedInstaller 的差别 ── LocalSystem 也不是无限

把 LocalSystem 叫成“Windows 最强帐户”并不准确。Windows Vista 起的 Windows 资源保护(WRP)只允许 TrustedInstaller(Windows Modules Installer 服务)更改重要的操作系统系统文件、文件夹与注册表项,连 SYSTEM 或管理员改写都会访问被拒。12 Explorer 的“您需要来自 TrustedInstaller 的权限”就是这个机制。反过来说,LocalSystem 几乎能碰到 WRP 保护区以外的一切,通常没有理由把这个给业务服务。

WRP 保护区与 TrustedInstaller 的关系WRP 保护的重要系统文件与注册表项,只允许 TrustedInstaller 更改,连 SYSTEM 或管理员都会访问被拒可以更改访问被拒几乎全部允许TrustedInstallerWRP 保护的系统文件等SYSTEM 与管理员WRP 保护区以外

图 5: LocalSystem 也不是无限;WRP 保护区的更改只允许 TrustedInstaller。

3.4. LocalSystem 合理的情况

例外合理的是 所需权限本来就超过管理员级 的服务 ── 与设备驱动程序紧密配合、操作操作系统安全基础、管理其他服务或会话等。备份代理或 EDR 这类软件属此。即便如此,仍值得确认是否真有用到该权限的代码路径,并考虑能否把需要权限的工作分开(怎么分辨见“Windows 什么时候需要管理员权限”)。

4. LocalService 与 NetworkService ── 最小权限的内置帐户

LocalService(NT AUTHORITY\LOCAL SERVICE,SID: S-1-5-19)与 NetworkService(NT AUTHORITY\NETWORK SERVICE,SID: S-1-5-20)是为低权限服务准备的内置帐户。两者在本地都只有最小权限,能做的事比 Users 组成员多不了多少。51

两者差别只有一点:从网络另一端看起来是谁5

  • LocalService:以 匿名凭据 连到远程。无法访问需要身份验证的资源。
  • NetworkService:向远程出示 计算机的凭据(域环境为 DOMAIN\计算机名$)。

切分是“不上网络,或上了也不需要身份”用 LocalService,“要以机器身份访问域内资源”用 NetworkService。

LocalService 与 NetworkService 的差别本地权限两者都最小,但对远程 LocalService 以匿名凭据连接,NetworkService 出示计算机的凭据LocalService以匿名凭据连接需要身份验证的资源做不到NetworkService出示计算机的凭据域环境看起来像 PC$

图 6: 本地权限同为最小,但从网络另一端看到的身份分成匿名或计算机帐户。

不过从现代观点,这两者有弱点。同一个帐户被许多服务共用。 若五个服务都以 LocalService 运行,只要 ACL 是按帐户,五个就能互相访问对方的资源。SQL Server 不支持 Local Service 帐户也是同一理由:它是共用帐户,无法与其他服务分开。1

共用帐户无法分开若多个服务共用同一个 LocalService,只要 ACL 按帐户,就能互相访问对方的资源服务 A同一个 LocalService服务 B服务 C能互相访问对方的资源因为 ACL 是按帐户

图 7: 共用同一帐户的服务,无法用 ACL 把彼此的资源分开。

解决“维持低权限,但按服务分开”的,就是下一题的虚拟帐户。

5. 虚拟帐户(NT SERVICE\<服务名称>)── 现代默认

5.1. 不必密码就能有每服务身份

虚拟帐户是 Windows Server 2008 R2 / Windows 7 起可用的“托管本地帐户”。特性有三。6

  • 帐户 自动管理;不必创建也不必设密码
  • 名称是 NT SERVICE\<服务名称>,成为 每个服务独有的身份
  • 在域环境可用 计算机帐户的凭据(DOMAIN\计算机名$) 访问网络

也就是保住 LocalService/NetworkService“不必管密码”的优点,拿掉“帐户共用所以分不开”的缺点。SQL Server 安装默认用 NT SERVICE\MSSQLSERVER 这类虚拟帐户,也是这个原因。1

虚拟帐户让什么得以并存虚拟帐户保住 LocalService 与 NetworkService 不必管密码的优点,拿掉因共用而分不开的缺点,并具备每个服务独有的身份保住拿掉优点(不必管密码)虚拟帐户缺点(共用而分不开)每个服务独有的身份不必创建也不必设密码

图 8: 虚拟帐户保住内置帐户的优点,只拿掉因共用而分不开的缺点。

5.2. 可在 ACL 上直接写“NT SERVICE\服务名称”

实务上的方便是 可以按名称只把该服务加进 ACL。“只有这个服务能写这个数据文件夹”不必建组也不必管密码就能做到。

# Change the service's logon account to a virtual account
# The value of obj= is "NT SERVICE\service-name". Do not specify a password
sc.exe config MyAppService obj= "NT SERVICE\MyAppService"

# Confirm the configuration (check SERVICE_START_NAME)
sc.exe qc MyAppService

# Grant modify rights on the data folder to this service only
icacls "C:\ProgramData\MyApp" /grant "NT SERVICE\MyAppService:(OI)(CI)M"

在 GUI 里,于 services.msc 打开服务属性 →“登录”选项卡 → 在“此帐户”输入 NT SERVICE\服务名称密码栏留空(虚拟帐户或 MSA 不指定密码是 SCM 的规格)。更改后重新启动服务即应用。

5.3. 限制 ── 出了机器就不是“那个服务”

虚拟帐户的身份是机器本地的,域认不出来。到了网络上会如后文所述缩成计算机帐户,所以 远程分不出“是哪个服务”,也不能在多台服务器共用同一身份。10

虚拟帐户的身份在机器外会缩水在机器内每个服务独有的虚拟帐户,到了网络上也缩成计算机帐户,远程分不出是哪个服务虚拟帐户 A计算机帐户 PC$虚拟帐户 B远程看到的身份分不出是哪个服务

图 9: 即使机器内身份独有,在网络另一端每个服务看起来都是同一个 PC$。

这个限制 ── 需要在网络另一端有服务专属身份、需要在多台服务器共用同一身份 ── 成为问题的那一刻,就是该叫出 gMSA(第 8 章)的时候。

6. 走上网络时的身份 ── 计算机帐户(PC$)的实务

6.1. “服务访问不到共享文件夹”是误解

在已加入域的机器上,以 LocalSystem、NetworkService 或虚拟帐户运行的服务访问远程资源时,会以计算机帐户(DOMAIN\计算机名$)验证36 开头那些“访问不到共享文件夹所以改成域用户”的咨询,其实多半这样就解了。只是目标端 ACL 没有允许 PC$。

以计算机帐户进行远程访问已加入域的机器上,LocalSystem、NetworkService 或虚拟帐户服务以计算机帐户向远程验证,目标端 ACL 允许 PC$ 就能访问服务(LocalSystem、虚拟帐户等)以 PC$ 验证目标端 ACL 允许 PC$ 吗?共享文件夹或数据库访问成功访问被拒

图 10: 在域环境,只要在目标端 ACL 授予 PC$,不必域用户也能建立远程访问。

文件服务器端的授予与一般 ACL 操作相同;帐户名指定 计算机名$(GUI 对象选择对话框请把对象类型含“计算机”)。

# On the file-server side: grant a service on APPSV01 modify rights on the shared folder
# You need to grant both share permissions and NTFS permissions
Grant-SmbShareAccess -Name "AppData" -AccountName "CORP\APPSV01$" -AccessRight Change -Force
icacls "D:\Shares\AppData" /grant "CORP\APPSV01$:(OI)(CI)M"

SQL Server 也一样:把计算机帐户建成登录,连接字符串用 Integrated Security=true 即可,不必密码。

-- On the DB-server side: permit Windows integrated authentication from a service on APPSV01
CREATE LOGIN [CORP\APPSV01$] FROM WINDOWS;

6.2. 认清 PC$ 做法的极限

这种做法有两个极限。

  1. 粒度是整台机器。 同一机器上的 LocalSystem、NetworkService 与所有虚拟帐户服务,从远程看起来都是同一个 PC$。无法在目标端“只允许这个服务”,也无法审计是哪个服务用了该帐户。2
  2. 工作组环境不能用。 计算机帐户是 Active Directory 对象,未加入域的机器没有。需要显式处理目标端帐户凭据的设计。

想越过极限 1 时,2026 年的答案不是下一章的域用户……而是跳过那个问题,直接走向 gMSA。

PC$ 做法的两个极限以 PC$ 验证的粒度是机器级,无法做每服务允许或审计;工作组环境没有计算机帐户本身,因此不能用PC$ 做法极限 1:整台机器极限 2:没有工作组没有每服务允许或审计使用显式凭据越过这里:gMSA

图 11: 想越过机器级粒度与域前提这两个极限时,跳过域用户,走向 gMSA。

7. 把域用户用在服务上的问题

7.1. 密码的结构性问题

若把域用户(或本地用户)指派给服务,SCM 会保存该密码,每次启动都用它登录。SCM 不管到期,所以 密码到期登录就失败,服务不会启动7

从那里开始,现场常见的负向螺旋出现。

  1. 发生因到期而服务停止的事故
  2. 为防再发,设成“密码永不到期”
  3. 更改程序从未建立,同一密码以明文写进多台服务器的操作手册、脚本与任务计划程序
  4. 即使有人离职也不改密码(一改就不知道什么会停)
以域用户运营的负向螺旋密码到期服务停止,为防再发设成永不到期,明文密码散进操作手册与脚本,即使有人离职也改不了1. 到期让服务停止2. 为防再发设成永不到期3. 明文密码扩散操作手册、脚本、任务4. 即使有人离职也改不了

图 12: 从到期事故开始,永不到期与明文密码扩散就此固定。

Microsoft 也指出,服务使用域帐户的配置,在密码与 SPN 的手动管理上耗费可观运营力气,维护还可能导致服务停止。1

7.2. Kerberoasting ── 服务帐户成为目标

域用户服务帐户特有的另一种攻击是 Kerberoasting。接受 Kerberos 身份验证的服务会在登录帐户上注册 SPN(服务主体名称)。域内任何已验证用户都能向已注册 SPN 的帐户请求服务票据,攻击者取得票据后离线暴力破解密码。人类决定的 10 到 16 字符密码挡不住这次攻击。

Kerberoasting 的流程对已注册 SPN 的服务帐户的服务票据,任何已验证用户都能请求,攻击者取得票据后离线暴力破解密码域内已验证的用户请求该 SPN 的票据取得服务票据离线暴力破解大约 10 到 16 字符就会被破解

图 13: 任何已验证用户都能请求票据,人类决定长度的密码挡不住离线暴力破解。

有效对应是 把密码做成人类猜不到也破解不了的强度。Microsoft 也列出强制长密码,以及使用密码为机器生成长随机值的 gMSA。8 同一文档也提到 Kerberos 装甲(FAST),但 FAST 保护预身份验证数据与对抗 KDC 欺骗;它并不阻止已验证用户向 SPN 请求服务票据,因此不能替代服务帐户的密码强度。SPN 与 Kerberos 的关系、身份验证回退到 NTLM 的条件,图解于“图解 NTLM 与 Kerberos”。

7.3. 若仍使用域用户

若因应用程序不支持 gMSA 等原因别无选择,把以下当作最低限度的缓解。

  • 把密码做成随机生成的 25 字符以上,除密码管理工具外(操作手册、脚本、共享 Excel)哪里都不写
  • 做成服务专用帐户并按服务拆开(不要与人类帐户共用2
  • 拒绝交互式登录与远程桌面,只允许“作为服务登录”
  • 所属组最小化(加入 Domain Admins 想都别想)
  • 建立定期轮换程序,把更改会影响的地方列入清册

全部做完仍比迁到 gMSA 更不安全也不更省事 ── 那就是下一章。

8. gMSA ── 把密码管理交给 Active Directory

8.1. 机制与效果

gMSA(组托管服务帐户)是把密码管理交给域控制器的域帐户。密码由域控制器从 KDS(Key Distribution Service)根密钥计算,只有获准的主机能取得。13

gMSA 如何管理密码域控制器从 KDS 根密钥计算密码,只有获准的主机取得并用来运行服务,密码默认每 30 天自动轮换KDS 根密钥DC 计算密码获准的主机取得用来运行服务默认每 30 天自动轮换

图 14: 域控制器承担生成、分发与更新密码,人可以在不知道密码的情况下运营。

效果很清楚。9

  • 240 字节随机生成的密码:暴力破解与字典攻击变得不实际,Kerberoasting 抗性大幅上升
  • 默认每 30 天自动轮换:人不需要规划更改,服务也不需要停
  • 可在多台服务器共用同一身份:负载均衡下的服务器场能以同一主体互相验证
  • 更单纯的 SPN 管理:SPN 的注册与管理也可委派并简化

人可以在不知道密码的情况下运营 ── 若把它理解成 Windows LAPS 对本地管理员密码所做的事,套到服务帐户上的机制,位置就比较好抓。

8.2. 要件

gMSA 有前提。10

  • Active Directory 域环境(工作组做不到)
  • 域与林功能级别为 Windows Server 2012 或更高
  • KDS 根密钥已经创建
  • gMSA 名称在林内唯一,不只是域内
  • 密码更改间隔只能在创建时设置

创建 KDS 根密钥是一次性工作,但 创建后最多 10 小时不能创建 gMSA,因为要等复制到每一台域控制器。这是防止复制尚未完成就取密码失败的安全装置。14

从创建 KDS 根密钥到创建 gMSA创建 KDS 根密钥后要等复制到每一台域控制器,因此最多 10 小时不能创建 gMSA;复制完成后才能创建创建 KDS 根密钥最多 10 小时等待复制防止取回失败事故的安全装置已复制到每一台 DC可以创建 gMSA

图 15: 创建根密钥后最多 10 小时的等待,是为了避免复制尚未完成就取回失败。

# Run as a domain administrator, on a domain controller (or an administrative
# workstation with the AD PowerShell module)

# Confirm whether a KDS root key exists, and create one if not (once per forest)
Get-KdsRootKey
Add-KdsRootKey -EffectiveImmediately   # Actually usable after up to 10 hours

8.3. 从创建到配置的程序

程序分四阶段:“① 创建获准取回的组 → ② 创建 gMSA → ③ 安装到服务器 → ④ 设置到服务”。10

引入 gMSA 的四个阶段以四个阶段引入:创建获准取回密码的组、创建 gMSA、安装到各服务器、设为服务的登录帐户① 创建获准取回的组② 创建 gMSA加入服务器的 PC$③ 安装到各服务器用 Test 命令验证取回④ 设置到服务

图 16: 从创建组到设置服务,引入 gMSA 分四个阶段进行。

# ① Create a security group permitted to retrieve the password,
#    and add the computer accounts of the servers that will run the service
New-ADGroup -Name "GG-SvcBatchHosts" -GroupScope Global
Add-ADGroupMember -Identity "GG-SvcBatchHosts" -Members "APPSV01$", "APPSV02$"
# Group membership is evaluated at computer logon, so
# restarting the target servers after adding is the reliable approach

# ② Create the gMSA
New-ADServiceAccount -Name "svc-batch" `
    -DNSHostName "svc-batch.corp.example.com" `
    -PrincipalsAllowedToRetrieveManagedPassword "GG-SvcBatchHosts"

# ③ On each server that will run the service, install the gMSA and validate
Install-ADServiceAccount -Identity "svc-batch"
Test-ADServiceAccount -Identity "svc-batch"   # True means retrieval is working

# ④ Set it as the service's logon account. Append $ to the name, and do not specify a password
sc.exe config MyBatchService obj= "CORP\svc-batch$"
Restart-Service MyBatchService

从 services.msc 设置时,帐户名也像 CORP\svc-batch$ ── 结尾加上 $,密码栏留空。MSA 系列帐户不能用于交互式登录。1 之后在共享文件夹或 SQL Server 的 ACL 授予 CORP\svc-batch$ 取代 PC$,以服务专属身份的网络访问就完成了,而且不必密码。

8.4. 有些应用程序不支持

要注意的是,不是每套软件都能以 gMSA 运行。通过标准机制设置登录身份的 ── Windows 服务、IIS 应用程序池、任务计划程序任务 ── 支持面很广,但也有限制,例如故障转移群集本身不支持 gMSA,以及内部要求密码的应用程序不能用。10 Microsoft 也明白写道,正式上线前应在测试环境确认以 gMSA 运行的行为。9

如何判断是否支持 gMSA通过标准机制设置登录身份的应用程序广泛支持 gMSA,但故障转移群集与内部要求密码的应用程序不能用,因此正式上线前要在测试环境确认标准机制要求密码目标应用程序登录怎么设置?支持 gMSA服务、IIS、任务不能用 gMSA故障转移群集正式上线前测试

图 17: 通过标准机制设置登录的应用程序广泛支持,但也有不支持的设计,正式上线前的验证不可或缺。

还有兄弟帐户:单台服务器的 sMSA(独立托管服务帐户),以及 Windows Server 2025 引入、绑定设备身份以对抗凭据窃取的 dMSA(委派托管服务帐户)。新建时以 gMSA 为基准,再按需求考虑。6

9. 随附设计 ── 登录权利、配置文件、DPAPI、审计

还有四件会随帐户改变的事要记住。

9.1. “作为服务登录”权利(SeServiceLogonRight)

要以服务启动,帐户需要“作为服务登录”用户权利。LocalSystem、LocalService、NetworkService 内置就有,但 其他帐户(域用户、gMSA 等)需要显式指派15

若从 services.msc GUI 的“登录”选项卡设置,管理单元会自动授予此权利。另一方面,CreateService / ChangeServiceConfigsc.exe config 调用的 API)并不验证指定帐户是否有此权利。用脚本配置的服务在启动时以“因登录失败而无法启动服务”停下,典型原因就是这个。不要依赖工具的副作用;把显式加入本地安全策略(secpol.msc)的“作为服务登录”,或通过 GPO/Intune 配置,写进部署程序(若此权利由组策略配置,策略应用时会覆盖本地授予,这一点也要注意)。反过来说,服务专用帐户的标准动作是一并设置“拒绝本地登录”。

“作为服务登录”权利因配置路径而异services.msc GUI 会自动授予权利,但 sc.exe config 调用的 API 不验证权利,没有权利的帐户会在启动时因登录失败而停下在 services.msc 设置权利自动授予服务可以启动用 sc.exe config 设置不验证权利有权利吗?服务可以启动因登录失败停下用 secpol.msc 或 GPO 显式授予

图 18: GUI 会自动授予权利,但脚本配置不验证,因此程序里必须包含显式授予。

9.2. 配置文件、%TEMP%、HKEY_CURRENT_USER 会变

SCM 在服务启动时加载该帐户的用户配置文件。7 因此实际的 %TEMP%%APPDATA%HKEY_CURRENT_USER 依登录帐户而不同,切换帐户后,旧帐户配置文件里存的设置与缓存看起来像“消失了”。

设计上的对应很单纯:把服务数据不要放在配置文件底下,而是放在 C:\ProgramData\<应用程序名称> 这类明确路径,并把该 ACL 授予登录帐户。这样帐户变更就不必伴随数据迁移。

配置文件依赖与数据放置的对应实际配置文件依登录帐户而不同,切换帐户会让旧配置文件数据看起来像消失,但放在明确路径并授予 ACL 就不必迁移对应切换登录帐户加载不同的配置文件旧数据看起来像消失放到 ProgramData 底下把 ACL 授予登录帐户帐户变更也不必迁移

图 19: 避开配置文件、把数据放在明确路径,帐户变更就不再伴随数据迁移。

9.3. 以 DPAPI 保护的数据绑在帐户上

更容易漏掉的是 DPAPI。以用户范围 DPAPI(CryptProtectData 或 .NET 的 ProtectedData)加密的数据,原则上只有当初保护它的同一个帐户才能解密。一改帐户,存好的连接字符串或 API 密钥就读不到 ── 那是 DPAPI 在正确做事,但若不在迁移程序里就会变成事故。

DPAPI 保护数据与帐户变更的关系以用户范围 DPAPI 保护的数据只能由当初保护它的同一个帐户解密,因此更改登录帐户后需要重新输入机密同一个旧帐户新帐户用旧帐户做 DPAPI 保护受保护的连接字符串等哪个帐户在解密?能解密不能解密重新输入机密

图 20: DPAPI 保护的数据绑在当初保护它的帐户上,帐户切换后需要重新输入。

对应是把“帐户切换后重新输入机密”写进迁移计划(存储在哪里的设计见“Windows 应用程序不要把敏感信息以明文存进配置文件的最佳实践”)。此外,能用 gMSA 或 PC$ 以 Windows 集成身份验证做完的配置,可以根本不必存储机密。正确顺序是先考虑“能否不存”,再考虑“存在哪里”

若服务想“以调用者的权限”处理,不要把帐户变得更强,而是用模拟。那见“正确处理 Windows 的模拟令牌”。

9.4. 审计 ── 看 4624 登录类型 5

服务启动会以事件 ID 4624(帐户已成功登录)的 登录类型 5(Service:SCM 启动了服务) 写入安全事件日志。事件中的“Virtual Account”字段指出登录是否由 MSA / 虚拟帐户进行,也可用来监视托管帐户的使用。11

审计服务启动的流程SCM 启动服务会记录为事件 ID 4624 登录类型 5,Virtual Account 字段可识别是否为托管帐户登录SCM 启动服务记录事件 ID 4624登录类型 5(Service)Virtual Account 字段监视托管帐户

图 21: 服务启动记录为登录类型 5 的 4624,连托管帐户的使用都能跟踪。

现况盘点的快方法是汇总服务列表的登录帐户。

# Aggregate which services are running as which account
Get-CimInstance Win32_Service |
    Group-Object StartName |
    Sort-Object Count -Descending |
    Select-Object Count, Name

# Inventory non-standard services running as LocalSystem (tell in-house / third-party by the path)
Get-CimInstance Win32_Service |
    Where-Object { $_.StartName -eq 'LocalSystem' -and $_.PathName -notlike '*\Windows\*' } |
    Select-Object Name, DisplayName, PathName

若这份输出排着“以 LocalSystem 运行的业务服务”与“以域用户运行的服务”,就该叫出下一章的判断流程。

10. 判断流程 ── 用四个问题决定

把到目前为止的内容收成选择程序。按序回答四个问题。

登录帐户的判断流程按序回答是否有网络访问、是否加入域、机器级身份是否足够、是否支持 gMSA 这四个问题,决定登录帐户对端要 Windows 验证?虚拟帐户需要时用 LocalSystem已加入域?保护存储的凭据机器级就够?虚拟帐户 + PC$应用程序支持 gMSA?gMSA用户 + 缓解

图 22: 按序回答四个问题,六种选择该用哪一种就定了。

问题 1:该服务是否以 Windows 身份验证访问网络上的另一台机器(共享文件夹、数据库、API 等)?

若否,虚拟帐户是默认。只有需要特殊本地权限时,先确认需求再考虑 LocalSystem。

问题 2:(若有访问)机器是否已加入域?

工作组既不能用 PC$ 也不能用 gMSA。使用显式处理目标端帐户凭据的设计(用 DPAPI 等保护存储),或考虑加入域。

问题 3:(在域内)机器级身份(PC$)够用吗?

够用就 虚拟帐户(或 NetworkService)+ 在目标端 ACL 授予 PC$ 即完成。若需要服务专属身份,或跨多台服务器的共同身份,进问题 4。

问题 4:应用程序支持 gMSA 吗?

支持(通过标准机制设置登录的 ── SCM、IIS 应用程序池、任务计划程序 ── 一般支持)就用 gMSA。别忘了在验证环境做行为检查。再怎样都不支持,就在套用 7.3 节全部缓解后使用 专用域用户

做成表如下。

状况 建议 备注
仅本地、一般权限 虚拟帐户 把 ACL 授予 NT SERVICE\<名称>
仅本地、需要超出管理员的权限 LocalSystem 先验证权限需求
不需要网络身份的本地处理 LocalService 维持既有服务现状时可接受
以机器身份访问域内资源 虚拟帐户(或 NetworkService) 在目标端 ACL 授予 PC$
以服务专属身份访问域内资源 gMSA KDS 根密钥 + 确认支持
多台服务器同一身份(负载均衡等) gMSA 虚拟帐户做不到
不支持 gMSA 的应用程序 + 需要特定身份 专用域用户 需要 7.3 节的缓解
工作组 + 需要远程访问 保护并存储显式凭据 也考虑重新审视设计

11. 总结

  • 服务的登录帐户是同时决定本地权限、网络身份与密码管理的设计决策。不要留在默认(LocalSystem)。
  • LocalSystem 持有 SYSTEM+Administrators 令牌与强特权,被接管时伤害最大化。多数业务服务不需要这个权限。
  • LocalService 与 NetworkService 都是低权限;差别是网络身份(匿名,或计算机帐户)。但帐户由多个服务共用,因此分不开。
  • 虚拟帐户(NT SERVICE\<服务名称>)是现代默认:不必管密码又能按服务分开。可直接指定到 ACL,配置只需改登录帐户名。
  • LocalSystem、NetworkService、虚拟帐户在域环境走上网络时是 DOMAIN\PC$。在共享文件夹或 SQL Server 的 ACL 授予 PC$,常常就能不用域用户。
  • 把域用户用在服务上,有到期停摆、明文密码扩散、Kerberoasting 这些结构性问题。若要用,需要专用帐户 + 长随机密码 + 登录限制。
  • gMSA 是 AD 自动生成并轮换密码的机制;要件是域、功能级别 2012 或更高、KDS 根密钥。服务设成“DOMAIN\名称$”且密码栏留空。
  • 改帐户时,把“作为服务登录”权利、配置文件与 %TEMP% 的搬移、DPAPI 保护数据的重新输入写进迁移程序。审计可用事件 ID 4624 登录类型 5 确认。

下次安装服务时,在登录设置画面停一下,再问一次。这个服务应该以谁的身份、访问到多远? 答案应该是本文判断表的某一行。

相关文章

相关咨询领域

小村软件有限公司承接 Windows 服务与常驻应用程序的登录帐户设计与最小权限强化、把以 LocalSystem 为前提打造的既有服务迁到虚拟帐户或 gMSA,以及帐户变更后因访问被拒、DPAPI、配置文件引起的故障调查。从“审计被点名了,但不知道从哪里开始”这个阶段开始也可以。

参考链接

  1. 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

  2. Microsoft Learn, Securing on-premises service accounts. 本地部署服务的优先顺序是先 gMSA、不能用再用 sMSA、然后计算机帐户、最后用户帐户;使用计算机帐户时无法得知哪个服务在用该帐户也不能审计更改;以及服务帐户的角色(识别、验证并启动服务)。  2 3

  3. Microsoft Learn, LocalSystem Account. LocalSystem 在本地计算机持有广泛权限且令牌含 NT AUTHORITY\SYSTEM 与 BUILTIN\Administrators 的 SID、没有密码、向远程服务器出示计算机的凭据、含 SE_DEBUG_NAME 与 SE_TCB_NAME 的特权清单,以及多数服务不需要这个权限级别、应考虑使用 LocalService/NetworkService。  2 3 4 5 6

  4. Microsoft Learn, sc.exe config. 用 obj= 参数指定服务的登录帐户、默认是 LocalSystem,以及使用 LocalSystem 以外的用户帐户时的 password= 参数。  2

  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 4

  6. Microsoft Learn, Service accounts. 虚拟帐户是不需密码管理的自动管理本地帐户、名称为 NT SERVICE<SERVICENAME> 形式、在域环境以计算机帐户凭据(\$)访问网络,以及在 sMSA、gMSA、dMSA、虚拟帐户之间选择的准则。  2 3 4

  7. Microsoft Learn, Service User Accounts. 服务在用户帐户的安全上下文中运行、SCM 在启动时登录帐户并把访问令牌关联到服务进程、SCM 加载用户配置文件,以及 SCM 不管密码到期,到期会让登录失败、服务无法启动。  2 3 4 5

  8. Microsoft Learn, Protect SMB traffic from interception. 包含以 gMSA 作为服务帐户保护(机器生成的长随机密码使暴力破解或字典攻击不实际)、强制长密码,以及提及 Kerberos 装甲(FAST)等建议。  2

  9. Microsoft Learn, Secure group managed service accounts. gMSA 密码是难以暴力破解或字典攻击的 240 字节随机生成、Windows 操作系统每 30 天更改密码故管理员不必规划更改或停止服务、部署到服务器场与更单纯的 SPN 管理、若服务不支持 gMSA 就用 sMSA、再不行就用有强密码管理的标准用户帐户,以及正式上线前应在测试环境确认以 gMSA 运行的行为。  2 3

  10. 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

  11. Microsoft Learn, 4624(S): An account was successfully logged on. 创建登录会话时事件 4624 记录在被访问的计算机上、登录类型 5 表示服务(SCM 启动服务),以及“Virtual Account”字段可识别 MSA 或虚拟帐户的登录,可用来监视托管服务帐户。  2

  12. Microsoft Learn, About Windows Resource Protection. Windows 资源保护(WRP)防止重要系统文件、文件夹与注册表项被替换、对 WRP 保护资源的完全访问限于 TrustedInstaller 且更改只能通过 Windows Modules Installer 服务的受支持替换机制进行,以及试图更改受保护资源的应用程序会收到访问被拒。 

  13. Microsoft Learn, Group Managed Service Accounts overview. gMSA 是把密码管理交给 Windows 的域帐户、域控制器从 Key Distribution Service(kdssvc.dll)共享机密计算密码且成员主机向域控制器查询当前与先前密码,以及它让服务器场能以同一主体互相验证。 

  14. Microsoft Learn, Create a Key Distribution Service (KDS) root key. 域控制器开始生成 gMSA 密码需要根密钥、用 Add-KdsRootKey -EffectiveImmediately 创建的程序、创建后最多 10 小时因等待 AD 复制收敛而不能创建 gMSA,以及复制不完整可能让密码取回失败。 

  15. Microsoft Learn, Policy CSP - UserRights: LogOnAsService. “作为服务登录”权利让安全主体能以服务登录、Local System、Local Service、Network Service 内置此权利、以其他帐户运行的服务需要指派此权利,以及组策略配置路径。 

共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。

与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。

本文与以下服务页面相关联,欢迎从最接近的入口查看。

常见问题

汇总了咨询这一主题时常见的问题。

目前以 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 而不是域用户。

作者简介

本文作者的个人简介页面。

Go Komura

小村软件有限公司 代表

以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。

返回博客列表