# Security Considerations When Using Doom: A Complete Guide to Safe ADCS Enumeration

> Learn essential security considerations for using Doom, a Python ADCS enumeration tool. Protect credentials and prevent MITM attacks with our expert guide.

- Repository: [000pp/doom](https://github.com/000pp/doom)
- Tags: deep-dive
- Published: 2026-02-22

---

**Doom is a Python-based Active Directory Certificate Services (ADCS) enumeration tool that requires careful handling of credentials, LDAP connections, and TLS validation to prevent credential exposure and man-in-the-middle attacks.**

Doom, developed by 000pp, is an open-source utility designed for security professionals conducting ADCS reconnaissance. While it provides valuable insights into certificate template configurations, several implementation details in the codebase introduce significant security considerations when using Doom in production environments. Understanding these risks is essential for maintaining operational security during penetration testing or red team exercises.

## Credential Handling Risks in Doom

### Clear-Text Password Storage in Memory

The authentication flow in Doom begins at [`src/doom/screens/login_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/login_screen.py), where the UI captures credentials using `Input(..., password=True)`. While this masks the display, the password is stored as a clear-text string in a plain dictionary within the `LoadingScreen` class before being passed to the LDAP connector.

This implementation means passwords exist in memory in an unencrypted state and may be written to logs if an exception occurs during the connection phase. The current codebase does not implement secure memory clearing after authentication attempts.

### Mitigation Strategies for Secure Credential Management

To reduce exposure when using Doom, implement the following practices:

- **Clear variables immediately after use**: Explicitly delete password variables from memory using `del password` after the LDAP connection is established.
- **Integrate secure credential vaults**: Replace raw input methods with Windows Credential Manager or similar secure storage solutions instead of passing clear-text passwords through the UI layer.

## LDAP Connection Security Vulnerabilities

### Unencrypted LDAP Fallback on Port 389

The `get_ldap_connection()` function in [`src/doom/protocols/ldap.py`](https://github.com/000pp/doom/blob/main/src/doom/protocols/ldap.py) attempts an unencrypted LDAP bind on port 389 before falling back to LDAPS on port 636. The code explicitly sets `use_ssl=False` for the initial connection attempt.

If the Active Directory server permits simple LDAP on port 389, credentials are transmitted in clear text across the network, exposing them to packet sniffers and network-level attackers. This fallback behavior creates an unnecessary attack surface.

### Insecure TLS Configuration and Certificate Validation

When LDAPS is used, the TLS configuration in [`src/doom/protocols/ldap.py`](https://github.com/000pp/doom/blob/main/src/doom/protocols/ldap.py) (lines 15-18) disables critical security checks:

```python
validate=ssl.CERT_NONE
ciphers="ALL:@SECLEVEL=0"

```

Setting `validate=ssl.CERT_NONE` disables server certificate verification, making the tool vulnerable to man-in-the-middle (MITM) attacks. The cipher override `"ALL:@SECLEVEL=0"` enables insecure cryptographic algorithms that modern security standards have deprecated.

To secure these connections, modify the code to use `validate=ssl.CERT_REQUIRED` and supply a proper CA bundle, removing the insecure cipher override entirely.

### Password Pre-Hash Detection Logic

The LDAP implementation contains logic that detects if a supplied password is a 32-character hexadecimal string. If detected, the code prefixes it with the NTLM hash marker `aad3b435b51404eeaad3b435b51404ee` (found in [`src/doom/protocols/ldap.py`](https://github.com/000pp/doom/blob/main/src/doom/protocols/ldap.py), lines 12-14).

This behavior introduces two risks: an attacker could intentionally supply a hash to bypass NTLM challenges, or the code could unintentionally treat a user-chosen password as a hash, weakening authentication strength. The tool should require an explicit flag for "hashed password mode" and validate that hashes truly originate from NTLM computations.

## Information Disclosure Risks

### Verbose Error Messages and LDAP Information Leakage

Error handling in [`src/doom/protocols/ldap.py`](https://github.com/000pp/doom/blob/main/src/doom/protocols/ldap.py) re-raises exceptions with raw error text: `raise Exception(f"LDAP bind error: {e}")`. Detailed LDAP error messages may reveal sensitive configuration details, such as which authentication mechanisms are permitted or the internal structure of the directory.

Operators should modify error handling to log detailed messages at a debug level only, presenting generic error messages to end users.

### ADCS Template Enumeration Output

The `enumerate_templates()` function in [`src/doom/modules/enumerate_templates.py`](https://github.com/000pp/doom/blob/main/src/doom/modules/enumerate_templates.py) returns all raw LDAP attributes, including potentially sensitive flags like `msPKI-Enrollment-Flag`. While this is the tool's intended purpose, the output provides attackers with a complete map of privileged certificate templates, facilitating privilege escalation attacks.

Run Doom only in controlled, authorized environments. Consider adding filters to hide high-risk attributes unless explicitly requested by the operator.

## Supply Chain and Dependency Security

The project declares dependencies in [`pyproject.toml`](https://github.com/000pp/doom/blob/main/pyproject.toml) and pulls code from external sources, including Certipy structs. Compromised third-party packages could introduce backdoors or malicious code into the enumeration workflow.

Mitigate supply chain risks by pinning exact dependency versions in [`pyproject.toml`](https://github.com/000pp/doom/blob/main/pyproject.toml), verifying package integrity with cryptographic hashes, and using reproducible build environments such as containerized deployments.

## Secure Implementation Examples

Replace the default insecure LDAP connection with this hardened implementation:

```python
import ssl
import ldap3

def get_secure_ldap_connection(host: str, username: str, password: str, domain: str):
    """Enforce LDAPS with certificate validation."""
    user = f"{domain}\\{username}"

    # Force LDAPS only

    tls = ldap3.Tls(
        validate=ssl.CERT_REQUIRED,
        # Use system default CA bundle

        ca_certs_file=ssl.get_default_verify_paths().cafile,
        version=ssl.PROTOCOL_TLS_CLIENT,
    )
    ldaps_server = ldap3.Server(
        f"ldaps://{host}",
        port=636,
        use_ssl=True,
        get_info=ldap3.ALL,
        tls=tls,
    )
    conn = ldap3.Connection(
        server=ldaps_server,
        user=user,
        password=password,
        authentication=ldap3.NTLM,
        auto_bind=True,
        raise_exceptions=True,
    )
    base_dn = conn.server.info.other.get("defaultNamingContext", [""])[0]
    return conn, base_dn

```

Clear sensitive data from memory immediately after authentication:

```python
password = self.query_one("#password-input").value
login_data = {"ip": ip, "domain": domain, "username": username, "password": password}

# ... use login_data ...

del password   # remove clear‑text password from locals

```

## Summary

- **Credential exposure**: Doom stores passwords in clear text in memory during the authentication flow in [`src/doom/screens/login_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/login_screen.py) and [`src/doom/screens/loading_screen.py`](https://github.com/000pp/doom/blob/main/src/doom/screens/loading_screen.py).
- **Unencrypted transmission**: The default `get_ldap_connection()` function attempts unencrypted LDAP on port 389 before trying LDAPS, risking clear-text credential exposure.
- **Disabled TLS validation**: The current implementation uses `validate=ssl.CERT_NONE` and insecure ciphers, making connections vulnerable to MITM attacks.
- **Information leakage**: Verbose error messages and raw LDAP attribute output in [`src/doom/modules/enumerate_templates.py`](https://github.com/000pp/doom/blob/main/src/doom/modules/enumerate_templates.py) may reveal sensitive ADCS configuration details.
- **Supply chain risks**: External dependencies in [`pyproject.toml`](https://github.com/000pp/doom/blob/main/pyproject.toml) require version pinning and integrity verification to prevent backdoor injection.

## Frequently Asked Questions

### Is Doom safe to use in production Active Directory environments?

Doom is designed for authorized security assessments, but its default configuration introduces significant risks for production environments. The tool transmits credentials over potentially unencrypted channels and stores passwords in clear text in memory. Only use Doom in isolated lab environments or with explicit authorization, and apply the security hardening measures described in this guide before connecting to production domains.

### How does Doom handle password storage securely?

Currently, Doom does not handle password storage securely. The [`login_screen.py`](https://github.com/000pp/doom/blob/main/login_screen.py) module captures passwords using `Input(..., password=True)`, which only masks the UI display, then stores the value in a plain dictionary passed to `LoadingScreen`. The password remains in memory as a clear-text string until the Python garbage collector reclaims it. Users should manually clear password variables using `del password` immediately after authentication and consider integrating Windows Credential Manager or similar secure vaults instead of manual entry.

### What are the risks of using Doom over unencrypted LDAP?

The `get_ldap_connection()` function in [`src/doom/protocols/ldap.py`](https://github.com/000pp/doom/blob/main/src/doom/protocols/ldap.py) attempts a connection to port 389 with `use_ssl=False` before falling back to LDAPS on port 636. If the Active Directory server accepts simple LDAP binds, this transmits credentials in clear text across the network, exposing them to packet sniffers and network-level attackers. Additionally, the TLS configuration disables certificate validation with `validate=ssl.CERT_NONE`, making the tool vulnerable to man-in-the-middle attacks even when LDAPS is used.

### How can I verify the integrity of Doom's dependencies?

Doom relies on external packages including `ldap3` and code from Certipy structs, declared in [`pyproject.toml`](https://github.com/000pp/doom/blob/main/pyproject.toml). To verify integrity, pin exact dependency versions in your [`pyproject.toml`](https://github.com/000pp/doom/blob/main/pyproject.toml) or [`requirements.txt`](https://github.com/000pp/doom/blob/main/requirements.txt) using hash verification. Use tools like `pip install --require-hashes` or containerized environments with reproducible builds to ensure that compromised third-party packages cannot introduce backdoors into your ADCS enumeration workflow.