Skip to main content


CertiHound

Linux-native AD CS collector for BloodHound CE

PyPI Python Version License

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

ESC1 Detection in BloodHound

CertiHound detects ESC1 vulnerable templates and creates enrollment edges to Enterprise CAs, enabling attack path analysis in BloodHound CE.

ESC4 - Template ACL Abuse Detection

ESC4 Detection in BloodHound

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

pipx install certihound
# Or, if you need Kerberos (-k) auth:
pipx install 'certihound[kerberos]'
# On an existing install, inject gssapi:
pipx inject certihound gssapi

From Source

git clone https://github.com/0x0Trace/certihound.git
cd certihound
pip install -e .            # core
pip install -e '.[kerberos]' # with Kerberos support

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/

# Pass-the-Hash (NTHASH only, or LMHASH:NTHASH)
certihound -d corp.local -u 'user' -H :31d6cfe0d16ae931b73c59d7e0c089c0 --dc 10.10.10.10

# LDAPS (SSL/TLS) connection
certihound -d corp.local -u 'user' -p 'password' --dc 10.10.10.10 --ldaps -o output/

# Kerberos authentication (uses ccache; requires the 'kerberos' extra)
KRB5CCNAME=user.ccache certihound -d corp.local -k --dc dc01.corp.local -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
  -H, --hashes TEXT         NTLM hash for pass-the-hash (LMHASH:NTHASH or NTHASH)
  --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

  1. Run CertiHound to generate the ZIP file
  2. Open BloodHound CE
  3. Click Import → Select the generated ZIP file
  4. 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 the feature/adcs-collection branch 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


Made with :heart: for the security community

Metadata

Release files for certihound 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for certihound 0.3.2
File Size Uploaded Provenance
certihound-0.3.2.tar.gz 72.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for certihound 0.3.2
File Interpreter ABI Platform
certihound-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 165.1 kB

Release files / certihound-0.3.2.tar.gz

Download URL certihound-0.3.2.tar.gz
Size 72.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b92a08e1bcf98771aecbc4ed7c78ec934ce8f4b34bd8127965114c14f936529d
BLAKE2b-256 checksum
How to use checksums
45309a6ccbefa74b399abbc2a556937eb62e87e44ae6fd6cd238d585421da420
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.9

Release files / certihound-0.3.2-py3-none-any.whl

Download URL certihound-0.3.2-py3-none-any.whl
Size 92.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c68b6f8efde09843685b616772445f0d68bff0865f54df5b12f576c1eebd1edd
BLAKE2b-256 checksum
How to use checksums
e641a42e7351d28f2ef7c30edf27fd412365b89ff3efe4907d1839c9ece25990
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.9

Security for certihound 0.3.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page