AD 域控分层加固要解决的不是「配置项够不够多」,而是「域管理员凭据会在哪些机器上出现」。绝大多数域控沦陷事件的路径都一样:运维用域管账号登录了一台被钓鱼的办公电脑,凭据落进 lsass,攻击者再用它登录域控。分层模型的作用就是提前规定凭据只能在哪些层级流动,再配合 LAPS 与 gMSA 把「共享的本地管理员口令」和「明文服务账号口令」这两类最容易扩散的凭据消灭掉。
适用场景
- 域内主机数量超过 30 台,运维仍习惯用 Domain Admins 直接登录业务服务器排障。
- 所有服务器共用同一套本地 Administrator 口令,一台机器被拿下等于全部主机失守。
- 等保测评或内部审计提出「应划分管理角色、限制特权账号使用范围」的整改项。
- 发生过域内异常登录,需要按层级收权并补齐可追溯的审计证据。
前置条件
- Windows Server 2016 及以上域控,域功能级别 2016 或更高(LAPS 的 AD 架构扩展有版本要求)。
- 执行操作使用一个专用管理账号,并已临时加入 Domain Admins,操作完成后立即移出。
- 管理机安装 RSAT 的 ActiveDirectory PowerShell 模块与 LAPS 模块。
- 已备份系统状态(
wbadmin start systemstatebackup)与 GPO 备份(Backup-GPO)。 - 域内已存在可用的时间同步源,Kerberos 对时间偏差敏感。
原理说明
Tier 模型按「控制能力」而不是「资产价值」分层。Tier 0 是能直接或间接控制域身份的所有组件:域控、AD 数据库文件、AD 证书服务、 federation 服务、以及域控的备份与虚拟化宿主。Tier 1 是企业服务器与应用。Tier 2 是员工终端。规则只有一条:高层级凭据可以登录低层级主机,低层级凭据永远不能登录高层级主机。凭据是单向流动的,一旦反向流动,分层就失效。
落地手段有三类。第一类是登录权限限制:通过组策略的「用户权限分配」把 Tier 0 主机上的「允许本地登录」「允许通过远程桌面服务登录」「从网络访问此计算机」三项权限,收窄到只有 Tier 0 管理员组;同时用「拒绝本地登录」「拒绝从网络访问」把 Domain Users 等宽泛组挡在域控之外。第二类是本地管理员口令去共享化:Windows LAPS 把每台机器的本地管理员密码托管到 AD 的一个受 ACL 保护的属性上,按周期自动轮换,读取权限按 OU 委派。第三类是服务账号去口令化:gMSA 的密码由域控每 30 天自动重置,服务进程通过 Kerberos 取票,磁盘上不存在可被抓取的口令。
这三类手段互补:登录限制解决「能不能进去」,LAPS 解决「本地提权后能横向多远」,gMSA 解决「服务账号被离线抓取」。只做其中一项,攻击者仍能从另外两个口子回到域控。
操作步骤
第一步:盘点 Tier 0 资产与特权组
先把「谁能控制域」列清楚,否则后面的限制对象会漏人。以下脚本递归展开所有高权限组,输出成员类型,user 是需要立刻收敛的,group 要继续往下展开。
Import-Module ActiveDirectory
$tier0Groups = @(
"Domain Admins","Enterprise Admins","Schema Admins",
"Administrators","Account Operators","Backup Operators",
"Key Admins","Enterprise Key Admins","Domain Controllers"
)
$rows = foreach ($g in $tier0Groups) {
$members = Get-ADGroupMember -Identity $g -Recursive -ErrorAction SilentlyContinue
foreach ($m in $members) {
[pscustomobject]@{
Group = $g; Name = $m.SamAccountName; Class = $m.objectClass
}
}
}
$rows | Sort-Object Group, Name -Unique | Format-Table -AutoSize
$rows | Sort-Object Name -Unique | Export-Csv .\tier0-members.csv -NoTypeInformation -Encoding UTF8
导出的 CSV 就是收敛名单。经验值:成员总数超过 5 个 Domain Admins 的组织,通常有 60% 以上是不再需要的遗留账号或离职账号残留。
第二步:用组策略封死域控的登录面
在域控 OU 上新建并链接一个 GPO,只保留三项关键设置。图形界面路径为「计算机配置 → 策略 → Windows 设置 → 安全设置 → 本地策略 → 用户权限分配」。
- 允许本地登录:只留
Administrators、Enterprise Admins、Domain Admins、GG-Tier0-Admins(自建的 Tier 0 管理组)。 - 允许通过远程桌面服务登录:同上,删除
Remote Desktop Users。 - 拒绝从网络访问这台计算机:加入
Domain Users、Everyone、ANONYMOUS LOGON。
用 secedit 把当前生效值导出比对,确认策略真的落地,而不是链接到了错误的 OU:
secedit /export /cfg C:\Windows\Temp\dc-sec.inf /areas USER_RIGHTS
Select-String -Path C:\Windows\Temp\dc-sec.inf -Pattern "SeInteractiveLogonRight|SeDenyNetworkLogonRight|SeRemoteInteractiveLogonRight"
# 确认 GPO 是否生效及来源
gpresult /h C:\Windows\Temp\dc-gp.html /f
gpresult /r /scope:computer | Select-String -Pattern "已应用|Applied"
注意 SeDenyNetworkLogonRight 的优先级高于允许项:把 Domain Users 写进拒绝列表后,即使某人在允许列表里也会被拒。所以 Tier 0 管理员不要用日常账号,必须用独立的 a- 前缀管理账号。
第三步:部署 Windows LAPS 托管本地管理员密码
先扩展 AD 架构,再按 OU 委派读密权限,最后用 GPO 下发客户端配置。架构扩展是不可逆操作,务必在变更窗口执行。
# 1) 扩展架构(仅需一次,需 Schema Admins)
Update-LapsADSchema -Verbose
# 2) 允许计算机对象自行写入密码属性
Set-LapsADComputerSelfPermission -Identity "OU=Tier1-Servers,DC=corp,DC=example,DC=com"
# 3) 只允许指定安全组读取密码
Set-LapsADReadPasswordPermission -Identity "OU=Tier1-Servers,DC=corp,DC=example,DC=com" `
-AllowedPrincipals "GG-LAPS-Readers"
# 4) 允许重置密码(用于应急轮换)
Set-LapsADResetPasswordPermission -Identity "OU=Tier1-Servers,DC=corp,DC=example,DC=com" `
-AllowedPrincipals "GG-LAPS-Admins"
GPO 侧路径为「计算机配置 → 管理模板 → 系统 → LAPS」,关键参数:密码长度 24、密码复杂度 4(大小写+数字+符号)、密码期限 30 天、管理员账户名保留默认或改为非 Administrator 的自定义名、启用密码加密。密码期限不建议超过 90 天,短于 7 天则域控写入压力明显上升。
第四步:把服务账号迁到 gMSA
域内凡是「某服务以域账号运行且口令写在配置文件里」的,都要迁成组托管服务账号。gMSA 的口令由域控托管、30 天自动轮换,攻击者拿到磁盘镜像也取不到可用凭据。
# 创建 gMSA,并授权指定主机组读取口令
New-ADServiceAccount -Name gmsa-app01 `
-DNSHostName gmsa-app01.corp.example.com `
-PrincipalsAllowedToRetrieveManagedPassword "GG-APP01-Hosts" `
-ManagedPasswordIntervalInDays 30
# 在目标主机上安装并自检
Install-WindowsFeature RSAT-AD-PowerShell
Install-ADServiceAccount -Identity gmsa-app01
Test-ADServiceAccount -Identity gmsa-app01
# 服务改为以 gMSA 运行(无密码)
sc.exe config "AppSvc" obj= "CORP\gmsa-app01$" password= ""
password= "" 中间的空格不能省,这是 sc.exe 的参数分隔约定,写成 password="" 会被当作服务名的一部分。
第五步:开启目录服务审计
没有审计的分层只能算「配了」,不能算「可控」。开启以下子类别,并把日志转发到独立收集器,防止攻击者清日志:
auditpol /set /subcategory:"目录服务访问" /success:enable /failure:enable
auditpol /set /subcategory:"目录服务更改" /success:enable /failure:enable
auditpol /set /subcategory:"账户管理" /success:enable /failure:enable
auditpol /set /subcategory:"登录/注销" /success:enable /failure:enable
auditpol /get /category:* | findstr /i "目录服务 账户管理"
重点盯四类事件:4624(登录成功,关注 Logon Type 3/10 与源 IP)、4672(授予特殊特权,任何非管理时段出现都要查)、4728/4732/4756(成员加入特权组)、5136(目录对象被修改,含 LAPS 属性读取之外的写入)。
配置验证
- 用普通域账号尝试
\\DC01\C$,应返回拒绝访问;用 Tier 0 管理账号应可访问。 - 在域控上执行
whoami /priv确认无异常特权;nltest /dsgetdc:corp.example.com返回正常。 - LAPS 读取:
Get-LapsADPassword -Identity SRV01 -AsPlainText应返回密码与过期时间;用非授权账号执行应报权限不足。 - gMSA 验证:
Test-ADServiceAccount -Identity gmsa-app01返回True;klist能看到对应服务票据。 - 审计验证:手动把测试账号加入 Domain Admins 再移出,事件查看器应产生 4728 与 4756 两条记录。
常见问题 FAQ
FAQ 1:LAPS 密码读取权限应该给谁?能不能直接给全域 Helpdesk?
不能。读密权限等价于「拿到该 OU 内所有主机的本地管理员」,属于 Tier 1 权限。正确做法是按 OU 建立 GG-LAPS-Readers-<业务线> 组,只委派对应 OU,且组内成员使用单独账号、开启多因素认证。域控 OU 的读密权限建议只给安全团队,Helpdesk 一律不给。所有读密操作都会在域控产生 4662 事件,配合 LAPS 密码检索 审计可以还原「谁在什么时候看了哪台机器的密码」。
FAQ 2:只有 3 台服务器的中小企业,Tier 模型是不是过度设计?
结构可以简化,原则不能省。最小落地清单是三条:域管账号只用于登录域控,日常运维使用单独的服务器管理账号;域控 OU 上加「拒绝 Domain Users 网络访问」;所有机器启用 LAPS。这三条加起来不到两小时工作量,却切断了「办公电脑被钓鱼 → 抓取域管凭据 → 登录域控」这条最常见的路径。Tier 0/1/2 的完整划分可以等到主机数超过 50 台再补。
FAQ 3:加了「拒绝本地登录」后运维远程登录失败,怎么快速回滚?
不要直接改生产 GPO。先把该 GPO 的链接禁用(不是删除),在域控上执行 gpupdate /force,然后 gpresult /r 确认策略已不再应用。恢复访问后,在测试 OU 上先用一台机器验证新的允许列表包含全部必要的管理组,再重新链接。建议把登录权限策略拆成独立的 GPO,与密码策略、审计策略分开,出问题时可以单独摘除,避免连带回滚。
总结
AD 域控分层加固的收益不在配置本身,而在它把「一次终端失陷」和「整个域沦陷」之间的路径切断。落地顺序建议按风险排序:先做域控登录面收窄(当天可完成、影响面可控),再做 LAPS(消除共享口令),然后迁移 gMSA(消除磁盘明文口令),最后补审计与日志外发。四步之间没有依赖关系,但每一步都要有验证动作和回滚方案,否则改完不知道是否生效,等于没改。