Linux-native AD CS collector library for BloodHound CE - enumerate ADCS and export to BloodHound format
Project description
CertiHound
Linux-native AD CS collector for BloodHound CE
Features • Installation • Quick Start • Usage • BloodHound • API
CertiHound enumerates Active Directory Certificate Services (AD CS) via LDAP and exports BloodHound CE-compatible data for attack path visualization. Identify ESC1-ESC17 vulnerabilities and visualize certificate-based attack paths.
Screenshots
ESC1 - Enrollee Supplies Subject Detection
CertiHound detects ESC1 vulnerable templates and creates enrollment edges to Enterprise CAs, enabling attack path analysis in BloodHound CE.
ESC4 - Template ACL Abuse Detection
WriteDacl, WriteOwner, and other dangerous permissions on certificate templates are identified and mapped as attack edges.
Features
| Feature | Description |
|---|---|
| Linux-Native | No Windows dependencies - pure Python LDAP enumeration |
| BloodHound CE v6+ | Direct JSON/ZIP import with full node and edge support |
| Vulnerability Detection | ESC1-ESC11, ESC13-ESC17, GoldenCert |
| Multiple Backends | Works with ldap3, impacket, or any compatible LDAP adapter |
| NetExec Integration | Seamless integration with NetExec's --bloodhound option |
| Comprehensive Coverage | Certificate templates, Enterprise CAs, Root CAs, NTAuth, AIA CAs |
Supported Vulnerabilities
| Vulnerability | Description |
|---|---|
| ESC1 | Enrollee supplies subject with low-privilege enrollment |
| ESC2 | Any Purpose EKU or no EKU allows enrollment agent abuse |
| ESC3 | Enrollment agent templates + vulnerable targets |
| ESC4 | Dangerous ACL permissions on certificate templates |
| ESC5 | Vulnerable PKI object access control on AD containers |
| ESC6 | EDITF_ATTRIBUTESUBJECTALTNAME2 on Enterprise CA |
| ESC7 | Dangerous CA permissions (ManageCA / ManageCertificates) |
| ESC8 | NTLM relay to AD CS web enrollment (HTTP) endpoints |
| ESC9 | No security extension + weak certificate mapping |
| ESC10 | Weak certificate mapping without strong binding |
| ESC11 | NTLM relay to AD CS RPC endpoints (no encryption enforcement) |
| ESC13 | Issuance policy with OID group link abuse |
| ESC14 | Weak explicit certificate mappings (altSecurityIdentities) |
| ESC15 | EKUwu - Application policy abuse on Schema V1 templates |
| ESC16 | Security extension globally disabled on CA |
| ESC17 | Server Authentication EKU + enrollee supplies subject (TLS MITM) |
| GoldenCert | CA private key extraction from hosting computer |
Installation
From PyPI (Recommended)
pip install certihound
From Source
git clone https://github.com/0x0Trace/certihound.git
cd certihound
pip install -e .
Verify Installation
certihound --version
certihound --help
Quick Start
Command Line
# Basic enumeration with password authentication
certihound -d corp.local -u 'user' -p 'password' --dc 10.10.10.10 -o output/
# LDAPS (SSL/TLS) connection
certihound -d corp.local -u 'user' -p 'password' --dc 10.10.10.10 --ldaps -o output/
# Kerberos authentication (uses ccache)
certihound -d corp.local -k --dc 10.10.10.10 -o output/
# Output as ZIP (default) or JSON
certihound -d corp.local -u 'user' -p 'password' --dc 10.10.10.10 --format zip
certihound -d corp.local -u 'user' -p 'password' --dc 10.10.10.10 --format json
Python Library
from certihound import ADCSCollector, BloodHoundCEExporter
from certihound.ldap.connection import LDAPConnection, LDAPConfig
# Configure connection
config = LDAPConfig(
domain="corp.local",
username="user",
password="password",
dc_ip="10.10.10.10",
use_ldaps=True,
)
# Collect and export
with LDAPConnection(config) as conn:
collector = ADCSCollector(conn)
data = collector.collect_all()
exporter = BloodHoundCEExporter(data.domain, data.domain_sid)
result = exporter.export(data)
result.write_zip("bloodhound_adcs.zip")
Usage
CLI Options
Usage: certihound [OPTIONS]
Options:
-d, --domain TEXT Target domain FQDN (e.g., corp.local) [required]
-u, --username TEXT Username for authentication
-p, --password TEXT Password for authentication
--dc TEXT Domain Controller IP or hostname
-k, --kerberos Use Kerberos authentication (ccache)
--ldaps Use LDAPS (SSL/TLS)
--ca-cert PATH CA certificate file for LDAPS validation
--port INTEGER LDAP port (default: 389 or 636 for LDAPS)
-o, --output TEXT Output directory (default: ./output)
--format [json|zip|both] Output format (default: zip)
--enum-only Only enumerate, skip vulnerability detection
-v, --verbose Increase verbosity (-v, -vv)
--version Show the version and exit.
--help Show this message and exit.
Output Files
CertiHound generates BloodHound CE v6 compatible files:
| File | Description |
|---|---|
certtemplates.json |
Certificate template nodes with properties and edges |
enterprisecas.json |
Enterprise CA nodes with template publishing |
rootcas.json |
Root CA hierarchy nodes |
ntauthstores.json |
NTAuth store configuration |
aiacas.json |
AIA CA entries |
BloodHound Integration
Importing Data
- Run CertiHound to generate the ZIP file
- Open BloodHound CE
- Click Import → Select the generated ZIP file
- Use the built-in ADCS queries or create custom ones
Example Cypher Queries
Find ESC1 Vulnerable Templates:
MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->
(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)
WHERE ct.enrolleesuppliessubject = True
AND ct.authenticationenabled = True
RETURN p
Find ESC4 Template ACL Abuse:
MATCH p = (principal)-[:WriteDacl|WriteOwner|GenericWrite|GenericAll|WriteAllProperties]->
(ct:CertTemplate)-[:PublishedTo]->(ca:EnterpriseCA)
WHERE NOT principal.objectid ENDS WITH '-512'
AND NOT principal.objectid ENDS WITH '-519'
AND NOT principal.objectid ENDS WITH '-544'
RETURN p
NetExec Integration
CertiHound integrates with NetExec for ADCS enumeration.
Status: Integration PR pending review at Pennyw0rth/NetExec#1054
Try it now: Use thefeature/adcs-collectionbranch from 0x0Trace/NetExec
# ADCS only collection
nxc ldap 10.10.10.10 -u user -p pass --bloodhound -c ADCS
# Full collection including ADCS
nxc ldap 10.10.10.10 -u user -p pass --bloodhound -c All --dns-server 10.10.10.10
NetExec Integration Code
from certihound import ADCSCollector, BloodHoundCEExporter, ImpacketLDAPAdapter
# In NetExec's ldap.py:
adapter = ImpacketLDAPAdapter(
search_func=self.search,
domain=self.domain,
domain_sid=self.sid_domain,
)
collector = ADCSCollector.from_external(
ldap_connection=adapter,
domain=self.domain,
domain_sid=self.sid_domain,
)
data = collector.collect_all()
exporter = BloodHoundCEExporter(data.domain, data.domain_sid)
result = exporter.export(data)
result.write_zip("adcs_bloodhound.zip")
API Reference
Core Classes
| Class | Description |
|---|---|
ADCSCollector |
Main collector for ADCS enumeration |
BloodHoundCEExporter |
Exports data to BloodHound CE format |
ImpacketLDAPAdapter |
Adapter for impacket-based LDAP (NetExec) |
LDAPConnection |
Standalone LDAP connection wrapper |
LDAPConfig |
Configuration dataclass for LDAP connections |
Data Models
| Class | Description |
|---|---|
ADCSData |
Container for all collected ADCS data |
CertTemplate |
Certificate template with properties and ACLs |
EnterpriseCA |
Enterprise CA with enabled templates |
RootCA |
Root CA node |
NTAuthStore |
NTAuth certificate store |
AIACA |
AIA CA entry |
ExportResult |
Export result with write_zip(), write_json(), to_dict() |
Detection Functions
from certihound import (
detect_esc1,
detect_esc2,
detect_esc3_agent,
detect_esc3_target,
detect_esc4,
detect_esc5,
detect_esc6,
detect_esc7,
detect_esc8,
detect_esc9,
detect_esc10,
detect_esc11,
detect_esc13,
detect_esc14,
detect_esc15,
detect_esc16,
detect_esc17,
)
Usage Example
from certihound import (
ADCSCollector,
BloodHoundCEExporter,
ADCSData,
ExportResult,
)
# Collect data
collector = ADCSCollector.from_external(adapter, domain, domain_sid)
data: ADCSData = collector.collect_all()
# Access collected objects
print(f"Templates: {len(data.templates)}")
print(f"Enterprise CAs: {len(data.enterprise_cas)}")
print(f"Root CAs: {len(data.root_cas)}")
# Export to BloodHound
exporter = BloodHoundCEExporter(data.domain, data.domain_sid)
result: ExportResult = exporter.export(data)
# Output options
result.write_zip("output.zip") # ZIP for BloodHound import
result.write_json("output/") # Individual JSON files
output_dict = result.to_dict() # Python dictionary
Development
Setup Development Environment
# Clone repository
git clone https://github.com/0x0Trace/certihound.git
cd certihound
# Install with dev dependencies
pip install -e ".[dev]"
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=certihound
# Run specific test file
pytest tests/test_detection.py -v
Code Quality
# Format code
black certihound/
# Lint
ruff check certihound/
# Type checking
mypy certihound/
Dependencies
| Package | Purpose |
|---|---|
ldap3 |
LDAP operations (standalone mode) |
impacket |
Kerberos authentication & NetExec integration |
cryptography |
Certificate parsing and analysis |
pydantic |
Data validation and models |
click |
CLI framework |
rich |
Terminal output formatting |
License
This project is licensed under the MIT License - see the LICENSE file for details.
Credits & References
- Inspired by Certipy by Oliver Lyak
- BloodHound CE format based on BloodHound by SpecterOps
- ADCS vulnerability research: Certified Pre-Owned by Will Schroeder & Lee Christensen
Made with :heart: for the security community
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file certihound-0.3.0.tar.gz.
File metadata
- Download URL: certihound-0.3.0.tar.gz
- Upload date:
- Size: 66.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1112797db62292128bc1c8522017b9b38285ff51ec5d9d4ed3442761701efa9b
|
|
| MD5 |
fffd512956b8354c12edd6e7ab8fd164
|
|
| BLAKE2b-256 |
f8fbb54bc507c72f7e5266b6633440c143a6e175e32024ff7da25ea11bc22506
|
File details
Details for the file certihound-0.3.0-py3-none-any.whl.
File metadata
- Download URL: certihound-0.3.0-py3-none-any.whl
- Upload date:
- Size: 87.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00c8bd63473684cee335f7f274ce2284c57219cb8f795a2fb82b2be6b7c6ba92
|
|
| MD5 |
649e7bb25086966f16aeb441b2dceb80
|
|
| BLAKE2b-256 |
4f9280ba20537fee36118bf3fd3da6f2121210775bc2a08d839c328b4e4fb95f
|