研究
AD FS Machine DPAPI:过期数据库记录之外的活动签名密钥
一场获得授权的红队评估从 WID 数据库解出了过期证书,却在 AD FS 主机的 Machine DPAPI 存储中找到了仍被服务使用的签名私钥。真正的调查不是“能否解密一个文件”,而是把配置、主机密钥托管、对外发布的 metadata 和下游信任重新对成同一张图。

文章导航
1 一张能解密、却不能再签发信任的证书
调查的第一个结果看起来几乎无可挑剔:Windows Internal Database 中的加密对象被成功取出,Active Directory 里的 Distributed Key Manager 材料也能把它还原,生成的 SAML 断言在结构上完整,签名算法和字段没有明显破损。真正的转折出现在信任链的最后一跳。Microsoft Entra ID 返回 AADSTS500172,拒绝了这张由旧材料签出的断言。
这个失败没有证明 AD FS 的活动私钥安全,也没有证明数据库提取流程无效。它只说明一件更具体的事:数据库返回的证书已经不在当前联邦信任中。Mandiant 随后确认,评估环境关闭了 AutoCertificateRollover,管理员曾手工轮换证书,而 WID 仍保留着已经过期的旧记录。数据库保存的是一个可以解开的历史事实,不是服务当下使用的全部运行状态。
如果在这里停止,报告会给出一个危险的假阴性:旧证书失效,于是活动签名密钥被当成不可获得。AD FS 服务却仍在正常为依赖方签发令牌,这意味着主机上必然存在某种可用的签名能力。调查因此从数据库记录转向操作系统密码学存储,问题也从“旧对象为什么失效”变成“当前服务到底从哪里取得签名能力”。
Mandiant 在该环境的 machine-scoped CAPI 存储中找到了与活动证书吻合的 RSA 私钥。它由 Machine DPAPI 保护,保护链依赖本机 DPAPI_SYSTEM 秘密和 SYSTEM 上下文的 machine master key;数据库里那条已经漂移的证书记录不在活动密钥的 Machine DPAPI 保护链中。恢复出的活动私钥在授权评估中签出了一份表示全局管理员身份的 SAML 断言,并被 Entra 接受。该结果验证的是获授权环境中的影响,并不表示未知攻击者已在其他环境执行了同样操作。
这四个动作组成了整篇研究最重要的因果线:WID/DKM 成功解密旧证书;下游拒绝旧签名;主机密码学存储保留活动私钥;活动私钥签出的断言被信任。任何一步单独拿出来都容易误导。把四步连在一起,才看见配置数据库、Windows 密钥容器、AD FS 运行时和 relying party 信任已经分成了不同步的事实面。
1.1 四个事实面回答四个不同问题
Get-AdfsCertificate 回答 AD FS 配置认为谁是 Primary、谁是 Secondary;本地 LocalMachine\My 与对应 provider 回答这台节点实际能否打开私钥;federation metadata 回答服务对外公布哪些公钥;依赖方自己的元数据缓存和信任配置回答它现在接受哪些签名。数据库只是这张表中的一列。
证书主题、有效期和指纹也不能彼此替代。名称可以重复,过期日期说明对象何时失效,指纹才把具体证书对象固定下来;私钥是否存在、是否可导出、由哪个 provider 承载,则是另一组属性。调查台账需要把这些字段放在同一行;一句“AD FS 证书正常”只会遮住真正的差异。
多节点 farm 会进一步放大漂移。主节点上的配置、每个节点的本地证书库、私钥 ACL、provider 和服务可用性都可能不同。只检查一台服务器,无法证明整个 farm 使用同一把签名钥匙;只查看 federation metadata,也无法证明每台节点都能安全地打开对应私钥。
依赖方又有自己的刷新节奏。有的自动消费 federation metadata,有的由管理员手工导入证书,有的允许一段时间同时信任新旧公钥。轮换是否完成,必须由真实依赖方用实际收到的签名指纹给出证据。AD FS 控制台里的 Primary 变化只证明配置推进了一步,尚不足以宣布结束。
四个事实面对账时,最小关联键不是证书显示名,而是指纹、用途、节点和采集时间的组合。若只用主题名称,重新签发但沿用同一名称的证书会被折叠;若只用指纹,又会丢掉它在某一刻究竟是 Primary、Secondary 还是已退役对象。调查表必须保留状态随时间改变的过程。
对账也要显式记录“未取得”。某个节点无法读取 provider 信息、某个遗留应用没有管理员确认、某段 AD FS 审计日志已经轮转,都是证据缺口,不应被空单元格伪装成一致。未知项会改变结论置信度,也会直接决定恢复时是否需要停机或强制重建。
正常变更可以解释差异,但解释必须落到可核验的动作:谁批准、在哪个维护窗口安装了哪张证书、哪一刻发布 metadata、哪些依赖方确认、何时提升和退役。只有一句“近期做过轮换”不能排除同一窗口内的异常读取,也不能证明旧公钥已从全部信任中删除。
反过来,四面不一致也不等于入侵。配置同步延迟、节点维护、依赖方缓存和人为遗漏都可能产生漂移。它们首先证明控制面无法回答当前状态;是否上升为密钥失陷,要看高权限会话、敏感对象访问、签发缺口与下游动作能否在同一时间线上相互支持。
因此第一轮调查不急着给事件贴名字,而是先产出一张差异表:预期指纹、实际指纹、差异开始时间、可能原因、支持证据、反证、负责人和下一步验证。表中每一行都能被另一名分析人员复查,才算从“看到一张过期证书”走到了可操作的问题。
1.2 公开证据给出了结果,也限定了不能外推的部分
Mandiant 的结论来自一次获得授权的红队评估。公开材料确认该环境关闭自动轮换、WID 返回过期证书、User DPAPI 离线恢复没有取得服务账户材料、Machine DPAPI 路径取得活动 CAPI 私钥,以及活动签名被 Entra 接受。它没有宣称所有 AD FS 都使用 CAPI,也没有宣称每个 User DPAPI 路径都会失败。
同样,SharpDPAPI 的公开源码只能说明格式、依赖和实现能力。源码中存在 CAPI、CNG、LSA secret、master key 与证书配对逻辑,并不能证明某个真实攻击者使用了这款工具。文章因此只用固定版本源码解释对象怎样连接,不把工具名字伪装成事件 IOC。
Event ID 385 在该环境里暴露了证书状态漂移,但它不是“私钥被窃”的事件。合法的手工轮换遗漏、配置同步失败和证书生命周期问题都可能触发同类告警。它适合打开一张有负责人和期限的完整性工单,再与敏感文件访问、异常进程、令牌签发和云登录一起判断。
最稳妥的公开结论因此很窄也很有力:当 AD FS 的配置与主机运行状态分离时,数据库提取可能只返回旧证书;如果攻击者已取得联邦服务器的高权限,而活动私钥以可导出的软件形式保存在 machine scope,那么服务账户改密和数据库检查都不足以排除签名密钥失陷。
公开证据可以按四级表达。Mandiant 明确写出的环境事实属于“已观察”;Microsoft 文档说明的产品行为属于“厂商定义”;由两者推导出的防守影响属于“分析判断”;公开材料没有给出的入侵者身份、具体受害范围和每一步时间则保持“未知”。四类句子不能共享同一个确定语气。
这种分层尤其适用于影响描述。公开研究证明授权评估中的活动私钥能够签出被 Entra 接受的高权断言,这是已验证能力;它没有证明真实攻击者已经在生产租户做过同样的事。文章可以解释最坏后果,却必须把能力验证与既成受害事实分开。
失败步骤也要原样保留。User DPAPI 路径在该环境没有产生目标材料,不代表研究者“什么也没发现”;它缩小了假设空间,并提醒防守方不要把域备份密钥当作所有服务密钥的万能入口。负结果只在采集范围、版本与上下文写清时才有复用价值。
固定源码复核只负责验证对象关系,不能替公开案例补齐剧情。它能回答实现是否处理 machine master key、CAPI 容器和证书配对,无法回答现场究竟执行了哪些命令、从哪里登录、持续多久。源文没有提供的步骤保持未知,叙事顺滑不能成为补写事件经过的理由。
2 手工轮换把一套密钥生命周期拆成了两条时间线
AD FS 的自动证书轮换本来试图让生成、发布、提升和退役成为一套连续流程。新证书先作为 Secondary 出现,提前进入 federation metadata,依赖方获得刷新窗口;到达提升阈值后,新证书成为 Primary,旧证书继续保留一段重叠期。时间窗口不是装饰,它让分布式信任有机会无中断地改变。
关闭 AutoCertificateRollover 后,组织接管了这套状态机。管理员需要生成或导入新证书、确保每个 farm 节点能访问私钥、把证书登记到 AD FS、公布新公钥、确认依赖方消费,再提升为 Primary。任何一步被“证书已经装进 Windows”替代,都会留下配置与运行时不一致。
本案的“幽灵”正来自这种分裂。WID 里仍然能看见并解密旧对象,它像一张保存完好的旧门票;服务已经从操作系统密钥存储中使用另一把钥匙继续营业。历史提取技术忠实地还原了数据库,却没有回答运行时选中的私钥。失败不是密码学错误,而是调查对象选错了时间面。
这种漂移还会改变检测习惯。团队如果只监控 DKM 或数据库访问,可能完全看不见攻击者读取当前 machine key;如果只监控 lsass.exe 内存访问,也可能错过离线取得注册表 hive、LSA secret 和 master-key 文件的组合。合法服务访问与异常恢复都发生在操作系统存储层,需要以对象、进程、登录上下文和后续签发共同定性。
2.1 WID 与 DKM 仍然重要,但只能作为带时间边界的证据
数据库路径能够保存 farm 配置、证书记录及相关加密对象,DKM 则提供解密所需的域内材料。它们对历史调查仍然关键:可以恢复旧证书、确认轮换顺序、比较配置变化,也能解释为什么某份签名在某个时期被接受。把这条路径判定为“没用”同样会丢失证据。
正确做法是给每个恢复对象加上时间和角色。记录数据库备份时间、证书指纹、NotBefore、NotAfter、Primary/Secondary 标记、AD FS 配置变更时间和依赖方信任窗口。随后与节点证书库、metadata 和登录结果比较。只有能对上同一时间窗口的对象,才能用于说明当时的签发能力。
AADSTS500172 是本案中极有价值的反证。它把“格式正确的断言”与“受信任的签名材料”分开,迫使调查回到实际公钥信任。错误码不能单独定位根因,却能证明旧对象没有完成最后的验证。仅保存一句错误截图会丢掉关联线索,因此请求时间、租户、应用和 correlation 字段都应完整保留。
历史数据库还可以帮助识别不受控轮换。若 WID 的证书记录、操作日志、变更单和 relying party 刷新记录彼此错开,组织就没有一条可证明的证书生命周期。Event 385 消失并不自动补齐这段历史;需要台账明确谁在何时以哪种方法修正了哪一面事实。
把轮换当成一笔分布式事务,会更容易看见风险。生成新钥只是开始;节点可用、Secondary 登记、metadata 发布、依赖方消费、Primary 提升和旧信任删除分别是提交点。任一阶段失败,都需要知道系统停在何处、谁可以回退、回退是否重新暴露旧钥。
例如新证书已经安装但尚未发布,回退通常只涉及本地对象;新公钥已经被部分依赖方消费后再回退,就会形成双向不一致;提升为 Primary 后才发现某个关键应用未刷新,则需要在业务中断与继续信任旧钥之间做显式选择。运行手册应提前定义这些分支,避免事故中临时猜测。
轮换时间轴还要纳入时钟。AD FS、域控制器、代理、Entra 和第三方应用的时间偏差会改变 NotBefore、NotOnOrAfter 与日志关联结果。每次变更前记录时间同步状态,调查中统一换算 UTC,并保存原始时区。否则几分钟偏差就可能把正常提升误写成异常签发。
数据库历史最终承担的是解释责任:为什么某个旧对象仍存在、何时不再被服务使用、何时不再被任何依赖方接受。只有后两项都有外部证据,旧记录才是可理解的档案;否则它既可能只是残留,也可能说明轮换从未真正收尾。
2.2 活动证书要从服务实际使用的链路反向确认
确认活动证书从 Get-AdfsCertificate 开始,但不能在那里结束。每个 farm 节点都要在 LocalMachine\My 找到同一指纹,确认 private-key association、provider、KeySpec、ACL 和服务读取能力。若使用 HSM,还要记录 provider、槽位、策略和高可用设计;软件私钥文件不再是这类部署的预期证据。
接着读取 federation metadata,确认对外发布的签名证书集合与预期一致。metadata 是发布面,不等于每个 relying party 已经消费。对关键 Microsoft 与第三方应用执行受控登录,从 AD FS 签发记录、SAML 响应签名和下游登录日志确认实际使用的指纹,才完成端到端验证。
这一反向路线还能发现节点漂移。负载均衡把请求分到不同节点时,如果其中一台缺少新私钥或仍使用旧配置,故障可能呈间歇性。测试要覆盖每个节点或通过可控方式固定后端,并记录签名指纹。单次成功登录只能证明那条请求路径成功。
最后再回到数据库:WID 中当前对象是否一致,历史对象是否有清晰退役状态,手工轮换脚本是否调用受支持的 AD FS 管理接口,变更单是否包含 relying party 确认。这样数据库从“唯一真相”变成证据闭环的一部分,幽灵记录也就不会再遮住活动钥匙。
端到端核验应建立固定测试矩阵:每个 farm 节点至少一次、每种关键协议路径至少一次、每个高影响依赖方至少一次。测试账号只拥有必要权限,断言与下游日志保留 correlation 和签名指纹,不在工单中保存可复用令牌。矩阵缺一格,就不能把单点成功推广到整座 farm。
负载均衡会掩盖节点差异。若没有后端标识,连续十次成功仍可能全部落在同一台健康节点。维护窗口中可使用受控的节点定向方法,或让代理日志提供后端映射,再将 AD FS activity 与节点事件连接。测试结束后恢复正常路由并复核健康探测。
依赖方确认不应只是一封“已完成”邮件。理想证据包括它当前保存的公钥指纹、最近一次 metadata 拉取、接受新签名的测试记录和拒绝旧签名的结果。无法提供技术证据的应用,至少需要业务负责人签署残余风险与会话处理方案。
轮换验收还要覆盖失败路径:Secondary 不可读时是否阻止提升,metadata 发布失败是否告警,某节点缺失私钥时健康检查是否摘除,依赖方拒绝新证书时是否能定位。只验证理想路径,会让真正的漂移在下一次变更中原样出现。
每次轮换前先冻结一份“预期状态契约”:新旧指纹、各自角色、所有节点、发布时间、提升条件、消费者批次、最长重叠与最迟回退点。自动化每完成一步便将实际状态与契约比较,出现未计划的节点、证书或消费者时立即停止。契约把口头计划变成机器和人工都能核对的变更基线。
3 Machine DPAPI 保护的是机器连续性,也继承机器失陷
Machine DPAPI 的设计目标首先是可用性。服务账户密码变化、gMSA 自动轮换、系统重启或服务重启都不应让 AD FS 失去签名能力。把私钥保护绑定到计算机,使本机授权服务可以持续打开同一密码学对象,而不依赖某个交互式用户会话或一份长期不变的服务密码。
这也解释了为什么“刚给服务账户改过密码”不能作为签名密钥安全的证据。服务身份凭据和 machine-scoped private key 有独立生命周期。前者变化不会自动生成新的 RSA 密钥、替换证书、更新 metadata、撤销下游信任或让旧 SAML 会话失效。
Microsoft 对 CRYPTPROTECT_LOCAL_MACHINE 的说明强调了计算机范围:受保护数据绑定机器,并不专属于调用用户。实际读取仍由文件 ACL、LSA secret、master key、进程令牌和操作系统自身的防护约束。这个标志从未允许任意远程用户解密;一旦攻击者取得足够的本机高权限,这些防护才会随主机一起失效。
因此 AD FS 服务器必须按 Tier 0 身份基础设施处理,其角色远超普通 Web 服务器。即使没有保存用户密码,它也保存着能代表所有联邦用户签发身份的能力。SYSTEM 失陷后应先按活动签名密钥可能受损处置,无需等到一份明显的私钥导出文件出现。
3.1 离线恢复链依赖多类本机材料,单个证书文件远远不够
固定版本 SharpDPAPI 源码展示了依赖关系:SYSTEM 与 SECURITY hive 提供 boot key 和 LSA secret 线索,DPAPI_SYSTEM 再为 SYSTEM 的 machine/user 部分提供 pre-key;S-1-5-18 保护目录里的 master-key 文件通过相应材料解开;密码学容器中的 DPAPI blob 最终才能还原 RSA 私钥。
boot key 本身由注册表多个 class value 按固定顺序重组。随后才有条件处理 SECURITY policy 中的 LSA 密钥和 DPAPI_SYSTEM secret。这个序列说明,备份一个 MachineKeys 文件并不等于拥有可用私钥;调查也不应把看到容器文件当成确认导出成功。
master-key 文件以 GUID 标识,DPAPI blob 引用对应 GUID,并携带盐、轮次、哈希算法、加密算法、HMAC 和密文等格式字段。实现会根据版本和算法进入不同分支。源码中的“不支持”或校验失败应保留为硬性失败信号,不能用猜测补成成功恢复。
完整取证需要记录每层对象的来源、采集时间、哈希、主机和权限上下文,却不应把 secret 值复制进普通工单。证据包保留受控原件,分析表只使用 GUID、证书指纹、文件哈希和是否成功验证等非秘密标识。这样既能复核链路,又不会把恢复过程变成新的泄露。
在线与离线证据也要分开。合法 AD FS 服务通过 Windows 密码学接口打开私钥,是正常业务;离线组合 hive、LSA secret、master key 与 key container,呈现不同的文件访问、备份、进程和工具轨迹。检测不需要识别某个工具名称,只需识别不符合基线的对象组合和上下文。
证据采集首先要维持来源关系。SYSTEM、SECURITY、Protect 目录与密钥容器若来自不同快照或不同节点,即使分别可读,也不能被默认拼成同一条恢复链。采集清单记录主机、卷、快照时间、文件系统时间和哈希,让分析人员知道哪些对象在同一个状态点。
备份系统是容易被忽视的第二条路径。拥有系统状态备份读取权的人,可能在不登录在线 AD FS 的情况下取得构成离线分析所需的多类材料。备份仓库、恢复控制台、快照服务账户和导出介质因此应纳入 Tier 0 范围,并保留与生产主机同等级别的访问审计。
恢复实验应在隔离环境使用只读副本,秘密输出只进入受控存储。分析人员不需要把 DPAPI_SYSTEM、master key 或明文私钥粘贴进聊天、终端历史和普通工单;多数验证可以用哈希、GUID、公钥参数和一次受控签名结果完成。每减少一份明文副本,就减少一次二次泄露。
完整性校验必须贯穿每层。DPAPI 结构通过校验不等于对象属于目标证书;公私钥匹配不等于它在目标时间是 Primary;受控签名成功不等于生产依赖方仍信任。每个“成功”只解锁下一层判断,不允许跳过中间的归属与时间验证。
主机仍在线时还要防止分析动作改变现场。直接导入证书、修改 ACL、启动 profile 或运行会触发密钥使用的测试,都可能更新时间戳和日志。优先在副本中恢复;确需在线验证时,先列出预期副作用、批准窗口和回滚,并把研究动作从潜在攻击活动中标记出来。
3.2 User DPAPI 的失败是环境观察,不是架构定律
Mandiant 先评估了 user-scoped 路径。域 DPAPI backup key 可以解开交互式用户 profile 的部分 master key,却没有取得该环境 AD FS 服务账户可用的材料;其他离线尝试也未成功。这段失败很重要,因为它解释调查为何转向 Machine RSA,但它不能被扩写成“AD FS 服务账户永远无法通过 User DPAPI 恢复”。
Windows 版本、服务账户类型、profile 是否加载、provider、证书部署方法、master-key 历史和备份材料都会改变结果。每个环境先盘点事实,再选择恢复假设。把一个红队现场的 provider 和 profile 状态外推到所有 farm,会制造错误的检测盲点。
CNG 也需要按同样方式核对。公开研究报告了该环境中的活动 CAPI 路径,但未报告活动 CNG 密钥;SharpDPAPI 则包含对多类目录和格式的枚举。资产盘点必须记录实际 provider,不能把“报告未提供”写成产品不支持。HSM 更应单独建模,因为不可导出密钥不等于普通文件容器。
防守团队真正需要复用的不是一条固定命令,而是一张依赖图:哪个身份保护哪类 master key,哪个 provider 保存哪把证书私钥,哪个服务在何时打开它,哪些依赖方信任对应公钥。工具和路径可以变化,这张所有权关系仍然成立。
建立依赖图时,证书对象应作为起点,目录假设放到 provider 识别之后。证书的 provider 与 key container 指向实际私钥实现;实现再决定需要关注 CAPI 文件、CNG key store 或 HSM 调用。这样即使环境版本、安装方式和服务账户变化,调查也不会被一条固定路径牵着走。
第二步是把“能读取”与“能签名”分开。有些身份可能有文件备份权限却不能在在线主机调用 provider;有些服务可以请求 HSM 签名,却永远看不到私钥字节。权限评审必须按能力建模,避免因为看不到导出权限就忽略被滥用的签名调用。
第三步是记录恢复依赖的替代来源。注册表 hive 可能来自系统状态备份,master key 可能存在历史快照,容器可能被复制到取证镜像。控制面需要监控这些汇合点;单守生产目录无法覆盖材料在其他位置重新组合的风险。
第四步是把版本差异放进测试而非脚注。升级 Windows、变更 provider、迁移 gMSA 或 HSM 后,重新验证对象位置、审计字段、服务权限和灾备恢复。旧检测仍有数据不代表它还覆盖新的密钥路径。
最后,任何工具特征都只能作为辅助。命令行、文件名和开源工具标识容易改变,合法红队与攻击者也可能使用不同实现。稳定检测对象是高权限登录如何接触一组敏感材料,以及随后身份系统是否出现无法由正常签发解释的结果。
采集顺序应先保护会变化的证据。当前进程、登录会话、打开句柄、网络连接、provider 状态和日志队列比磁盘上的历史容器更容易消失;在不破坏现场的前提下先记录它们,再取得一致性快照和离线材料。每一步都写明可能造成的时间戳、缓存或审计副作用。
4 找到 RSA 字节以后,还要证明它就是当前签名者
密码学容器目录里可能有很多服务和历史遗留对象。文件名、创建时间和相邻证书都只能产生候选。将一个成功解密的 RSA 结构直接称为“AD FS 活动私钥”,会跳过最重要的归属验证:它是否与活动证书公钥吻合,是否被当前 AD FS Primary 状态引用,是否正在被依赖方接受。
开源实现从私钥结构恢复 modulus 等公钥参数,再遍历证书库,用公开参数进行匹配。公私钥数学吻合后,才能得到证书 subject、有效期和 thumbprint。这个匹配证明“私钥属于该证书”,还没有证明“该证书正在签发当前联邦令牌”。
第二层验证来自 AD FS 配置与运行行为。将指纹与 Get-AdfsCertificate 的 Primary 项、每个节点证书库、federation metadata 和受控登录的实际签名对齐。四面一致时,活动身份才成立。任何不一致都应作为配置漂移继续调查。
第三层验证来自时间。证书可能在调查前后刚完成提升或退役,metadata 与依赖方也可能处于重叠期。证据必须带 UTC 时间和节点,说明该私钥在什么窗口具有什么角色。没有时间的“当前”很快就会在轮换中失真。
4.1 CAPI、CNG 与 HSM 是三种不同的证据对象
CAPI 软件密钥常见于 ProgramData\Microsoft\Crypto\RSA\MachineKeys 等位置,证书对象通过 provider 信息连接到容器。CNG 使用不同的 key storage provider 与目录。两者的文件格式、API、ACL 和审计路径并不相同,调查表应明确区分。
HSM-backed key 的关键属性是私钥材料不以可导出的软件字节存在于主机。AD FS 仍能请求签名,但调用经过 HSM provider 和设备策略。这样可以切断本文描述的 Machine DPAPI 软件导出链,不过主机上的授权签名调用、claims rule 修改、会话窃取和管理面滥用仍需控制。
迁移 HSM 不是把证书“导入一个更安全的位置”这么简单。需要验证设备高可用、provider 支持、AD FS 服务权限、备份与恢复、密钥生成与不可导出策略、审计、灾备 farm 以及所有依赖方的轮换窗口。没有演练的 HSM 会把安全问题变成可用性问题。
对于现有软件密钥,记录 Exportable 属性和实际 provider,检查私钥 ACL 是否只有预期服务与管理员可用。不要为了调查而把生产私钥重新导出;归属可通过受控签名、证书关联和 provider 元数据验证。若已怀疑主机失陷,应优先轮换并保存必要证据。
公私钥匹配最好使用不改变生产状态的方法。证书公钥的 modulus 与 exponent 可以和恢复候选比较,或让 provider 对无害挑战执行一次受控签名并在外部验证。两种方法都只证明密钥对关系;活动角色仍要由 AD FS 配置、时间与下游接受共同确认。
KeySpec、provider 名称和容器关联错误会制造很像“密钥损坏”的故障。证书能在存储中显示,并不表示 AD FS 服务令牌拥有打开对应私钥的权限。部署验证要以服务上下文完成一次真实签发;管理员账户在证书管理器里看到的钥匙图标只能证明另一种上下文。
ACL 评审要同时看直接授权、组嵌套和继承。一个表面上只允许 SYSTEM 与管理员的容器,可能通过备份操作员、服务控制或远程管理路径被间接取得。高权限能力图应覆盖谁能更改 ACL、替换服务二进制、创建计划任务和读取系统状态备份。
HSM 环境的证据重心会从文件转向调用:哪个节点、哪个服务身份、何时、以何种策略请求了多少次签名,是否经过双人批准或速率限制。设备不可导出并不会让审计变得不重要;相反,异常调用记录成为判断签名能力是否被滥用的核心。
可用性也属于安全验收。HSM 集群失联时,AD FS 应以可预期方式失败,不能自动退回一把无人管理的软件密钥;灾备切换必须继续使用受控密钥或明确中止签发。每次演练都验证 failover 后的实际指纹,防止备用路径悄悄恢复旧风险。
4.2 一张可复核的活动密钥台账需要九类字段
第一组是 farm 与节点:farm 标识、行为级别、数据库类型、主节点、所有成员和负载均衡路径。第二组是 AD FS 状态:证书用途、Primary/Secondary、thumbprint、NotBefore、NotAfter、自动轮换和阈值。第三组是本地密码学状态:store、provider、container/key name、KeySpec、ACL、可导出策略与 HSM 标识。
第四组是发布:metadata 中出现的证书和获取时间。第五组是消费:每个关键 relying party 的刷新方式、当前受信任指纹、负责人和最后确认。第六组是运行验证:受控登录时间、节点、签名指纹、AD FS correlation 与下游 correlation。
第七组是历史:安装、登记、提升、退役和删除的变更单、执行者与批准人。第八组是异常证据:Event 385、对象访问、可疑登录、进程和网络。第九组是处置:新密钥生成位置、重叠期、旧公钥撤销、会话处理、主机重建状态和最终验收人。
这张台账不保存私钥或 secret。它保存能证明对象身份与状态的公开指纹、受控标识和事件引用。若团队无法填满九类字段,就无法声称轮换已经在配置、主机、发布、消费和会话五个层面同时完成。
台账应以一行状态变更为最小单位。持续覆盖同一个“当前值”会抹掉过程证据。Secondary 生成、metadata 首次出现、每个依赖方确认、Primary 提升、旧公钥最后一次被接受和私钥退役都留下独立时间,事故窗口和长期停滞步骤才能被重建。
自动采集负责客观字段,人工签署负责业务含义。脚本可以读取 AD FS 状态、节点证书库与 metadata,却无法替代应用所有者确认刷新、会话撤销和业务测试。系统需要同时保留机器证据与责任人,不把其中一方伪装成全部事实。
对账任务应定期从 farm、metadata 和关键依赖方独立取数,再比较上一次快照。若采集脚本只读取同一配置源,它会稳定地重复同一个错误。至少一项验证必须来自信任链的另一端,例如实际 SAML 响应指纹或依赖方保存的公钥。
临近过期只是最容易测量的风险。更重要的指标是 Secondary 发布后多久被消费、Primary 提升后旧公钥还被多少应用接受、节点之间的 provider 是否一致、最近一次旧签名拒绝测试何时完成。它们直接描述轮换闭环,单看证书日历无法得到这些答案。
当台账发现差异时,工单状态不能只写“已修复”。关闭条件包括差异原因、受影响窗口、是否需要事件调查、技术验证、依赖方确认和防复发动作。下一次审计抽取任一指纹,都能沿记录走完从生成到退役的旅程,才说明控制真正可持续。
5 活动签名钥匙把主机权限扩展成下游身份
SAML relying party 接受 AD FS 断言时,验证的是签名、issuer、audience、时间和自身策略。持有活动私钥的人可以构造密码学上有效的断言;若 claims、受众和其他字段也满足规则,依赖方会把它当成来自可信身份提供者的结果。MFA 与条件访问如果位于上游认证流程,就可能不再看到真实用户完成过什么步骤。
这就是 Golden SAML 的危险:攻击者不是猜用户密码,而是冒充签发者。Mandiant 在授权环境用恢复出的私钥签发全局管理员身份,Entra 接受了相应断言。这个结果证明的是该评估中的完整影响链,不意味着每个依赖方、每项 claim 和每种策略都会自动接受任意断言。
影响范围由 relying party trust 决定,不只包含 Microsoft 365。任何信任该 AD FS issuer 和公钥的 SaaS、内部应用、VPN 或管理平台都应进入清点。每个依赖方的会话期限、刷新、撤销能力和日志字段不同,处置不能用一条 Entra 会话撤销命令覆盖全局。
签名密钥轮换阻止旧私钥继续制造被信任的新断言,却不会自动终止已经交换出的应用会话。某些依赖方在接收 SAML 后建立自己的 cookie、refresh token 或 API token。事件响应因此要同时处理“还能不能签新票”和“已经换出的票还活多久”。
5.1 真正的异常藏在签发端与消费端之间
单看 Entra sign-in,一份伪造但签名有效的断言可能像普通 federated sign-in。下游看见可信 issuer 和有效签名,却不知道 AD FS 是否真的执行过对应认证。检测重点是把下游登录反向关联到 AD FS 的认证、claim 处理和 token issuance。
关联字段因版本和配置而异,应优先保留 UTC 时间、UPN/subject、relying party 或 audience、源地址、设备和 user-agent、authentication context、claim set、证书指纹、AD FS activity/correlation 标识以及下游 request/correlation。没有稳定 ID 时,以窄时间窗口和多个字段组合,保留误差。
最有价值的缺口是“下游接受了高风险联邦登录,但签发端找不到合理前序”。这不自动证明 Golden SAML,日志丢失、farm 节点未采集、时间漂移和代理解析也会制造缺口。调查先验证遥测完整性,再将无法解释的登录提升为高优先级事件。
一条正常联邦登录至少包含三个可区分阶段:用户在 AD FS 或上游完成认证,AD FS 为特定 audience 生成并签名断言,依赖方验证后建立自己的会话。每一段都有独立时钟、标识和日志保留策略。关联规则要先证明这三段在正常业务中能够稳定接上,才有资格解释缺失。
同一个 UPN 与相近时间远远不够。共享出口、批量任务和用户快速切换应用都会产生碰撞。更可靠的组合包括 AD FS activity、relying party identifier、authentication context、签名指纹、源网络、设备线索和下游 correlation;字段越少,结果越应标成候选而非定论。
claim 的变化也能暴露信任路径异常。角色、组、认证方法、ImmutableID 或其他关键 claim 若偏离该账户与该应用的长期形状,即便登录来源常见,也值得复核。检测保存规范化后的关键 claim 与规则版本,不必收集与目的无关的全部个人属性。
重放、时钟偏差和代理改写会制造另一类假象。依赖方可能拒绝一份真实签发但已过期的断言,也可能因日志时间采用接收时刻而与 AD FS 相差数分钟。调查先校准时间、确认唯一断言标识与应用重试逻辑,避免把传输故障当作伪造。
所谓“没有签发前序”必须附带覆盖证明:相关节点在该窗口在线、审计已启用、日志成功集中、队列没有积压、时间同步在容差内、检索范围包含正确 relying party。任一条件不成立,结论只能是遥测不足,不能直接升级为 Golden SAML。
一旦覆盖完整且缺口成立,分析要继续追踪下游会话生命周期。SAML 断言可能只出现一次,随后活动表现为 cookie、refresh token 或应用自身令牌。把最初的异常登录与后续管理动作连接起来,才能判断伪造身份是否只是尝试、已换得会话,还是已经改变了控制面。
5.2 影响评估按依赖方、会话和动作逐项落地
先列出所有 relying party:issuer/audience、业务负责人、信任指纹、metadata 更新方式、session 与 refresh 生命周期、撤销接口、日志位置和高权角色。退出使用的旧应用也要核实信任是否真正删除;停用流量不等于撤销签名公钥。
随后在可能暴露窗口内搜索高风险登录与动作。账号创建、角色提升、MFA 或条件访问修改、OAuth 应用授权、邮箱规则、下载、数据导出、密钥生成和审计变更优先。活动私钥理论上能代表普通用户,实际影响仍由观察到的登录与动作证据分级。
对于没有完整日志的依赖方,结论应记录为未知;“未受影响”在此时缺少证据。根据会话最长期限、私钥可能暴露时间和业务敏感度决定强制登出、重置、密钥轮换或临时隔离。每个决策写明证据、残余风险和负责人。
最终报告把“密钥可用于伪造”与“已观察到某个账户被伪造”分开。前者在主机失陷和软件私钥可恢复时可作为高置信风险;后者必须有签发缺口、登录、操作或其他独立证据支持。这种分层既避免漏报,也避免把能力当成事件事实。
影响窗口的起点不是证书签发日期,而是活动私钥最早可能被未授权主体接触的时间。它可以来自首个异常特权登录、敏感对象读取、备份导出或主机完整性失去保证;若无法确定,则要回溯到最后一次可信检查。终点是旧公钥被所有依赖方拒绝且旧会话完成处置。
依赖方按可达权限和撤销能力分层。身份管理、邮件、云控制台与代码仓库优先于低权限门户;能够即时强制登出的应用优先执行,无法撤销的遗留应用可能需要临时断开信任或缩短网络可达。顺序由减少现实权限的速度决定,不由应用清单字母顺序决定。
对于发现的高风险动作,必须保存动作对象、执行身份、会话标识、来源、前后状态和回滚结果。仅列“管理员登录成功”无法判断后果;同一会话若新增应用凭据、授予持久角色或修改审计策略,处置就要扩展到新建的秘密与控制。
长尾应用往往是恢复中最后的未知。它们可能多年没有流量,却仍保存旧 issuer 和公钥,一旦重新启用便接受失陷材料。清点应结合 AD FS relying party 配置、网络流量、应用资产和业务访谈,并对无法找到所有者的 trust 设定隔离与删除期限。
仅仅“没有再看到异常”不足以完成影响评估。每个高影响依赖方都要有明确结论:未受影响且证据充分、已处置、或未知且已有风险决定。结论与证据窗口绑定;日志范围后来扩展或出现新会话时,事件必须重新打开,一次性报告不能把它封死。
会话地图要记录信任如何变形。SAML 断言进入应用后,可能生成浏览器会话、刷新令牌、个人访问令牌或后台作业凭据;其中一些继续派生新的短期令牌。响应人员沿每种转换记录签发者、最长寿命、撤销入口和验证方法,避免在最初断言失效后遗漏仍能自主续期的后继凭据。
6 检测要把文件读取、进程上下文与身份结果连起来
MachineKeys 与 S-1-5-18 Protect 目录可以配置 SACL,让符合条件的对象访问生成 Security Event ID 4663。高权限服务、证书管理、备份、EDR 和系统维护都可能合法读取相关对象,因此事件本身不是告警结论。它提供的是“谁以什么访问掩码碰了哪个对象”的一块拼图。
保留 SubjectUserSid、SubjectLogonId、ObjectName、AccessMask、ProcessId、ProcessName、计算机和 UTC 时间,再用 LogonId 连接 4624、4672、服务安装、计划任务、远程管理、EDR 进程树和网络会话。合法 AD FS 服务的稳定访问与一个临时管理进程批量读取 hive、master key 和容器文件,行为形状不同。
注册表 hive 和 LSA secret 相关访问同样重要。攻击者不一定直接读取在线 LSASS 内存;卷影副本、备份、离线 hive 和高权限文件复制可能形成低噪声路径。监控应覆盖敏感对象被谁组合读取、随后是否打包、传输或在不同主机上处理。
身份侧同时采集 AD FS 管理与审计日志、certificate lifecycle 事件、token issuance/claims 事件、federation metadata 变化和所有下游登录。主机完整性失去保证后,即使尚未发现伪造登录,主机读取证据仍足以触发密钥轮换评估;下游异常登录如果没有主机读取证据,也不能因为“没看到导出工具”而关闭事件。
6.1 Event 385 是漂移哨兵,4663 是对象访问,不是 IOC 清单
Event 385 在公开案例里揭示 WID 与活动证书状态不一致。它应该带出配置复核:自动轮换是否关闭、当前 Primary/Secondary 指纹、证书库和 metadata 是否一致、最近变更是否完整、依赖方是否刷新。只有把这些问题回答完,事件才完成闭环。
4663 的价值取决于 SACL。没有预先配置的对象审计,事件不会凭空出现;配置过宽又可能制造大量正常噪声。上线前在测试 farm 验证哪些访问被记录、合法服务频率如何、路径和进程字段是否可用,并确保安全日志容量和集中采集足够。
路径不是恶意指标。C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\ 与 C:\Windows\System32\Microsoft\Protect\S-1-5-18\ 是合法系统位置,直接按字符串告警会惩罚正常运行。规则应组合非预期进程、特权登录、批量或离线读取、后续归档和身份异常。
错误码也不构成独立 IOC。AADSTS500172 可以来自配置错误和过期签名材料。它在本案中帮助修正假设,是因为前面已经有 WID 恢复对象和受控断言。生产告警应关联 issuer、应用、证书时间和轮换状态;所有同码失败直接归为攻击会制造大量误报。
SACL 部署应先在非生产或单节点观察模式中测量。分别记录正常签发、证书轮换、备份、EDR 扫描、补丁和故障转移会触发哪些对象访问,再决定目录级还是文件级审计。否则过宽规则会淹没安全日志,过窄规则又在容器名称变化后失效。
基线不能只按进程名建立。合法二进制可能被高权限会话借用,同名路径也可能被替换。规则同时比较签名与哈希、父进程、服务身份、LogonId、维护窗口、读取对象组合和网络后续;越接近多种敏感材料在短时间汇合,优先级越高。
集中日志要保留原始事件和规范化字段。规范化便于关联,原始 XML 则用于复核 AccessMask、对象名称与事件版本。转发器丢包、节点离线和解析失败本身要产生健康告警,否则“没有 4663”可能只是管道没有工作。
检测测试使用受控、无害的管理动作,不需要真的导出生产私钥。可以在测试节点触发预期的证书读取、备份副本访问和 metadata 变更,确认事件从主机到 SIEM 的字段与时延,再验证关联规则只在异常上下文升级。测试结果作为规则版本的验收证据。
6.2 一条可执行的调查从稳定种子逐层扩展
以活动 Primary thumbprint 为种子,列出每个节点的 store/provider/container 和最后访问,随后连接 AD FS 签发事件与下游登录。以 Event 385 时间为另一种子,查看前后证书管理、服务重启、metadata 改变和依赖方刷新。两条时间线如果相交,就能解释漂移形成与修正。
以敏感对象访问为种子时,先扩展登录会话和进程祖先,再看文件、注册表、卷影、归档和网络。任何未知 SYSTEM 会话、远程工具、脚本宿主或短时服务都进入人工复核。合法变更应能回到工单、批准人、维护窗口和预期输出。
以下游高权登录为种子时,反查 AD FS 是否存在对应认证与签发,比较 claim、audience、指纹、源和 user-agent。找不到前序先检查日志覆盖和时间同步;确认覆盖完整后,缺口本身成为强信号。随后搜索同一源、会话和 claim 组合的其他账户。
三类查询最终汇入同一调查对象:哪把私钥、在哪个节点、在什么时间被谁访问,签出了哪些断言,被哪些依赖方接受,产生了哪些会话和高风险动作。只有结果能回答这句话,检测工程才从告警变成取证能力。
实践中可以把调查对象画成一张小型关系图:证书指纹连接 provider 与容器,容器访问连接进程和 LogonId,LogonId 连接主机与远程来源,签发连接 audience 与 subject,下游登录再连接会话和动作。图中断开的边就是下一轮查询,分析员不得用未经验证的假设补齐。
查询输出要包含可验证的原始引用。每个结论旁保存事件记录 ID、日志源、UTC 时间、主机、检索条件和导出哈希;仪表板截图只能作为说明,不能替代可重放数据。第二名分析人员使用同一输入应能得到相同候选集合。
置信度随独立证据增加。单个 385 或 4663 是弱线索;异常特权会话加敏感对象组合读取属于中等;再出现活动指纹匹配、无法解释的签发缺口或下游高权动作,才构成强关联。不同来源的证据比同一日志中多个相似事件更有分量。
保留期会限制最早可见时间。若 AD FS 详细审计只保留七天、应用会话却能持续数周,调查就不可能完整反查。日志策略应由私钥风险与最长会话共同决定,并把集中存储、访问控制和成本纳入设计;事件发生后才发现前序消失,已经没有补救采集的机会。
7 轮换的终点是旧私钥再也换不到新会话
- 发现可疑 SYSTEM 活动或无法解释的签发缺口后,先保存证据并建立事件指挥。记录当前 Primary/Secondary、每节点 provider 与容器、metadata、relying party 清单、活动会话和关键日志覆盖。若攻击仍在进行,隔离管理路径和出网,限制 AD FS 主机,只允许经批准的恢复身份操作。
- 新 token-signing key 应在可信环境生成,优先使用 HSM-backed、不可导出的设计。按受支持流程作为 Secondary 加入 AD FS,确保所有节点可用,再发布新公钥。依赖方确认消费前,不要贸然提升;处于紧急失陷时,应在短暂中断、隔离或明确接受残余风险之间作出记录在案的决定,不能为了无缝切换默认继续信任可能暴露的旧密钥。
- 提升新证书为 Primary 后,通过每个 farm 路径执行受控登录,保存实际签名指纹和下游 correlation。对关键第三方 relying party 取得书面或日志证据,确认新签名被接受。经过明确的重叠策略后,从所有信任中移除旧公钥,并退役对应私钥容器。
- 在治理允许的前提下,以受控测试材料执行隔离、无害的验证,确认生产依赖方拒绝旧签名,能把“配置看起来已更新”变成端到端证据。不得为此新增真实生产私钥副本;结果只记录指纹、时间、目标和拒绝结果。
7.1 签名能力、现有会话与下游持久化按不同时间收口
第一层是签名能力:生成新钥、发布、提升、撤销旧信任。第二层是已经建立的联邦会话:Entra 与每个 relying party 分别强制失效或等待最短可接受期限。第三层是攻击者可能利用高权会话修改的下游对象:应用注册、OAuth 授权、管理员、邮箱规则、API key、证书和数据。
如果只完成第一层,旧私钥不能再造新票,但已换出的会话仍可操作;如果只强制登出而不换签名钥匙,攻击者可以立即再签。两层必须在同一事件计划中交叉验证。下游对象审计则防止会话失效后保留新的持久化。
服务账户凭据仍应按主机失陷程序轮换,但不能把它当成 token-signing key 轮换的替代。gMSA 改善密码卫生,也不会撤销 machine DPAPI 保护的旧 RSA 私钥。恢复计划把两项列成不同任务、不同证据和不同验收。
若 farm 节点本身的完整性无法证明,应从可信介质重建;仅删除可疑工具不足以恢复信任。新节点接入前核对补丁、基线、管理网络、EDR、日志、证书 provider 和 HSM 策略;旧节点保持隔离用于取证,不能重新加入负载均衡。
计划轮换与失陷轮换的重叠期不同。日常变更可以给依赖方充分刷新时间;确认私钥可能泄露后,继续同时信任旧钥本身就在延长风险。事件指挥根据关键应用就绪度决定压缩重叠、临时中断或隔离遗留 trust,并把选择和残余风险交给明确负责人。
密钥更新前还要核对 claims rule 与 relying party 配置完整性。主机高权限失陷不仅可能暴露私钥,也可能改变谁能获得何种 claim。若只换钥而保留被篡改的规则,新密钥会继续为错误权限签名。可信基线、配置差异和双人复核应在重新开放签发前完成。
应急账户与管理通道必须独立验证。轮换过程中若所有管理员都依赖同一个 AD FS trust,错误配置可能让恢复团队把自己锁在门外。受控的 break-glass 身份、离线联系表和经过演练的替代入口提供可用性,但其使用要产生高优先级审计并在事后轮换。
会话撤销要按实际产品能力验证,执行命令只是起点。记录撤销时间后,使用事先准备的测试会话再次访问,确认令牌、cookie 与刷新流程确实失败;无法立即失效的应用,通过网络隔离、账户禁用或应用侧密钥轮换补偿,直到最长生命周期结束。
旧钥拒绝测试同样要覆盖主要路径。一个依赖方拒绝不代表全部拒绝,一个节点签出新指纹也不代表全部节点已切换。最终矩阵把新钥成功与旧钥失败放在相邻两列,二者都通过才关闭对应应用和节点的恢复任务。
7.2 每一次轮换都要留下可以独立复核的证据包
证据包包括事前与事后 AD FS 配置、每节点证书库和 provider、metadata、relying party 信任、受控登录、签名指纹、会话撤销、旧公钥拒绝、主机重建和下游审计。每项带采集时间、负责人、来源、哈希或稳定 ID。
变更记录要区分“安装证书”“登记到 AD FS”“提升为 Primary”“依赖方已消费”“旧信任已删除”。这些状态在界面上可能相邻,安全含义完全不同。自动化脚本也应分别验证,失败时停在明确阶段并给出回退。
第二组复核人员随机选择一个节点、一个 Microsoft relying party 和一个第三方 relying party,从配置一路追到实际签名和登录,再验证依赖方拒绝由旧密钥产生的签名,确认旧公钥信任已经失效。若无法独立重放,说明恢复依赖执行者记忆,不是可运营控制。
事件关闭时保留未知项:日志盲区、无法强制撤销的会话、未能确认刷新方式的遗留应用、尚未迁移 HSM 的节点。每项有风险接受人和期限。把未知藏进“轮换完成”只会为下一次幽灵记录留下空间。
证据包要保存变更前快照,因为恢复动作会快速覆盖现场。Primary/Secondary、metadata、节点证书库、claims rule、信任配置、活动会话与日志健康先冻结并哈希;紧急情况下无法全部采集,也要记录跳过了什么、由谁决定以及可能损失的判断。
执行记录采用双人控制:一人操作,一人逐项读回指纹、节点和状态,并由不同渠道确认关键依赖方。双人并不是形式上的两次点击,而是防止把旧指纹、错误租户或测试环境写入生产。复核者有权在任一验收证据缺失时暂停提升。
回退也必须留痕。若新证书导致业务失败,记录失败依赖方、错误、发生阶段和临时选择;不能简单恢复旧钥后删掉中间记录。失陷事件中的回退可能重新开放已知风险,需要新的批准、隔离措施和最短期限。
恢复指标至少包括发现到隔离、生成到发布、发布到关键依赖方确认、提升到旧公钥删除、撤销到测试会话失败的时间。它们揭示真正的瓶颈在技术、所有权还是沟通。下一次演练应针对最长阶段改进;单一的“轮换成功”总时长会掩盖关键等待。
关闭后的触发条件要提前写明:发现新的敏感对象读取、某依赖方仍接受旧签名、旧会话继续产生动作、证据显示 claims rule 被改或新的节点漂移,都自动重开事件。恢复结论必须随证据更新,会议纪要没有永久冻结它的权力。
8 让下一次调查不再从一张过期证书走错方向
长期改进的第一步是把 AD FS 纳入身份控制面;普通服务器资产分类无法体现它的签发权。管理只从专用特权工作站和受控网络进入,禁止通用运维工具与共享管理员,限制出网和交互式登录;EDR、对象审计、AD FS 审计与时间同步成为部署基线。
第二步是让证书生命周期可观测。无论自动还是手工轮换,都为生成、Secondary 发布、依赖方消费、Primary 提升、旧证书退役设置明确阈值和告警。Event 385 不能长期静默;任何指纹不一致都必须在台账中有原因和完成时间。
第三步是减少可携带私钥。HSM-backed non-exportable key 把签名材料留在受控设备中,主机只获得签名能力。它不能替代主机加固,却能把 SYSTEM 失陷后的一个高影响分支封住。密钥操作审计还为异常签名频率和调用主体提供新的证据面。
第四步是逐步减少依赖 AD FS 的信任。能迁移到原生现代联合或托管身份的 relying party,应按业务计划退出旧 trust。只有从依赖方删除对 AD FS issuer 与公钥的信任,才真正缩小这把钥匙能打开的门数。
8.1 HSM、gMSA 与自动轮换分别解决不同的问题
HSM 处理私钥可导出性和受控签名;gMSA 处理服务账户密码生成、轮换与运维;自动证书轮换处理 AD FS 证书生命周期和 metadata 提前发布。三者互补,不能用其中一项替代另外两项。控制说明必须写清对象、威胁和验收。
例如启用 gMSA 后,验证密码不再由人工管理、服务可持续运行和权限收敛;它不要求 machine key 自动改变。启用自动轮换后,验证 Primary/Secondary 与 relying party 刷新;它不证明私钥不可导出。部署 HSM 后,验证私钥生成、不可导出、provider、审计与灾备;它不证明 claims rule 没被篡改。
桌面演练应从 Event 385 与一条异常 4663 开始,随后加入无法对应 AD FS 前序的高权登录。值班团队要在规定时间内确定活动指纹、隔离节点、生成轮换计划、通知 relying party、撤销会话并形成证据包。只讨论职责不算通过。
演练要故意加入现实摩擦:一个遗留应用手工保存公钥、一个节点日志转发中断、一个业务负责人无法联系、一个测试会话在撤销后仍能刷新。团队必须用现有资产、联系人和工具解决,口头假设不计入演练结果。每个失败转化为有期限的工程任务。
特权管理路径也需要持续收敛。AD FS 节点不承载浏览、邮件和通用脚本,不从普通办公网络直接登录;紧急工具经过签名、审批和会话录制。备份、虚拟化与监控平台若能读取节点内存或磁盘,也纳入同一特权范围和访问复核。
迁移计划要按 trust 的现实用途排序。先识别能够改用托管身份、现代协议或云原生认证的应用,再评估会话、claim 与业务依赖。每删除一个不再需要的 relying party,都是减少一扇旧私钥可能打开的门;仅停用 AD FS 页面而保留 trust,不算迁移。
对暂时无法迁移的应用,明确补偿控制:最短会话、严格 audience、最小 claim、专用网络、强日志和快速公钥轮换。补偿措施有到期日与所有者,不能成为无限期接受软件可导出私钥的理由。架构债务只有被量化,才会进入真正的路线图。
季度复核不只检查证书是否过期,还抽样重放完整证据链:从某节点活动指纹开始,找到 provider、metadata、依赖方公钥、一次真实签发和下游登录,再验证旧测试钥失败。这个过程在平时可完成,事故中才不会第一次发现联系人、日志或脚本早已失效。
8.2 最终标准不是“没有告警”,而是信任重新可证明
一个健康的 farm 能随时回答:当前 Primary 和 Secondary 是谁,每个节点从哪个 provider 打开私钥,metadata 发布什么,每个关键 relying party 接受什么,上一次受控登录实际用了哪个指纹,旧私钥和旧会话是否已经失效。答案来自证据,不来自某个人的记忆。
一个可调查的 farm 还能回答:敏感密钥与 master-key 对象被谁读过,合法服务基线是什么,AD FS 签发如何与下游登录关联,日志是否覆盖每个节点,缺失记录多久会被发现。没有这些能力,Machine DPAPI 的正常连续性会在事件中变成取证盲区。
这宗研究最有价值的地方集中在一次判断修正,一条新的导出命令反倒不是重点。数据库对象可以真实、完整、可解密,却已经无法回答运行时状态;操作系统为了服务连续性保存的另一把钥匙,才决定下游继续信任什么。实际签名结果确定调查方向,熟悉的存储位置只能提供线索。
当配置、主机密码学、metadata、依赖方信任和会话重新一致,旧私钥无法制造新会话,旧会话已经被处理,另一组人员能够重放证据,恢复才算完成。到那时,“幽灵”不再是数据库里一张过期证书,而是一条已经被制度化检查捕获的漂移信号。
这套标准也改变了日常问题的问法。团队不再问“数据库里的证书能不能解开”,而是问“此刻哪把钥匙代表组织签名、它由谁控制、哪些系统接受、每个判断来自什么证据”。前者只关心一个对象,后者覆盖信任从产生到消费的全部旅程。
同样,主机没有出现已知工具或显眼导出文件,不能证明密钥没有暴露。若 SYSTEM 层的可信状态已经失去保证、关键材料可从快照组合、日志又存在缺口,风险判断应保守;但报告仍把“可能暴露”与“观察到伪造登录”分开,避免用严重性代替事实。
真正成熟的控制允许快速证伪。遇到 385,值班人员能在分钟内取出四面指纹;遇到 4663,能连到登录与变更单;遇到联邦高权登录,能找到对应签发和 claim;轮换后,能让旧签名在每个关键依赖方失败。无法证伪的告警会长期停留在猜测。
公开案例中的旧 WID 对象并没有撒谎,它只是回答了过去。错误来自调查者最初把历史存储误当成运行时全景。将这次修正固化为对账、审计、轮换和会话验收,组织便能在下一次遇到相同失败时更快转向真正决定信任的证据。
文章中的每项建议都可以落到一个可见交付物:活动密钥台账、节点测试矩阵、依赖方所有者清单、跨层关联查询、失陷轮换手册、旧钥拒绝报告和迁移路线图。没有交付物的“加强监控”无法验收,也无法在人员更替后继续运作。
最终,AD FS 的风险并不神秘。它源于一个非常具体的事实:一台服务器持有替组织断言身份的能力。只要这项能力仍存在,私钥托管、服务身份、证书生命周期、下游信任与审计证据就必须同时有人负责;任何一块沉默,都会让下一张过期记录再次把调查带离真正的活动钥匙。
研究记录
9证据、对象与来源
下面保留本文实际使用的标识、时间和原始材料,便于继续调查。
9.1研究对象
报告涉及的产品、行为者、技术、受影响对象和控制点。
提示证书有效性或配置漂移,需要核对证书四事实面;不能单独认定私钥被窃。
仅在配置相应 SACL 时提供对象访问证据;需要与登录、进程、对象路径和身份结果关联。
公开案例中用于识别旧签名材料已不被信任;也可能来自普通配置与证书生命周期问题。
该环境活动 CAPI 软件私钥的 machine-scoped 存储面;路径本身不是恶意指标。
SYSTEM machine master-key 证据面;路径本身不是恶意指标。
Machine DPAPI 依赖之一;任何访问应按高敏感本机秘密处理。
9.2事件时间
- 配置与运行时分叉
服务开始使用新证书,而 WID 仍保留过期对象;Event 385 为该环境提供漂移线索。
- 旧对象可解密但不可用
恢复出的证书能够生成结构完整的断言,Entra 以 AADSTS500172 拒绝。
- 活动 CAPI 私钥被确认
授权评估从主机 machine-scoped 存储恢复与活动证书吻合的 RSA 私钥。
- 活动签名被下游接受
恢复出的活动私钥在授权环境签出全局管理员断言,并被 Entra 接受。
- Mandiant 公开研究
公开配置漂移、Machine DPAPI 依赖、检测与恢复建议。
- SOSEC 完成分层复核
对照 Microsoft 文档和固定 SharpDPAPI 源码,重建配置、密码学对象、签发与 relying party 的证据链。
9.3来源与材料
- Mandiant:通过 Machine DPAPI 恢复活动 AD FS 签名密钥https://cloud.google.com/blog/topics/threat-intelligence/recovering-active-adfs-signing-keys-machine-dpapi
- Microsoft:AD FS token-signing certificateshttps://learn.microsoft.com/en-us/windows-server/identity/ad-fs/design/token-signing-certificates
- Microsoft:配置 token-signing 与 token-decrypting 证书https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-ts-td-certs-ad-fs
- Microsoft:Get-AdfsCertificatehttps://learn.microsoft.com/en-us/powershell/module/adfs/get-adfscertificate?view=windowsserver2025-ps
- Microsoft:Set-AdfsCertificatehttps://learn.microsoft.com/en-us/powershell/module/adfs/set-adfscertificate?view=windowsserver2025-ps
- Microsoft:Get-AdfsPropertieshttps://learn.microsoft.com/en-us/powershell/module/adfs/get-adfsproperties?view=windowsserver2025-ps
- Microsoft:CryptProtectData 与 CRYPTPROTECT_LOCAL_MACHINEhttps://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectdata
- Microsoft:Data Protection API 概览https://learn.microsoft.com/en-us/windows/win32/seccng/cng-dpapi
- Microsoft:保护 AD FS 的最佳实践https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/deployment/best-practices-securing-ad-fs
- Microsoft:AD FS 事件与日志https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/troubleshooting/ad-fs-tshoot-logging
- GhostPack SharpDPAPI:固定复核版本https://github.com/GhostPack/SharpDPAPI/tree/4428263fe85bb1fde1640b6208d11dff6db4fb55
- SharpDPAPI:boot key 与 LSA secret 依赖实现https://github.com/GhostPack/SharpDPAPI/blob/4428263fe85bb1fde1640b6208d11dff6db4fb55/SharpDPAPI/lib/LSADump.cs
- Mandiant:Abusing AD FS Replicationhttps://cloud.google.com/blog/topics/threat-intelligence/abusing-replication-stealing-adfs-secrets-over-the-network/
- Microsoft:系统性身份入侵后的恢复建议https://www.microsoft.com/en-us/security/blog/2020/12/21/advice-for-incident-responders-on-recovery-from-systemic-identity-compromises/
- MITRE ATT&CK T1606.002https://attack.mitre.org/techniques/T1606/002/