DCSync域内权限维持:原理、落地与检测对抗
“域内权限维持”这个话题做内网方向的朋友应该都不陌生。而DCSync几乎是这条链路上绕不开的一环——它不往目标机器上落地任何文件不需要在域控上开一个交互式会话也不会去碰 LSASS 进程只是安安静静地“要一份数据”域控就老老实实把凭据交了出来。我第一次在授权环境里接触它的时候最大的感受不是“好用”而是“太安静了”安静到很多防守方事后复盘时根本意识不到有人来过。这篇文章我想把 DCSync 在域内权限维持场景下的原理、落地思路、检测与对抗掰开揉碎讲一遍重点不是教你“打”而是让你在防守时知道该看哪里在授权测试时知道该记什么、留什么证据。内容适合有过 AD 基础、做过内网横向、或者负责域环境安全加固的同行参考纯小白顺着原理部分也能理解个大概——毕竟这个东西的底层逻辑其实跟“两个仓库管理员互相调货”差不多。1. DCSync 的技术底子它到底在“同步”什么1.1 多主复制模型是这一切的前提要理解 DCSync得先理解 Active Directory 为什么需要复制。AD 是一个多主multi-master的目录数据库一个域里通常有多台域控任何一台都可以接受写操作写完之后再通过复制把变更传播给其他域控。为了让这个过程高效且可追溯每一台域控都会为目录里的每个对象维护一组 USNUpdate Sequence Number并且通过 KCCKnowledge Consistency Checker自动计算复制拓扑站点内默认 15 秒触发一次通知式复制站点间按链路开销和计划表走。关键在于这套复制机制并没有规定“只有域控才能发起复制请求”。协议层面它信任的是调用方是否持有正确的权限而不是“调用方是不是一台域控”。这就留下了一个非常微妙的口子只要某个安全主体在域命名上下文上被授予了“复制目录更改”相关的扩展权限它就可以像一台域控一样向真正的域控发起复制请求然后拿到包括密码哈希在内的敏感属性。生活化的类比是这样的两家仓库之间有固定的调货流程管理员 A 只要出示一张合规的调货单管理员 B 就会把货交出来。B 不会去核实 A 到底是不是仓库管理员他只看单子对不对。DCSync 做的就是伪造一张“合规的调货单”。1.2 DRSBind 与 DRSGetNCChanges 两个调用构成了核心链路从协议层面看DCSync 走的是 Microsoft Directory Replication ServiceDRSRemote Protocol核心是两个 RPC 调用。第一个是DRSBind作用类似于“报到”。调用方向域控的\pipe\lsarpc或 DRSUAPI 接口发起绑定把自己伪装成一个复制伙伴。这一步本身不涉及敏感数据只是建立一个上下文。第二个是DRSGetNCChanges这才是真正“提货”的动作。调用方需要指定命名上下文NC比如DCexample,DClocal这个域分区并且可以指定想要拉取的属性集。如果请求里带了DRS_EXTENDED_OP之类的标志还可以要求返回更完整的数据。域控收到请求后会做一次权限检查调用方是否具备该分区上的复制权限有就把数据打包返回。返回的数据包里包含的是目录对象的完整属性这里面就有unicodePwd、dBCSPwd、supplementalCredentials这类敏感字段。对于用户对象而言unicodePwd本身就是 NT 哈希的存储形式supplementalCredentials里则可能包含 Kerberos 的 AES 密钥。换句话说一次成功的复制请求等于把域内所有账户的凭据材料打包带走。提示很多人以为 DCSync 只能拿 krbtgt其实它的能力范围是整个分区的所有对象属性包括计算机账户、服务账户、msDS-KeyCredentialLink 等。理解这一点对后续设计检测规则很重要。1.3 三个权限位决定了“能不能提货”域控在做权限检查的时候看的不是组 membership而是对象 ACL 上有没有对应的控制访问项ACE。具体涉及三个扩展权限它们的 GUID 是公开且固定的权限名称GUID作用范围DS-Replication-Get-Changes1131f6aa-9c07-11d1-f79f-00c04fc2dcd2允许读取目录变更DS-Replication-Get-Changes-All1131f6ad-9c07-11d1-f79f-00c04fc2dcd2允许读取包括机密属性在内的全部变更DS-Replication-Get-Changes-In-Filtered-Set89e95b76-444d-4c62-991a-0facbeda640c允许读取过滤集中的属性较新系统引入实际利用中前两个是必须的第三个是加分项。这三个权限默认只授予Domain Controllers、Enterprise Domain Controllers以及少数几个系统内置主体。也就是说只要能给任意一个普通账户加上前两个 ACE这个账户就具备了 DCSync 的能力。这里有个容易被忽略的细节ACE 是加在域根对象DCexample,DClocal上的而这个 ACE 会继承到整个分区下的所有对象。所以不需要在每个 OU 上重复授予一次授予全域生效。这也是为什么权限维持场景下攻击方特别喜欢这条路径——一次操作长期有效而且默认不会触发任何安全告警。1.4 为什么它比常规凭据抓取更适合“维持”对比一下常见的凭据获取手段DCSync 的隐蔽性优势非常明显不落地文件不需要往目标机器上传 mimikatz 之类的工具全部操作通过 RPC 完成。不触碰 LSASS绕开了绝大多数基于 LSASS 访问的 EDR 检测点。不需要交互式登录只要能发起到域控 135/445/49152 端口的 RPC 连接就可以执行。可以跨网段从一台普通工作站发起只要网络可达即可。日志稀疏默认审计策略下成功路径几乎不留痕迹只有开启“目录服务访问”审核之后才会在 4662 事件里留下记录。这几点叠加起来就解释了为什么 DCSync 在权限维持环节如此受欢迎——它不像黄金票据那样需要拿到 krbtgt 之后还要考虑票据生命周期也不像影子凭据那样需要改目标对象的属性会触发 5136 事件。它更像是一种“订阅”关系只要权限还在随时可以再来取一次。2. 权限维持视角下的落地思路2.1 一次性窃取和长期维持是两套逻辑很多人把 DCSync 当成“一次性拿哈希”的工具用完就走。但在权限维持的语境下思路要转过来真正的价值不在于这一次拿到了什么而在于下一次还能不能拿到。一次性窃取的典型路径是拿到某个具备复制权限的账户 → 执行一次复制 → 拿到域管哈希 → 横向 → 结束。这条路径的问题在于一旦域管密码被重置或者 krbtgt 被重置两次之前拿到的材料就全部作废需要重新找入口。长期维持的思路则完全不同目标不是“拿到哈希”而是“建立一个可重复调用的通道”。具体表现为在域内留一个低关注度的安全主体比如一个看起来像服务账户的用户或者一个嵌套很深的组给它赋予复制权限然后让这个主体处于休眠状态。需要的时候激活它执行复制再休眠。这种模式下即使防守方做了一次全面排查只要没有专门审计 ACL这个通道依然存在。2.2 权限授予的几条路径与痕迹对比在实际授权测试中给主体授予复制权限的路径不止一条留下的痕迹也不一样。我整理了一个对比表路径操作对象主要痕迹隐蔽性评价直接在域根 ACL 添加 ACE域命名上下文5136对象修改、4662后续复制中ACL 变更本身较显眼通过已有高权限组间接获得组成员关系4728/4732组变更中低取决于组本身的关注度利用 AdminSDHolder 传播AdminSDHolder 容器5136、后台 SD 传播器周期性写 ACL中传播周期约 60 分钟时序特征明显修改对象的 nTSecurityDescriptor任意对象5136低但容易破坏继承链借助已有的复制权限账户无需变更仅 4662高前提是找得到这类账户第三条路径值得多说两句。AdminSDHolder 是 AD 里一个特殊容器系统有个后台线程SDProp默认每 60 分钟运行一次把 AdminSDHolder 上的 ACL 强制覆盖到所有受保护对象域管、企业管理员等上。如果在 AdminSDHolder 上加一条 ACE那么所有特权账户都会被“传染”上这条权限。这个手法的隐蔽性在于它不需要直接改特权账户本身但缺点是传播有固定周期时序上很容易被关联分析抓出来。第四条路径也就是直接改nTSecurityDescriptor是最不推荐的做法。这个属性一旦写错很容易破坏 ACL 继承导致域内权限混乱严重的甚至需要从备份恢复。在授权测试里这么做属于给自己挖坑。注意无论走哪条路径在授权环境中都必须提前记录变更前的 ACL 快照。没有快照事后清理就是一场灾难。这一点我在实际项目里吃过亏后面会详细说。2.3 维持链路的稳定性要提前设计一个能长期存活的 DCSync 通道需要考虑几个稳定性因素这些因素在设计阶段就得想清楚不能等通道断了再补。第一是账户的生命周期。如果用的是新建账户要考虑密码策略默认域策略可能是 42 天过期、账户锁定策略、以及是否会被资产管理系统标记为“僵尸账户”。比较稳妥的做法是挂靠在一个已有的、看起来合理的服务账户上或者干脆利用机器账户——机器账户的密码是系统自动轮换的不需要人工维护反而更稳定。第二是域控的可用性。域内通常有多台域控如果只盯着其中一台那台宕机或者被打补丁通道就断了。实际做法是把所有域控的 IP 都列出来做失败重试只要能连上一台就能提货。第三是权限的持久性。如果给某个账户授予了复制权限而这个账户后来被加入了某个组组的嵌套可能导致权限被间接放大或覆盖。另外如果防守方做了 ACL 清理比如用脚本批量移除可疑 ACE通道就会断。所以好的设计会准备两条独立通道一条在主路径上另一条藏在不易被清理的位置。第四是时间同步。DRS 协议对时间偏差有一定容忍度但 Kerberos 认证本身要求客户端与域控的时间偏差在 5 分钟以内。如果发起复制的主机时间漂移过大会在认证阶段就失败表现为“绑定失败”而不是“权限不足”排查时容易误判。2.4 授权测试中的记录义务这一节是写给做授权项目的同行的。DCSync 这类操作在授权测试里有明确的记录要求变更前 ACL 快照、变更的具体 ACE谁、什么权限、加在哪个对象上、变更时间、执行人、以及清理计划和清理验证结果。我见过不止一个项目测试结束后只写了一句“已清理”结果防守方复测时发现 ACE 还在直接导致验收不通过。原因很简单ACL 的继承机制会导致“删了父对象上的 ACE子对象上的显式 ACE 还在”如果当初是在子对象上加的清理时就必须回到子对象去删。提示清理之后一定要做一次回归验证用同一个账户再发起一次复制请求确认返回的是“访问被拒绝”而不是“成功”。只删不验等于没删。3. 授权环境中的复现步骤与关键参数3.1 前置条件核对清单在动手之前先把下面这张表过一遍任何一项不满足后续操作都会卡住。检查项说明不满足时的表现已获得书面授权明确授权范围包含域环境不合规不应继续具备域内任意有效凭据用于发起 RPC 绑定RPC 绑定失败网络可达域控 RPC 端口135、445、49152-65535 动态端口连接超时主机时间与域控偏差 5 分钟Kerberos 认证前提认证失败报时钟偏差具备修改 ACL 的权限通常是域管或具备 WriteDACL 的主体写入 ACE 时拒绝访问已准备好 ACL 快照工具用于变更前备份事后无法精确回滚这里重点说一下第五项。授予复制权限本身是一个 ACL 写操作需要调用方对目标对象的nTSecurityDescriptor具备写权限。如果手上只有普通域用户凭据是没法直接加 ACE 的。实际路径通常是通过某种方式先拿到 WriteDACL 能力比如利用某些组的内置权限或者通过已有的高权限会话。3.2 权限授予的操作要点授予操作的本质是往域根对象的 DACL 里追加一条ExtendedRight类型的 ACEObjectType指向前面表格里那两个 GUIDAccessControlType为AllowIdentityReference指向目标主体。操作上有几个细节必须注意第一ACE 要加在域根上不要加在 OU 上。加在 OU 上只对那个 OU 生效覆盖面太窄而且 OU 数量多容易被逐层排查发现。加在域根上继承机制会自动覆盖全域。第二继承标志要设对。一般设置为“应用到本对象及所有子对象”也就是ContainerInherit | ObjectInherit。如果只设了ThisObject那这个 ACE 只对域根自身有效复制请求会被拒绝。第三主体选择要慎重。直接用域管账户加权限等于把“这里有鬼”写在脸上。实际更常见的是选一个看起来人畜无害的主体比如某个业务系统使用的服务账户或者一个从名字上看像是备份用途的账户。第四操作完成后立刻验证。验证方式不是看 ACL 里有没有这条记录而是实际发起一次复制请求看能不能拿到数据。ACL 记录正确但复制失败的情况很常见原因可能是继承没生效需要等待或强制刷新、或者主体被其他 Deny ACE 覆盖。3.3 触发复制与验证复制请求的触发协议层面是构造DRSGetNCChanges调用指定目标 NC 和需要的属性集。在实际操作中通常会封装成工具来做但核心参数就那么几个目标 NC一般是域分区本身格式为DCexample,DClocal。对象 DN可以指定只复制某个特定对象比如只拉取krbtgt或者某个域管账户减少数据量和日志噪音。属性范围可以选择全属性也可以只拉取敏感属性。只拉敏感属性的话日志里的数据包大小会小很多但痕迹反而更可疑因为正常复制不会只拉这几个属性。复制标志DRS_EXTENDED_OP这类标志会影响返回数据的完整性一般保持默认即可。验证成功的标志是返回的数据结构里包含目标对象的凭据材料而不是仅仅“调用没报错”。有些工具在权限不足时会静默返回空结果看起来像是成功了实际上是失败的。注意验证阶段不要用域管账户去测否则一旦被审计到等于把“域管账户发起了异常复制请求”这条高价值告警直接送到防守方手里。用那个专门为维持准备的低关注账户去测。3.4 参数量级与性能考量完整复制一个中等规模域几万个对象的数据量大概在几百 MB 到 1 GB 之间这个量级在带宽充足的情况下几分钟就能拉完。但在权限维持场景下根本不需要全量复制。实际做法是精确指定目标对象比如只拉krbtgt和两三个域管账户数据量可以压缩到几十 KB。这样做的另一个好处是日志体积小不容易在流量分析里触发告警。对象 DN 的构造需要注意转义。如果对象名里包含逗号、加号、反斜杠这类特殊字符必须按 RFC 4514 的规则转义否则 DN 解析会失败表现为“对象不存在”而不是“权限不足”很容易误导排查方向。还有一个容易踩的坑是域控选择。如果域内有只读域控RODC复制请求打到 RODC 上会失败因为 RODC 本身不具备完整的复制能力。所以脚本里要显式跳过 RODC或者干脆只连可写域控。4. 检测与排查DCSync 留下的蛛丝马迹4.1 审计策略必须先打开这是所有检测工作的前提。默认状态下Windows 的安全日志不会记录目录服务的访问也就是说 DCSync 成功了也不会留下 4662 事件。很多环境之所以对这类行为“零感知”根本原因是审计策略从来没配过。需要开启的高级审计策略包括审计目录服务访问Audit Directory Service Access对应 4662 事件记录对象访问。审计目录服务更改Audit Directory Service Changes对应 5136 事件记录对象属性修改。审计账户管理对应 4720/4728/4732 等记录账户和组变更。审计登录事件对应 4624/4625用于关联源主机。开启方式可以通过组策略统一推送路径在“计算机配置 → Windows 设置 → 安全设置 → 高级审核策略配置 → 对象访问”下。不要只开基础审核策略基础策略在域控上的记录粒度不够很多对象的访问根本不会记录。开启之后日志量会显著上升尤其是 4662 事件在大型域里每天可能产生几十万条。这时候就必须靠过滤规则来降噪否则日志系统会被淹没。4.2 4662 事件的正确读法4662 事件的关键字段是Properties它记录了本次访问涉及的对象属性 GUID 和扩展权限 GUID。要检测 DCSync就是在这个字段里匹配前面提到的两个复制权限 GUID。一个典型的可疑 4662 事件长这样事件 ID: 4662 主体: EXAMPLE\svc_backup 对象: DCexample,DClocal 属性: {1131f6aa-9c07-11d1-f79f-00c04fc2dcd2} {1131f6ad-9c07-11d1-f79f-00c04fc2dcd2}关键判断点有三个第一主体是不是域控账户。正常的复制请求主体应该是EXAMPLE$这类机器账户或者Domain Controllers组。如果主体是一个普通的用户账户或服务账户基本可以判定为异常。第二源主机是不是域控。事件里的Account Domain和Logon ID可以关联出源 IP。如果源 IP 是一台普通工作站或者服务器同样高度可疑。第三属性组合是否符合正常复制模式。正常复制会请求大量的属性变更而 DCSync 往往只请求少数几个敏感属性这个特征可以作为辅助判断。写一个简单的筛选逻辑思路是这样的# 审计用途从安全日志中筛出可能涉及复制权限的 4662 事件 $events Get-WinEvent -FilterHashtable { LogName Security Id 4662 StartTime (Get-Date).AddHours(-24) } -ErrorAction SilentlyContinue $events | Where-Object { $_.Message -match 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 -or $_.Message -match 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 -or $_.Message -match 89e95b76-444d-4c62-991a-0facbeda640c } | Select-Object TimeCreated, {nDetail;e{$_.Message}} | Export-Csv -Path .\dcsync_suspect.csv -NoTypeInformation -Encoding UTF8这段代码只是把可疑事件捞出来真正的判断还得靠人工看主体和源主机。机器判断很容易误报因为某些备份软件也会调用类似的接口。4.3 ACL 基线审计比日志更可靠日志是“事后”的ACL 是“事中”的。如果能在 ACL 层面定期比对基线很多维持通道在建立阶段就会被发现而不是等到复制发生。审计的核心是找出所有非默认主体在域根上持有的复制权限。下面这段脚本可以直接用# 审计用途列出域根上被授予复制权限的非默认主体 $root DCexample,DClocal $replGuids ( 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2, 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2, 89e95b76-444d-4c62-991a-0facbeda640c ) $acl Get-Acl -Path AD:$root $acl.Access | Where-Object { $_.ObjectType -and ($replGuids -contains $_.ObjectType.Guid.ToString()) } | Select-Object IdentityReference, ActiveDirectoryRights, AccessControlType, ObjectType, InheritanceFlags, PropagationFlags | Format-Table -AutoSize跑出来的结果里如果出现了非Domain Controllers、非Enterprise Domain Controllers的主体就需要逐个确认来源。建议把这份输出做成周度基线每周跑一次与上周结果做 diff任何新增条目都要有人认领。这个方法的优点是成本低、误报少缺点是只能发现 ACL 层面的变更对于“借用已有复制权限账户”的情况无能为力。所以它必须和日志检测配合使用。4.4 排查速查表真到了排查阶段思路要按“从外到内”的顺序走避免一上来就扎进日志里出不来。排查顺序检查内容判断依据处置动作1域根 ACL 是否有多余的复制权限与基线 diff移除并回溯变更来源2AdminSDHolder 的 ACL 是否异常与默认模板比对还原并检查 SDProp 日志3近期是否有 4728/4732 组变更组成员是否被塞入异常账户回滚组变更44662 事件中主体非域控的记录主体类型 源主机 IP隔离源主机、重置凭据5服务账户的登录来源是否异常4624 的源 IP 与历史基线的偏差排查该账户是否泄露6krbtgt 密码上次重置时间是否早于可疑活动时间安排两次重置这张表的价值在于给出一个明确的执行顺序。实际响应中最怕的就是“大家一起上”结果 ACL 也改了、密码也重置了最后连原始现场都没保住。先取证、再处置这个顺序不能乱。注意如果确认存在未授权的复制行为重置 krbtgt 密码需要连续执行两次且两次之间要间隔大于域内最大票据生存期默认 10 小时再留出安全余量。只重置一次是没有意义的旧票据依然有效。5. 防御加固与对抗思路5.1 权限最小化是根本DCSync 能成立的前提是有主体持有多余的复制权限。所以最根本的防御手段就是把这份权限收归到最小范围。具体做法包括定期审计域根 ACL确认复制权限只授予Domain Controllers和Enterprise Domain Controllers对所有被授予复制权限的非默认主体要求业务方书面说明用途无说明的一律移除把 ACL 审计纳入变更管理流程任何 ACL 修改都要走审批。这里有个现实问题很多环境里某些备份软件、监控系统确实需要复制权限。这种情况下不能一刀切删掉而是要把这类账户纳入高价值目标管理——限制它的登录来源只能从指定主机登录、限制登录时段、启用更严格的监控。权限本身不可怕可怕的是权限落在一个谁都能用的账户上。5.2 凭据轮换策略要跟上即使权限被收紧了也不能假设之前的通道已经彻底断掉。攻击方可能已经通过 DCSync 拿到了哈希这时候唯一的补救手段就是轮换。轮换的优先级是krbtgt → 域管账户 → 具备复制权限的服务账户 → 其他特权账户。krbtgt 必须重置两次这是硬性要求。域管账户重置一次即可但如果怀疑哈希已经被用于 Pass-the-Hash还需要考虑清除相关会话。轮换的时机也有讲究。不建议在业务高峰期做因为 krbtgt 重置会导致所有 Kerberos 票据失效用户需要重新认证表现为短暂的登录异常。比较稳妥的窗口是业务低峰期并且提前通知相关方。5.3 蜜罐账户与诱饵权限这是一个成本低、效果好的补充手段。思路是创建一个看起来很有价值、但实际上无人使用的账户比如名字叫svc_sql_backup、admin_backup这类给它授予复制权限然后对这个账户的任何复制行为设告警。正常业务绝不会用这个账户发起复制所以任何一次触发都是高置信度的告警。这个手法的关键在于诱饵要做得像真的——账户要有正常的描述、要有登录历史可以用脚本模拟、要放在合理的位置。如果诱饵账户一看就是新建的空壳稍微有点经验的攻击方都不会碰。同样的思路可以扩展到组创建一个名字诱人的组加入一些无关紧要的成员然后监控对这个组的任何查询和修改。这类“主动防御”手段的价值不在于阻止而在于把发现时间从“事后数月”提前到“事中数分钟”。5.4 实操中容易踩的几个坑第一个坑是只监控 4662 不监控 5136。4662 记录的是“访问”5136 记录的是“修改”。如果攻击方还处在“加权限”的阶段只有 5136 会记录。等 4662 出现的时候权限已经加完了。两个事件必须一起看。第二个坑是审计策略开了但没配 SACL。目录服务访问审核依赖对象上的系统访问控制列表SACL。如果只在组策略里开了审核但域根对象上没有对应的 SACL 条目4662 依然不会产生。这个配置需要在 ADSI Edit 里手动加很多环境漏了这一步。第三个坑是误把备份流量当成 DCSync。某些备份产品会调用类似的接口读取目录数据特征是主体固定、源主机固定、时间规律。排查时先把这类流量加白名单否则告警会被淹没。第四个坑是ACL 清理不彻底。前面提过继承机制会导致子对象上有显式 ACE 残留。清理时必须同时检查域根和各个 OU确认没有遗漏。5.5 我个人的几点体会做了这么久的内网方向我越来越觉得 DCSync 这类技术的防御难点不在技术本身而在** visibility**。协议是微软公开的权限是标准 ACL 机制日志也是系统自带的所有材料都摆在那里问题只是有没有人去看。我见过配置得非常好的环境域根 ACL 每周自动比对任何新增条目都会触发工单4662 事件接入 SIEM 做实时关联蜜罐账户一触发就打电话。也见过配置得很差的环境域管账户密码三年没换ACL 从来没人看过出了事只能全量重置。两者的差距不在工具在有没有人真正把“权限基线”当回事。最后分享一个小技巧如果你手头没有 SIEM又想低成本地做监控可以用计划任务每天凌晨跑一次 ACL 导出把结果存成带日期的 CSV然后用一个简单的 diff 脚本比对前后两天的差异有变化就发邮件。这套东西加起来不到一百行代码但能覆盖住绝大部分 ACL 层面的维持手法。我在几个资源有限的环境里部署过实测下来很稳误报也少。至于更深的对抗比如针对msDS-KeyCredentialLink这类新型持久化手法的检测那是另一个话题了后面有机会再单独聊。