Skip to content

v13.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 10 Oct 21:13

Added

  • ENS is now scored against a scope the client declares (profile plus the level of each of the five security dimensions), with the category derived from it, instead of an assumed category. A measure the scope does not require, or one met by a compensatory measure, is reported with the article behind it and sits outside the score. The CCN-STIC 890A and 890C profiles use their own applicability tables. Declarable from the workbench, the Enterprise platform, or adscan execute compliance_scope.
  • Both reports and the Enterprise platform now state how long the assessment took, and how long it took to reach full domain control. The two are labelled apart, and a run that reached no domain compromise makes no such claim rather than showing a zero.
  • Recovered NT hashes are now cracked locally against ADscan's corpus before the scan moves on, under a time budget you pick from estimates measured on your hardware. It takes the hashes the breach lookup never saw or could not reach, which used to go untested. GPU cracking also now works in adscan ci and adscan execute, not only in the interactive workbench. ADSCAN_NO_LOCAL_CRACKING=1 opts out.
  • The Client Deliverable Kit now includes an AD Password Hygiene Report whenever credential recovery ran: recovery rate, coverage per privilege tier, and the groups of accounts sharing a password, with native remediation. It never prints a recovered password, and is absent rather than reporting a clean result when no recovery was attempted. The Enterprise platform serves the same analysis.
  • Both reports now carry an Endpoint Defense section: which hosts were examined for antivirus and endpoint detection, what was observed, and what the credential-extraction techniques did where a product was active. It publishes no coverage percentage, since protection is only examined on hosts a technique needed to reach, and states the unexamined hosts as their own figure. Installed-but-not-running is reported apart from absent, and a Tier 0 host as its own figure rather than averaged in with a laptop. The kit adds endpoint_defense_appendix.csv; the platform serves the same view.
  • Every credential dump now shows the host's endpoint-protection posture before it runs, not only dump_lsass, and records which method recovered the credentials: the in-memory read or the hive-export fallback. Those are different answers for a SOC, since the first leaves no disk artifact. Nothing detected is never presented as a host having no protection.
  • ADCS ESC15 (EKUwu, CVE-2024-49019) gained a Schannel route that needs only the one vulnerable template, where the original needs a second template accepting an enrollment agent. ADscan tries it first where the directory answers over LDAPS and falls back otherwise; an operator can force either.
  • Three new findings: Certighost (CVE-2026-54121), where an unpatched Certificate Authority still exposing the domain-controller chase fallback lets a standard user obtain a certificate that authenticates as a domain controller, detected read-only without requesting one; a decommissioned Certificate Authority still trusted for authentication, whose certificate left in NTAuthCertificates keeps domain controllers accepting the logon certificates it issued; and unconstrained Kerberos delegation on a non-domain-controller, listing each affected host.
  • Deliverables can carry your own branding: adscan deliver --branding {adscan,cobrand,whitelabel} co-brands or removes the ADscan mark, and --client-cover, --client-back and --client-logo supply your own cover, closing page and per-page logo. The Security Assessment Report is also written as HTML beside the PDF, --theme <file.css> applies your own stylesheet, and --emit data writes report_model.json, a branding-neutral export of the report's data.
  • adscan execute can now run the credential dumps without the workbench: dump_lsa, dump_sam, dump_lsass, dump_dpapi, dump_registries and dump_host, each with its own target and credentials.
  • LDAP channel binding is now assessed over StartTLS where a domain controller firewalls LDAPS, so enforcement is reported as Required or Not enforced instead of Unknown.

Changed

  • Every client surface now counts findings by the rating the report tells you to plan from. The counts totalled what a technique is worth in any directory while the cards, compliance verdicts and platform showed what this assessment observed in yours, so one scan read "0 Critical" on its cover and a different count in the platform. The baseline band is still published beside each finding, with the method behind both grades.
  • Client deliverables no longer print a CVSS score. Only 17 of the 93 finding types map to a published CVSS vector, so the rest were rated with a decimal nobody could recompute; a methodology annex now states how ADscan's own severity is produced. ADSCAN_REPORT_CVSS_BASE=1 prints the Base score beside its vector for a tender that requires it by contract, and a named CVE keeps its NVD score. Compliance verdicts across all six frameworks now read the severity band: verified over 610 requirements, no verdict changed.
  • ADCS ESC15, ESC9 and ESC10 are now actively confirmed during collection instead of inferred from template attributes. Each depends on the authority's patch state or the controllers' certificate-binding enforcement, neither readable over LDAP, so the findings used to ship as flat criticals that were false positives on a hardened environment. ADscan enrolls one self-subject certificate and inspects the result, minting no privileged identity: a hardened environment withdraws the finding and records a verified control, and a check that could not run says so. ADSCAN_NO_ESC15_CONFIRM=1 and ADSCAN_NO_ESC9_CONFIRM=1 skip the issuance.
  • Relationship and ACL findings (excessive control rights, delegation, DCSync, ADCS enrollment) now fire only where the right crosses a privilege tier upward or a forest trust, so the report lists real tier-crossing exposures instead of thousands of same-tier rights that only shape an attack path. The excessive rights are consolidated into one "Excessive Rights Across a Tier Boundary" finding naming each crossing.
  • Finding Affected Assets now name the object that carries each weakness and the object to remediate, not just where a path ends: DCSync names the account holding the replication right, roasting labels each account cracked, attempted or exposed, and staleness findings show the measured password age or OS version. Every asset carries its privilege tier so the most critical are first. "Domain Admin Sessions" is now "Privileged Sessions on Lower-Tier Hosts".
  • The compliance framework is now an explicit choice for an audit engagement, never one ADscan picks. adscan ci --generate-report used to default to ENS, so a client regulated under DORA or PCI DSS could receive a verdict against a regime they are not subject to. An audit run asks for --frameworks and refuses to render without one; a CTF or lab run is never asked; and a report with no mapping says so instead of omitting the section silently.
  • The lab writeup is now a practice-target artifact only, produced on no automatic audit path including adscan ci: it was the one place a run wrote every recovered secret in cleartext. adscan writeup on an audit workspace still gives the evidence spine as an engagement record, with secrets replaced by their shape; --full-credentials gives the full table. It also tells one timestamped story per attack path actually walked, replayed from the execution record: two walked paths used to be fused into one chain whose own timestamps refuted it, and could state neither path's duration.
  • Credential recovery now reports coverage against the four privilege tiers the rest of the product uses, so a Tier 1 server or application admin is no longer counted as standard. Tier 0 is split between accounts controlling the domain directly and accounts one technique away. An account that could not be placed reads "Not graded" on its own row.
  • Local password recovery now asks about a stage that will not finish in the time it has, instead of stopping it quietly. Where the measured estimate exceeds the time left you can give it the time, skip it, hand it to a background job, or let it stop early knowingly. Every outcome but letting it finish still reports a test that stopped before working through the candidate set. An unattended run is never asked.
  • The spray eligibility panel now accounts for every name as a funnel: listed, skipped because the engagement already owns them, held back for lockout safety, and actually sprayed. A domain of 186 users read "1 eligible / 9 total" with no way to find the other 177. Spraying a domain you already own is also your decision now rather than a silent refusal, with the user-side spray defaulting to No. Nothing about what gets sprayed has changed, and lockout safety is unchanged.
  • A password candidate found in an LDAP attribute or a share file is now shown inside the text it came from, with the matched span highlighted and the detector rule named. A twelve-character string is a leaked password or a ticket reference depending entirely on the sentence around it, and that sentence was discarded. Long values are windowed around the match so the candidate cannot be clipped out of its own evidence.
  • explain now answers "what will my SOC see" for every technique, and says so plainly where the answer is nothing. Fifteen techniques had no detection section, so a reader could not tell an undocumented technique from a silent one.
  • An attack step that ran but did not complete now states the specific reason instead of a bare "stopped here": a roast whose hash was captured but not cracked reads as attempted with the hash in hand, not as a never-executed theoretical step. The underlying weakness keeps its own severity regardless.
  • Each of the two account figures on the report's exposure page now states which accounts it counts. Both numbers are unchanged, but read one under the other they said "nobody is exposed" and then "everybody is exposed". Where no account reaches a Tier 0 host, the page says that instead of describing reach that is not there.
  • Constrained Kerberos delegation is now rated by its abuse power, with protocol-transition ranked above Kerberos-only, and a configured resource-based delegation trust is its own backdoor-review finding, separate from the write right that can set it.
  • The Enterprise platform's compliance view now shows a control awaiting your confirmation as its own state, with its own colour, filter and count, instead of displaying it as conformant. These sit outside the score until you answer.

Fixed

  • The ADCS ESC14 (altSecurityIdentities) routes now execute to compromise instead of erroring out. Steps authenticate as the controlled target rather than the wrong identity, terminate at the account actually compromised rather than over-reporting Domain Admins, and remove the machine account they create, which an ordinary impersonated account could not delete. The finding is reported wherever a principal can write a target's mapping and enroll, not only where a specific vulnerable template existed, and no longer surfaces guest and default accounts as targets. Template selection is automatic, as for ESC1 and ESC2.
  • ADCS ESC4, ESC6 and ESC7 now reach domain compromise on domain controllers enforcing strong certificate binding (KB5014754), where they previously aborted: the impersonated account's security identifier is embedded during enrollment, as it already was for ESC1, ESC3 and ESC13. An ESC9 or ESC10 step against such a controller now reports the honest outcome, that the escalation is not viable, and records the refusal as a verified control rather than a cryptic failure.
  • A finding's rating no longer depends on which deployment, render or page is reading it. The scan records the rating it computed, so the platform reports what the assessment decided instead of deriving it again: in an appliance deployment the 76 finding types with no CVSS vector all resolved to zero and displayed real findings as Informational, and a finding counted Critical on the dashboard could open as High on its own page. The first report from a fresh workspace also counts what the scan found, so generating it once and twice give the same figures.
  • A finding affecting a Tier 0 account is now rated as one, in the finding and in every finding derived from a proven attack step. The overlay reads the privilege tier the assessment stamped on each affected asset, so an account holding the domain through control-plane group membership counts as Tier 0 the way the report's own legend says. It was reading a field nothing writes and an older boolean blind to membership, so a privileged account's exposed password rated the same as an ordinary user's.
  • Client-facing figures and headings now describe what they are. The cover no longer calls its severity counts a baseline distribution, the remediation roadmap's attack-path row no longer prints a hand-typed 9.8 and the word Critical that no grading produced, a route with no title is named by its two ends instead of "Attack Path: Attack Path", and the severity methodology no longer lists a condition that cannot raise a grade. The free report now shows both figures behind each grade, which its own scoring section had promised and no card carried.
  • The Start Here work order now states what the order is, once. It was described four ways in the paid report and three in the free one, two still saying the list leads with what ADscan proved, which stopped being true when proof became a marker rather than the sort key. Every surface now reads one sentence: containment first, then by how many attack paths each fix closes, cheapest first on a tie. The order itself has not changed.
  • A report now discloses credential material the assessment took out of the environment, and every file it wrote on your machines. The containment section states what left, what was in it, where it went and what that obliges, with the day to search your own logs. A process dump, saved hive or uploaded helper is reported either as deleted with the removal confirmed or as still present with the command to delete it; previously these appeared in no deliverable at all. Where the directory database itself was copied it says so, krbtgt included, with the double reset that stops a forged ticket outliving the rotations.
  • The cleanup record now covers every change an attack-path step makes. Six steps undid their own work through a private path the record never saw, among them creating an account and adding it to Domain Admins, granting full control over an object, and overwriting a logon script. Each is recorded as made and verified when reversed, and a change left undone when a session ends is reported as needing manual cleanup with the native command. Two renders of the same assessment can also no longer disagree about whether the directory was modified.
  • Every object a remediation command names is now the real object the finding pinned or a visible fill-in. Three commands in one kit named objects the client's directory did not contain, and one left an account slot blank on a page whose own affected-assets block named it. A command meant to be pasted now takes the share, file, account and host from the assessment, with an angle-bracket fill-in only where the choice is genuinely the client's.
  • Reports no longer credit a control ADscan did not observe, or let an absent result read as reassurance. A replication right read from the directory but not exercisable, because the protocol needed ports the assessment's position could not reach, is reported as present and attributed, with a statement that this is not evidence the controller refuses replication. An ADCS finding whose authority was unreachable asks the two questions that are the client's to answer, and stays a declared data gap.
  • A containment instruction now says which clock its instant came from. ADscan synchronises the assessing machine's clock with the domain controller mid-run, so an instant recorded after that belongs to the controller's clock, which is the one its Security log is written in. Where nothing places an instant in any clock, the report points at the assessment window instead of naming a moment the client cannot find, and it no longer reads an empty log search as proof that object-access auditing is disabled.
  • A group membership obtained during a scan is now always visible to attack-path search. When a step added a principal to a group, the engine could keep answering from the membership picture held before that write, so a later step depending on it was reported unavailable: coverage lost in the one direction that matters, because it understates what an attacker can reach.
  • A yes/no confirmation now always returns the answer you gave it. The prompt layer could resolve a confirmation to its own default without reading your reply and without saying anything on screen, which on a prompt defaulting to yes meant proceeding without consent. Where there is genuinely no terminal, as in adscan ci, the documented default applies as before.
  • Credential dumps now complete in several cases where they used to fail. A dump a just-proven access step unlocked is no longer refused with a message telling you to obtain the host's machine account first, which is the very thing the dump recovers. The Backup Operators escalation reads a domain controller's SAM and LSA secrets in place again, and now without writing anything to disk, so it leaves no file for an endpoint product to find. A read interrupted on every attempt is recognised however the failure surfaces, so the dump keeps its fallback instead of stopping on a bare SMB error. And dumps, remote registry and service control now succeed against servers requiring SMB3 encryption, the default from Windows Server 2016 onward.
  • Where an endpoint product was independently confirmed active, a read interrupted on every retry is now assessed as that product interrupting it, with the basis stated and the host and window given so you can confirm it in your own console. Where none was confirmed, the interruption is reported without attributing it to anything, because a transient fault looks identical. The assessment never claims the attack was blocked: in several of these cases the credentials came out anyway. The observation also reaches the platform's attack-step panel for all four dump techniques, DPAPI included.
  • Recovered credentials are no longer lost, mis-ranked or mis-attributed. A second, narrowly scoped DCSync run no longer rewrites the domain's register from scratch, so a full replication of several thousand accounts is not left holding one entry. Recovering a cleartext no longer discards the NT hash, so pass-the-hash and Kerberos reuse stay available; a scraped candidate no longer outranks replicated key material; a credential in DOMAIN\user form no longer fails verification with a parsing error; and a password recovered by breach lookup is credited to the lookup rather than claiming replication returned it.
  • Accounts your team has already deleted no longer count as part of the enabled user population. A deleted object keeps the flags it had when removed, so every figure built on that population inherited them: account totals, the spray candidate list, password-policy and stale-account findings, and the denominator under the exposure percentages. On one engagement seven of the nine accounts a spray reported as its population were deleted. They are now counted separately, so your deletions read as the remediation they are.
  • Cracking time estimates are now measured, and never quoted from a reading taken under contention or by an older method. The figure came from a synthetic benchmark that overstated real speed by 1.7 to 15.5 times and ignored how many hashes were loaded, so fifty salted accounts were quoted as one. A tier is now planned from a short real attack in the configuration the crack will run, the graphics card is reserved per machine rather than per session, and a reading taken without the card to itself falls back to the calibrated figure, labelled provisional. The password-hygiene figures are brought up to date when a background attack finishes, so a report no longer states two of fifty passwords fell where thirty did.
  • A host whose graphics driver was upgraded while the previous version was still loaded no longer kills the scan before it starts. The run used to end on container internals about a missing socket, naming neither cause nor fix, for a card only password cracking wanted. ADscan now checks the driver answers and otherwise runs without it, naming the loaded version, that the fix is to restart, and that captured hashes are still reported for cracking offline.
  • A password written beside a misspelled or abbreviated label is now reported, in an account's description and in share files alike. A service account whose description read "Psswd: " followed by its password went unreported, because detection ran only the rules understanding correctly spelled labels. The vocabulary now covers the forms people actually type, in English and Spanish. Dates, job titles, reminders that merely mention a password, and the shapes that resemble one are still left alone.
  • A credential found in a readable share now names the account it belongs to, when the file states it beside the secret, so a password belonging to an account one step from domain control is no longer rated like an ordinary user's and the rotation command can name what to reset. A secret with no owner named nearby is still reported as the file alone, because sending a client to rotate the wrong account leaves the exposed one live.
  • An attack step now names the account that acted, not the group it belongs to. Where the privilege comes from a group or a broad identity such as Authenticated Users, that collective sat in the acting principal's slot, so one sentence told a client that Backup Operators controls its own member and another credited a recovered credential to every authenticated user in the domain. Where no single account can be identified the sentence says a member of that group.
  • By-design Tier 0 rights are no longer reported as client vulnerabilities. A principal already Tier 0 administering its own PKI, NT AUTHORITY\SYSTEM and the machine service identities holding full control over directory objects, the built-in Exchange self-management entries beside real Force Change Password findings, and an Azure AD Connect sync account's replication right are each classified as Tier 0 hardening items instead. A genuine cross-forest escalation from a Tier 0 principal is still reported. A certificate template localized in the directory's own language is also no longer listed twice.
  • The standard-user exposure figure no longer counts routes running only through a file-share access right, such as an over-broad share ACL on a domain controller. Share access is reported as its own exposure finding, not a compromise route, so the exposure figures and choke-point blast radius match the validated attack-path set.
  • A route ADscan confirmed and deliberately did not execute, because running it would have disrupted production, is now its own figure rather than counted among paths found by configuration analysis. Its card reads Not Executed for Safety rather than Theoretical, and says whether the withheld step was the route's last or sat mid-chain. The summary states what was withheld and that the decision was ADscan's own: it is never presented as a control in your environment having stopped the attack.
  • A report no longer declares route discovery was sampled when it completed, nor prints two different numbers for its own "routes to full domain compromise" headline. The coverage statement is written by the computation that produced the routes, and reachable Tier 0 assets are shown as a separately labelled figure. The end-of-run panel also no longer reports "no paths found" where routes were identified and simply not walked end to end.
  • A direct member of Backup Operators, DnsAdmins or Print Operators now shows the full validated route to domain compromise instead of one that stopped at the group.
  • Client Deliverable Kits no longer collide or carry stale documents. Two kits built from one workspace on the same day collapsed into one, the second overwriting the first, with the platform serving the newer file under the older kit's name. A kit now carries the time it was built, keeps its own index, stays downloadable after a later one, and contains only what that run produced. A deliverable that cannot be produced fails the run and names itself, and a document whose client-specific half is missing opens by stating it is incomplete, with the operator warned before the kit is handed over.
  • The AD Control Coverage Report no longer denies or misplaces observations the same kit reports. It stated the run produced no observed-good reading at all, which was false on any run that recorded some, while the compliance section marked controls conformant off exactly those readings. It now says how many were recorded and where, and lists them itself when no regime is selected. It also states its ENS coverage from the same declaration the Security Assessment Report uses, so one kit never carries two denominators.
  • ENS conformance is now stated against the measures your system is actually audited on. Four measures carried the wrong level and would each have produced a false non-conformity for a system certifying at the lowest category: op.acc.5, op.acc.6, mp.com.2 and mp.com.3 were marked MEDIA and are required from the lowest level. A workspace declaring no scope is assessed against the measures required at every category, and says so, rather than being assumed to be at MEDIA.
  • The Enterprise platform's Defensive Posture figures no longer report a host as unprotected when its posture could not be determined. A probe that did not complete produced the same empty result as a host with nothing installed, so an unmeasured domain controller was listed as a Tier 0 asset without endpoint protection: a finding about the most critical asset in the estate the evidence did not support. Such hosts are now their own figure and left out of the coverage rate.
  • The Enterprise platform and the AD Hardening Playbook now carry the Start Here work order and the Most Exposed Accounts ranking for a domain whose report came from the free CLI. Both derive from attack paths only a paid run had to hand, so a free-tier report recorded neither and the Playbook dropped the domain without saying why. A domain that genuinely has no attack paths records that explicitly, so an uncomputed ranking cannot read as an empty one.
  • adscan writeup no longer contradicts itself about whether the domain fell, and carries the chain the scan proved. On a run that owned the domain the summary read "none of them end to end" while two sections below reported a path reaching full domain compromise. Where the executor's log held less than the attack graph, the document narrated the log, drawing the single hop that failed and never mentioning the three techniques that worked. It now leads with the same verdict the rest of the product reports, attributes the compromise to the one path that proved it, states the time from no credentials to full domain control, and says plainly when the run changed nothing.
  • The free exposure report's attack-path step list now names the same techniques as the rest of the product: a step abusing a logged-on user session is narrated as the technique it is instead of dropped from the route, and a step that only records a precondition of the environment no longer appears as something that was run.
  • DPAPI credential extraction now also recovers Scheduled Task and service-account secrets under the SYSTEM, LocalService and NetworkService profiles, so entries saved by a task running "whether user is logged on or not" are no longer missed.
  • Messages that tell you to run a command now name one that exists. adscan posture probe <domain> was printed in fourteen places but posture is a workbench command typed on its own, and a pending-rollback warning pointed at adscan cleanup hassession, which has never existed. -v also now works wherever --verbose does, before or after the subcommand.
  • The sample kit adscan demo hands you now carries the documents the product ships. Baked by hand in May, it still offered an "Executive Assessment Report", a standalone MITRE Remediation Checklist folded into the main report months ago, and a renamed "Coverage Matrix", so a new operator's first look was three filenames that no longer exist. The demo kit and the published example report are now both rendered by the delivery pipeline itself.