Releases: dehobbs/ADScan
Release list
v1.3.4
Fixed
AdminSDHolder ACL check — multiple correctness fixes
These bugs caused both false positives (legitimate principals flagged) and missed findings (real write-access not reported):
- Trustee SIDs were rendered as raw hex blobs. ACE SIDs used
str(sid)(e.g.0105…00020000) instead offormatCanonical(), which defeated every
name/RID match — so every principal, including Domain Admins and SYSTEM, was flagged. Now converted to canonicalS-1-5-…form. - Tier-0 groups now recognized by RID. Domain Admins, Enterprise Admins, Schema Admins, Domain Controllers, and Administrators are matched by their
SID RID, so they're excluded even when SID→name resolution is unavailable. - Mislabeled access-mask constants corrected.
0x00020000(READ_CONTROL — a read right) was treated asWriteDACLand included in the "dangerous"
mask, so any principal with normal read access was flagged as having write. Corrected to the real Win32/ADS write bits (WriteProperty, WriteDACL,
WriteOwner, GenericWrite, GenericAll). - Authenticated Users and Everyone removed from the expected allowlist. They should only ever have read access, so write access for them is now
correctly reported instead of suppressed.
SID resolution — well-known SIDs resolve to friendly names
ADConnector.resolve_sid() now consults a static well-known-SID table before the LDAP lookup, so reports show Authenticated Users / SYSTEM /
Administrators instead of S-1-5-11 / S-1-5-18 / S-1-5-32-544 (these have no queryable directory object and can't be resolved via LDAP). Benefits
every check that resolves SIDs.
Full Changelog: v1.3.3...v1.3.4
v1.3.3
Added
- Generic check preflight hook: a check module may now define an optional
preflight(connector)function.adscan.run_preflight()invokes every
loaded check's hook (inCHECK_ORDER) before the scan loop, so interactive setup happens up front and the scan then runs unattended. A hook that raises
is logged and skipped so it cannot abort the scan. Covered by unit tests.
Changed
- BloodHound engine prompt moved to the start of the run. The Legacy vs Community Edition question is now asked up front via
check_bloodhound's
preflight()hook instead of mid-scan when the collection step is reached. The operator answers once and can walk away; data collection still runs last
(CHECK_ORDER 99) — only the prompt moved. The prompt is skipped entirely when BloodHound is excluded via--checks/--skip, and non-interactive
sessions still default to Legacy.
Full Changelog: v1.3.2...v1.3.3
v1.3.2
Added
Fine-Grained Password Policies (PSO) check - flags 'msDS-PasswordSettings' objects weaker than the default domain policy; escalates when linked to a privileged principal.
Print Spooler on Domain Controllers check - detects the Print Spooler (MS-PRN / PrinterBug) on DCs via NetExec; coercion --> ESC8/RBCD/unconstrained relay.
WebClient (WebDAV) Coercion Surface check - sweeps hosts for the WebClient service (HTTP coercion -> ESC8/LDAP relay).
First unit test suite ('tests/').
Check count: 40 --> 43.
Full changelog: https://github.com/dehobbs/ADScan/blob/v1.3.2/CHANGELOG.md
ADScan v1.3.1
Highlights
-
Plaintext-password leak in the redacted customer report — fixed. The "Passwords Found in Privileged Account Description Fields" finding in
check_privileged_accounts.pywas populating itsdetailslist with<sam>: <description>strings, where the description body is the leaked credential. The finding never set adetails_redactedcompanion list, solib/report.py:_get_details(redact=True)fell through and rendered the plaintext into the redacted customer report. The finding now provides bothdetails(operator) anddetails_redacted(customer), so passwords no longer appear in the default report when--unredactedis not specified. Every other check that handles credential material was audited; only this one was leaking. -
CLI help layout. The
--timeoutflag was registered under the Output argument group, so it appeared next to report-path and log-file flags. It is a connection-level setting like--protocol,--dns-server, and--dns-tcp, so it now lives at the bottom of the Target group where it belongs. Functional behaviour is unchanged; only the help layout shifts. -
CLI Reference completeness. Four flags that existed in
adscan.pybut were missing from the README's CLI Reference tables are now listed there:--dns-server/-ns,--dns-tcp,--unredacted, and-V/--version. The--timeoutrow was also tightened to mention its dual role as the LDAP receive-timeout used by the stall detector introduced in v1.3.0.
Install (existing users)
Pipx users:
pipx install --force git+https://github.com/dehobbs/ADScan.git@v1.3.1
adscan --setup-tools
Editable clone:
git pull origin main
pip install -e
ADScan v1.2.0
ADScan v1.2.0
Highlights
-
One-line install via pipx
pipx install git+https://github.com/dehobbs/ADScan.git adscan --setup-toolssetup-tools now bootstraps uv itself when it is not already on PATH, then provisions every external CLI tool into its own isolated virtual environment.
-
BloodHound engine selector. When the BloodHound step starts, you are prompted to choose between Legacy BloodHound (bloodhound-python) and BloodHound Community Edition (bloodhound-ce-python). Both ingestors install via uv tool install. Non-interactive sessions default to Legacy.
-
Kerberos works against arbitrary lab DCs. ADScan now synthesizes a usable krb5.conf on the fly when the host system has none or omits a default realm, and resolves the DC FQDN via SRV when you pass an IP for dc-ip so GSSAPI builds the correct service principal name.
-
Pre-Windows 2000 computer accounts check rewritten. The check no longer depends on the standalone pre2k binary; it invokes the NetExec pre2k LDAP module instead and parses both the pre-created and the verified-vulnerable account sets.
-
ADCS check expanded. The Certipy phase is now joined by a NetExec adcs module phase. Certipy retains priority for any ESC class it reports; NetExec fills in gaps. The legacy LDAP-only checks are muted by default.
Authentication
- Synthesize a temp krb5.conf when Kerberos is requested and none is configured (deleted at process exit).
- Resolve the DC FQDN via SRV when dc-ip is an IP, then patch the in-process DNS resolver so the FQDN routes to the original IP. Subsequent ldap3 and impacket calls build SPNs as ldap or cifs slash FQDN, which Active Directory actually has registered.
- pre2k auth path now supports Kerberos cleanly and no longer falls through to an empty password when no credential material is available.
Reports and UX
- Spinner is suspended for the duration of any interactive prompt so the elapsed-time counter never overwrites the question.
- MATCH_KEYS for verify_pre2k and verify_pre_windows_2000 disambiguated; each check's findings now route to the correct verification module regardless of import order.
- Comprehensive developer reference added at docs/REFERENCE.md.
Cleanup
- Removed the standalone pre2k entry from the tool registry (NetExec covers the same surface area).
- Dropped the unsupported BloodHound op flag for bloodhound-python 1.6 plus.
- README, pyproject, requirements: install instructions consolidated, Git prerequisite removed.
Install (existing users)
If you previously installed by clone, pull main and re-run pip install. If you want the new pipx workflow:
pipx install git+https://github.com/dehobbs/ADScan.git@v1.2.0
adscan --setup-tools
Pinning to v1.2.0 gives you a reproducible install rather than tracking main.