Skip to content

v13.0.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 20:00
· 2 commits to main since this release

Added

  • Zero-credential attack paths now begin at an explicit "Unauthenticated (null session)" entry
    step. The kill chain reads from the no-credential start, through the account it derived, all the
    way to full domain compromise, instead of silently starting mid-chain as if the attacker were
    already logged in. It is flagged "Executable without credentials, confirmed" and sorts to the top
    of the attack-path list, and ADscan can now execute such a path end to end straight from that
    entry instead of stalling with "no starting point you control". The recovered-credential finding
    behind the entry is rated by its proven context. It is Critical when the no-credential chain
    reaches full domain compromise, so a run that proves a zero-credential takeover no longer reports
    zero critical findings. The explanation stays honest about the mechanism: the file is reachable
    because the server permits null-session access to that share, not because an anonymous permission
    sits on it. The finding names the principals with measured read access and the null/guest session
    as an access vector, so the full remediable picture lives in the finding itself.
  • A domain controller that accepts an unauthenticated anonymous LDAP bind is now a first-class
    "LDAP Anonymous Bind Enabled" finding with native remediation: disable anonymous operations via
    dsHeuristics, strip the Anonymous Logon read grants, each with a before/after check and a
    validation bind that should now fail. Because it needs no credential to begin, it leads the
    0-30 day remediation roadmap.
  • On hosts where the scan account is a local administrator, collection now reads six host-local
    credential-protection settings over the same session and flags the weak ones: LSASS not running
    protected (RunAsPPL), WDigest cleartext caching, LM hash storage, a weak LAN Manager auth level,
    weak minimum NTLM session security, and custom Security Support Providers allowed into LSASS. Each
    carries native GPO/registry remediation and a Get-ItemProperty validation step. A non-admin host
    is skipped at no cost.
  • A new configuration check flags a domain (or fine-grained password policy) that stores passwords
    with reversible encryption, recoverable to cleartext, with native remediation and validation.
  • The compliance scorecard now includes the controls ADscan verified good, where before it listed
    only the broken ones. When ADscan reads a hardening setting and observes it correctly configured (passwords not stored reversibly, a
    machine-account quota of zero, hosts that refuse SMBv1 to a live negotiate probe), the mapped
    control is marked conformant across all six frameworks with the reading as evidence. Only a
    definitive observation greens a control; a setting ADscan could not read stays "not assessed"
    rather than assumed compliant.
  • Compliance reports can now map findings to the CIS Microsoft Windows Server Benchmark, selectable
    alongside ENS, NIS2, ISO 27001, DORA and PCI DSS. Each executed path or validated finding is tied
    to the specific CIS control the environment deviates from, version-aware to each affected host's
    actual Windows release (Server 2016/2019/2022/2025, Windows 10/11), and shown in both the report
    and the platform. It is presented as a technical hardening baseline, kept apart from the regulatory
    frameworks, and makes no certification claim.
  • The learning mode now teaches the full technique set it executes: ADCS ESC2 through ESC17, the
    coercion and relay techniques (PetitPotam, PrinterBug, DFSCoerce, coerce-and-relay to ADCS), the
    named CVEs (Zerologon, noPac, EternalBlue, PrintNightmare), the lateral-movement and access
    techniques, the DCSync and secret-dump primitives, the ACL-abuse and delegation escalations, and
    the MSSQL escalations. Each renders a full teaching card before it runs, and on demand through the
    explain command: what the weakness is and why it works, the by-hand command, the MITRE ATT&CK
    mapping and detection events, a native check, and remediation. These techniques previously
    executed but taught nothing.
  • Reports and the CLI now show which non-privileged accounts can reach a Tier-0 asset (a domain
    controller, an ADCS certification authority, an Exchange server) and by what means: full local
    administrator, a remote session, or a database role, with the share of the domain that holds such
    access. It distinguishes what an account is granted from what it can reach. An ordinary account
    with a path onto a domain controller stays an ordinary account, and the finding is that it can
    reach the control plane at all.
  • Attack paths can now be queried to one named target from the REPL. The attack_paths command
    takes a --target "Domain Admins" flag (a group, a host, or an OU) and shows only the validated
    routes that reach that object, resolving the name to its canonical graph label and listing the
    closest objects when a target does not match, instead of returning an empty result.
  • Attack-path discovery shows a pre-flight panel before it runs: the graph's node and edge scale,
    the control hubs driving the density, and whether discovery will run in sampled mode on a large,
    dense directory. A new graph_stats command shows the same summary on demand and adscan ci
    prints a one-line version. It reads the already-computed graph, so it is instant.
  • Attack-path results now persist per workspace, so reopening a workspace or a fresh adscan ci run
    reuses the prior path set instead of recomputing the full discovery pass when nothing in the
    directory changed. The cached set is dropped the moment the graph changes, so a stale set is never
    served, and it is skipped under --no-cache.

Changed

  • adscan ci (autonomous, non-interactive scanning) is now a PRO capability. The free LITE tier
    keeps the full interactive adscan start workflow on every platform; automation and unattended /
    CI runs are part of PRO. adscan ci is no longer marked beta.
  • The minimum supported Python is now 3.10 (was 3.9). Field telemetry shows no one running ADscan on
    3.9. The lowest version in use is 3.10, so the 3.9 floor was carrying maintenance cost for an
    audience that no longer exists.
  • Privilege-tier classification now recognizes the full Tier 0 control-plane set consistently across
    the report and the platform, from one authored source. Group Policy Creator Owners, DnsAdmins, the
    Exchange privileged groups, the read-only Domain Controller groups, Cryptographic Operators, and
    the Certification Authority and its templates are all graded Tier 0 wherever a tier is shown, and a
    Domain Admins member is graded Tier 0 by its membership rather than by name alone. The report's
    tier legend now states why each Tier 0 group is classified there, including the groups flagged
    Tier 0 for parity with industry tooling despite no known single-step technique, and shows the exact
    tier ("Tier 0: Domain Control", "Tier 0: Escalation-capable", "Tier 1: Server / Application Admin")
    in place of a coarse "High Value" badge.
  • Member servers and accounts are now tiered by what they actually do, beyond their operating system
    or group membership. A Remote Desktop or Citrix host where ordinary users log on is Tier 2; a jump
    box, hypervisor or backup agent that administers a Tier 0 asset is raised to Tier 0; a SQL,
    Exchange or SharePoint host is recognised as an application server; and an account with local
    administrator (or SQL sysadmin) rights over a Tier 1 server is itself Tier 1. Every Tier 1 verdict
    records how it was inferred, and the report states that Tier 1 is heuristic and
    customer-overridable while Tier 0 is derived deterministically.
  • A credential found in a file on a share (a Group Policy Preferences password, a recovered
    SecureString, a spidered secret) is now attributed in the attack graph to the principals that can
    actually read that share, the measured share-ACL and file-NTFS read set, in place of the account
    that happened to recover it. The report and the platform now agree on who could reach the exposed
    secret whether ADscan reached it unauthenticated or with credentials. Each attribution states its
    verification level: read access confirmed live, share and file NTFS both evaluated, or share-level
    access only with the file's NTFS unverified, so an auditor sees which attributions are proven and
    which are a lead.
  • The Security Assessment Report reads as one finding, rather than a tool dump, when a dense domain
    produces dozens of near-identical attack paths that share one root cause. Routes that begin the
    same way and hit the same over-broad grant are grouped, the structurally-distinct examples shown
    in full and the rest folded into a compact "Tier 0 objects reachable by this same chain" table
    (one fix closes them all). The attack-graph diagrams also draw every interchangeable pivot behind
    a finding, each colored by whether that route was proven (green), attempted (amber) or theoretical
    (grey), so the reader sees the full set of ways in without the finding list exploding.
  • The free exposure report now reads as a complete assessment. The executive page leads with a
    labelled exposure figure (the share of accounts with a validated path to Tier 0) set beside the
    posture score with each figure's direction spelled out, a green "attack surface already reduced"
    callout naming the attacker avenues your own configuration already closes, and a compact Tier 0/1/2
    legend that makes the direct-versus-escalation-capable split explicit for an auditor.
  • The Force Change Password finding now separates expected Exchange self-management from genuinely
    over-scoped delegation. The Exchange management groups resetting their own system mailboxes fold
    into one annotated row, the human and service accounts that matter stay itemized, and the finding
    text names the distinction, so an Exchange-aware reader no longer dismisses a real over-scoped
    grant as background noise.
  • Offline mode now also skips the launcher and runtime version check, so an air-gapped run makes no
    call to PyPI or Docker Hub. --no-update-check now also accepts --no-update as an alias.
  • When a bundled tool fails to start because the machine's CPU lacks the x86-64-v2 baseline NumPy 2.x
    requires (common in a VM whose hypervisor exposes a generic CPU model), the startup check and the
    credential scan now name the real cause and the fix (give the guest the host CPU, -cpu host) in
    place of a raw NumPy baseline traceback that reads like a broken install. Credential scanning then
    degrades cleanly as an honest coverage gap and the scan continues.

Fixed

  • The report and the writeup now quote the same attack-path total, so a report can no longer read
    "closes all 42 paths" one page from a headline of "43". Both documents lead with the one validated
    inventory figure the exposure score already uses. The recovered-secret count is reconciled the same
    way: when the krbtgt key is among the recovered secrets, both documents footnote that the count
    includes it, so the credentials table and the writeup ledger never present two different totals.
  • Principal and group names now read the way a consultant writes them across the report, the writeup
    and the attack-path diagram: an account renders as michael.wrightson and a group as
    Backup Operators, in place of a shouting MICHAEL.WRIGHTSON@CICADA.HTB login string, a raw SID,
    or an internal placeholder, and well-known identities keep their proper names. A principal in a
    different domain still shows its domain, so a cross-forest hop stays clear.
  • Remediation and verification commands in the report and the playbook now carry the environment's
    real identifiers. An NTAccount/dsacls principal is written with the real NetBIOS name (for
    example HTB\Account Operators) in place of an unfilled placeholder or the DNS form Windows
    rejects, and every "verify this finding independently" command uses the object's real
    sAMAccountName, distinguished name or hostname rather than the display label, so a command a
    sysadmin pastes resolves the object instead of silently matching nothing.
  • The report's executive summary no longer contradicts itself. The Compromise Reach cards now add up
    to the total attack-path count shown above them, the exposure gauge matches the same
    validated-exposure figure quoted elsewhere, the candidate routes discovery evaluated are named
    separately from the deduplicated paths the report presents (so two counts never share the word
    "route"), and the page leads with a single headline figure and states why findings rated Medium in
    isolation drive a Critical posture. Every count and score is unchanged; the page now explains them.
  • Attack paths whose opening step ADscan actually executed now read as partially validated (or fully
    validated when the whole chain ran) in the report and the platform, in place of merely theoretical.
    The proof of that first step was being recorded against a separate representation of the same
    account and lost when the report re-derived the path. A route with no successful step still reads
    as theoretical.
  • The free exposure report no longer overstates its evidence relative to the paid report. A route to
    full domain compromise that was mapped but not walked end to end now reads "a mapped path to full
    domain compromise whose entry step is proven" rather than "a validated path", and the free and paid
    reports now derive the same headline figures from one source: the share of accounts with a path to
    Tier 0 (previously blank in the free report) and the count of attacker avenues the environment
    already closes are computed once and read by both.
  • A readable share reached over a null or guest SMB session now reports its actual authorized-reader
    list, read straight from the folder's security descriptor, in place of a lower-confidence inferred
    placeholder, so findings sourced from such a share cite the real principals with measured read
    access.
  • A valid computer-account credential is no longer reported as invalid when the domain controller
    enforces AES Kerberos with a non-default salt; the check derives the machine-account key correctly
    and confirms the credential over RC4/NTLM before rejecting it. The authenticated scan also no longer
    prints a raw multi-line trace when only the Kerberos ticket step fails but the scan continues over
    NTLM, and no longer implies a valid credential was rejected in that case.
  • The important-port scan is far faster on large domains. It previously retried each unreachable host
    up to ten times, so a domain with many stale or powered-off computer accounts spent most of the
    scan waiting on hosts that no longer exist. It now gives up on a non-responding host after a few
    tries and caps the time spent per host, so a scan of a thousand mostly-stale hosts finishes in
    minutes instead of over an hour, with identical results on the hosts that are up. The scan stays
    gentle by default (no increased packet rate against live hosts); operators who own the network can
    opt into faster timing with the ADSCAN_PORTSCAN_NMAP_* variables.
  • Opening and working in a workspace for a large domain is far faster. The terminal no longer stalls
    and drips output line by line while loading a directory with thousands of accounts and computers.
    The slowdown grew with the size of the domain, so the biggest environments were the worst affected;
    a large lab that took over a minute to open now opens in a couple of seconds.
  • Attack-path discovery on a large or dense directory no longer exhausts memory or gets killed. The
    result cache is now bounded by actual memory rather than a blind fixed path count, and on the
    native Windows build (which has no container cgroup) discovery reads the host's real memory limit
    and free memory, so a big run stops cleanly with a clear message instead of being killed. What
    ADscan computes and serves is unchanged.
  • Password cracking no longer fails when a previous cracking run is still active; each run uses its
    own session so concurrent or leftover runs do not block a new one.
  • adscan ci and other scans no longer abort at preflight when the bundled credential-scanning tool
    is a newer build than expected; the version check now matches the shipped tool.