Skip to content
Security
Skill

/ad-environment-constraints

Real-world Active Directory environment constraints that silently break attacks when ignored: NTLM disabled (Kerberos fallback), AES-only KDCs (RC4 blocked by GPO), LDAP signing and channel binding requiring LDAPS on 636, Kerberos clock skew (KRB_AP_ERR_SKEW), SPNs that must be

BOOST
From plugin
claude-ad
2128 skills3 agents3 commands
Install
$ npx -y skills add ADScanPro/Claude-AD --skill ad-environment-constraints --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/ad-environment-constraints

Context preview

The summary Claude sees to decide when to auto-load this skill.

Real-world Active Directory environment constraints that silently break attacks when ignored: NTLM disabled (Kerberos fallback), AES-only KDCs (RC4 blocked by GPO), LDAP signing and channel binding requiring LDAPS on 636, Kerberos clock skew (KRB_AP_ERR_SKEW), SPNs that must be

SKILL.md

ad-environment-constraints.SKILL.md
name: ad-environment-constraints
description: >
  Real-world Active Directory environment constraints that silently break attacks when
  ignored: NTLM disabled (Kerberos fallback), AES-only KDCs (RC4 blocked by GPO), LDAP
  signing and channel binding requiring LDAPS on 636, Kerberos clock skew (KRB_AP_ERR_SKEW),
  SPNs that must be FQDNs never short names or IPs (the misleading invalidCredentials),
  Protected Users / LAPS / gMSA / MachineAccountQuota, LDAP 1000-object paging, and VPN
  latency. Use this whenever a bind, TGT request, LDAP query, or SMB negotiation fails in a
  way that looks like bad credentials but is really hardening, or before running any AD
  tooling against a domain you have not fingerprinted. Standard-tooling knowledge (netexec,
  impacket, certipy, bloodyAD, kerbrute), no vendor-specific engine.

AD Environment Constraints

Code and commands that work in a lab break in a hardened domain, and the failure almost never says what it is. A Kerberos SPN mismatch surfaces as `invalidCredentials`. NTLM being disabled surfaces as a logon failure. AES-only KDCs reject your RC4 request with an etype error you have to know to read. This skill is the checklist of those constraints and how to survive each one with standard tooling.

**Detect the posture before you authenticate.** Every constraint below is detectable up front: probe whether NTLM answers, whether the KDC accepts RC4, whether LDAP signing is required, whether LDAPS is listening. Fingerprint first, then choose your auth path to match. Fixing an auth path reactively after each failure is slower and noisier than reading the environment once and picking the right transport from the start.

---

1. Authentication protocol: NTLM may be disabled

NTLM can be turned off org-wide or on specific DCs by GPO. Any auth path that assumes NTLM must fall back to Kerberos.

  • impacket: add `-k` (use Kerberos) and `-no-pass` when you have a ccache/TGT.
  • netexec: `-k` / `--kerberos`.
  • certipy: `-k` / add `--dc-host <fqdn>` so it targets the KDC by name.
# NTLM path
nxc smb dc01.corp.local -u user -p pass
# Kerberos path (NTLM disabled): request a TGT, export ccache, reuse it
getTGT.py corp.local/user:pass -dc-ip <dc_ip>
export KRB5CCNAME=user.ccache
nxc smb dc01.corp.local -u user -k --use-kcache

**Reading the signal, not guessing it.** A healthy NTLM-enabled DC answers an NTLM bind with a *bogus* password with exactly `invalidCredentials` / logon-denied, and that proves NTLM is alive (the DC reached credential verification and rejected the password). Do not infer "NTLM disabled" from a failed bind with a wrong password. NTLM is actually disabled only when you see the SSP collapse markers (`STATUS_NTLM_BLOCKED`, unsupported-function), or when a bind fails as logon-denied *while a valid Kerberos TGT for the same identity succeeds concurrently*. Only then is "wrong password" ruled out as the cause.

If a tool only supports pass-the-hash (NTLM hash), treat that as an explicit limitation in an NTLM-disabled environment: it will not work, and no flag fixes it.

---

2. AES-only KDCs: RC4 blocked by GPO

Domains migrating off legacy crypto enforce AES-128/AES-256 and reject RC4 (arcfour-hmac).

  • Do not force `-cipher rc4` or an explicit `etype 23`. A request that only offers RC4

fails with `KDC_ERR_ETYPE_NOTSUPP` on an AES-only KDC.

  • Let tools negotiate. impacket and netexec negotiate supported etypes by default.
  • For roasting, offering RC4 *first* is fine where the KDC still allows it (RC4 hashes

crack faster); on an AES-only KDC the request simply falls back to AES automatically.

  • On AES-only KDCs with a non-standard salt, AES key derivation needs the salt from an

ETYPE-INFO2 pre-auth probe. Standard clients do this as part of the AS exchange; if you hand-roll key derivation you must probe the salt first or the key is wrong.

# Kerberoast: RC4 preferred where allowed, auto-falls back to AES on an AES-only KDC
GetUserSPNs.py corp.local/user:pass -dc-ip <dc_ip> -request -outputfile hashes.kerberoast

---

3. LDAP signing, channel binding, and LDAPS

Hardened DCs require signed LDAP or channel-bound LDAPS. Plain LDAP on 389 gets rejected after the bind with `strongerAuthRequired` / `LDAP_STRONG_AUTH_REQUIRED`.

  • Prefer **LDAPS on 636**. It satisfies both signing and channel binding in one move.
  • Certipy, bloodyAD and any LDAP-writing tool need `-scheme ldaps` (or the equivalent) when

channel binding is enforced; a plain LDAP write is refused.

  • If only plain LDAP 389 is available and the server demands signing, the client must sign

the connection (SASL sign/seal). A tool with no signing support cannot talk to that DC; that is a hard limitation, document it.

certipy find -u user@corp.local -p pass -dc-ip <dc_ip> -scheme ldaps
bloodyAD --host dc01.corp.local -d corp.local -u user -p pass --secure get object <target>

**Legacy environments without LDAPS.** Not every domain has a cert on the DC. Where 636 is closed, LDAP 389 is your only channel and it is plaintext; signing is often on to compensate. Distinguish a *transport* failure (636 closed → connection refused / TLS handshake error → retry on 389) from a *policy* failure (bind succeeds, then `strongerAuthRequired` → signing/channel-binding issue, a different fix). A tool that tries LDAPS and falls back to plain LDAP handles the first case; the second needs signing, not a port change.

---

4. Clock skew: Kerberos requires ≤5 minutes

Kerberos rejects tickets outside a five-minute window with `KRB_AP_ERR_SKEW`. Sync to the DC before any Kerberos operation.

sudo ntpdate <dc_ip>            # or rdate -n <dc_ip>
# netexec auto-retries after clock correction on skew errors

If a TGT request that should work fails with a skew error, it is your clock, not your credentials.

---

5. Kerberos SPNs: always FQDN, never short name or IP

This is the most misleading failure in AD. A service ticket requ

Read more
Ships withclaude-ad

Active Directory pentest methodology for Claude Code. Skills, agents and commands that give Claude the playbook for an internal Active Directory assessment: the phase order, the environment constraints that break your tooling, the telemetry each technique

Get the whole plugin

Other skills on claude-ad.