63 min read

The Twenty-Year Local Admin Password Crisis: From GPP cpassword to Windows LAPS

Microsoft published the AES key that "protected" Group Policy Preferences passwords. Twelve years later, MS14-025 still has not deleted the artefacts. Here is how Windows LAPS finally fixed the architecture -- and what it still cannot solve.

Permalink

1. One Password, Fifty Thousand Laptops

In May 2012, a domain user with twelve lines of PowerShell could read the local Administrator password for every machine in the organisation. The tool was Get-GPPPassword.ps1 [1]. The "encryption" was AES-256-CBC with a 32-byte key Microsoft had published in its own protocol specification [2] -- not leaked, published, as a feature, so that third-party Group Policy implementations could read the format. Eleven years later, on April 11, 2023, Microsoft finally shipped the in-box fix [3].

This is an article about those eleven years.

Pass-the-Hash

A lateral-movement technique in which an attacker uses the NTLM hash of a captured password directly in an authentication exchange, without recovering the cleartext. If the same local Administrator password is reused across a fleet, one dumped hash unlocks every machine. MITRE catalogues the technique as T1550.002.

The pattern was old before 2012. Through the 2000s, the only practical way to provision the local Administrator account on a Windows fleet was to bake one shared password into the reference image and ship the image to every endpoint. Helpdesk knew the password. Pentesters guessed at it. And once Benjamin Delpy's Mimikatz had pulled the hash from a single phished workstation in 2011, the rest of the org fell to a single psexec spray. Microsoft documented the threat model precisely in its December 2012 Mitigating Pass-the-Hash whitepaper [4], which named the shared local Administrator credential as the architectural enabler of the entire intrusion class [5].

Microsoft also had a fix. It had shipped one in 2008 with Group Policy Preferences (GPP), the feature that could push a per-machine local-admin password from a Group Policy Object to every endpoint. GPP put the password in an XML file in SYSVOL. SYSVOL was world-readable to every authenticated user in the domain. Microsoft encrypted the password with AES-256-CBC -- and then published the key. The result, after a four-author weaponisation chain in mid-2012 [@sogeti-2012-wayback; @obscuresec-gpp-2012; @rewtdance-gpp-2012; @metasploit-gpp], was that GPP made the original problem worse: instead of one shared password recoverable by physical access to a help-desk laptop, it was now one shared password recoverable by any authenticated domain user with a copy of Get-GPPPassword.ps1. Microsoft "patched" it on May 13, 2014 with MS14-025 [6], which disabled new authoring but deleted nothing already deployed. Twelve years later, PingCastle still finds the artefacts in production AD [7].

The first real fix was Generation 2: the legacy Microsoft LAPS, shipped May 1, 2015 as a separate MSI [8]. It stored a per-machine random password in the ms-Mcs-AdmPwd attribute on the computer object, marked CONFIDENTIAL [9]. The directory-side ACL was tighter than SYSVOL, but the deployment surface (install on every endpoint, extend the schema, delegate the OU) capped its real coverage; the password sat in plaintext in AD, one DCSync from "plaintext everywhere"; and a delegation pattern that helpdesks regularly issued -- "All Extended Rights" on the computer OU -- silently included read access to the CONFIDENTIAL attribute [9]. SpecterOps modelled that bypass as the ReadLAPSPassword BloodHound edge on August 7, 2018 [10].

Generation 3 -- Windows LAPS, in-box, no MSI -- shipped on Patch Tuesday April 11, 2023 [3] across Windows 11 22H2 and 21H2, Windows 10 22H2, Windows Server 2022, Windows Server 2019, and Windows Server Annual Channel. Windows Server 2016 was explicitly excluded [11]. The new architecture wrapped the password with CNG DPAPI's group key-protector against a configurable principal, exposed Microsoft Entra ID as a peer backup directory [12], and added a post-authentication rotation primitive that closed the screenshotted-password OPSEC tail on the next managed-account logon [13].

The local Administrator account always has the well-known relative identifier (RID) 500 in the machine's SAM, irrespective of any administrative renaming. Renaming the account at the friendly-name level does not change its SID, which is why Windows LAPS resolves the target account by SID and not by name -- and why an empty AdministratorAccountName policy still finds the right account even on a renamed-built-in host.

Microsoft knew the right architecture for managing local Administrator passwords in December 2012, when its own Pass-the-Hash whitepaper named the shared-credential pattern as the architectural enabler of lateral movement. It took until April 11, 2023 to ship that architecture as a Windows default. Eleven years is a long time. The intervening generations each solved part of the previous problem and introduced a new one. The 2026 baseline is, for the first time, an OS-default solution rather than an out-of-band one -- and for the first time, the residual attack surface is the actual surface rather than an artefact of incomplete shipping.

Ctrl + scroll to zoom
Twenty-eight years of Microsoft's local-administrator password story, from the imaged-build era to the in-box Windows LAPS default. Eleven years separate Microsoft's December 2012 Pass-the-Hash architectural articulation from the April 11, 2023 in-box default.

The article that follows traces the architecture of each generation, the attacks each one solved and each one enabled, and what "standard local admin password management" looks like as a 2026 default. To see why this took twenty years, we have to start in 1998, before Active Directory.

2. Origins: Why Every Workstation Had the Same Local-Admin Password (1998-2008)

Picture a system administrator in 2005. They are holding a CD-R labelled Win-Build-7.iso and a sticky note with a 12-character password. Those two artefacts are the entire local-Administrator-credential lifecycle for ten thousand desktops. The CD will be cloned to a USB drive, the USB drive will reseed Norton Ghost, and Ghost will paint the build onto every new workstation the company buys for the next eight months. Each painted machine will boot with the sticky-note password as its built-in local Administrator. Helpdesk knows the password because they typed it into the image. Five hundred field technicians know the password because they have to be able to recover unmanaged laptops off-network. The pentester who shows up in March will know the password by Tuesday lunch.

This was not a deviation. It was the architecture.

RID 500 (the built-in local Administrator)

Every Windows machine ships with a built-in local Administrator account whose security identifier ends in the relative identifier 500. The RID is constant across machines, languages, and SKUs. Renaming the account changes the friendly name but not the RID, so identity-aware tooling (including Windows LAPS) resolves the account by SID rather than by name. Disabling the account is a configuration choice, not a deletion: the account remains in SAM and can be re-enabled at any time.

The mechanics were a function of how Windows was deployed at scale. Microsoft Sysprep /generalize strips a reference image's machine SID before duplication, but it leaves the SAM intact. Whatever local Administrator password sits in the reference image is the local Administrator password on every endpoint painted from that image. Imaging pipelines were built around this: Norton Ghost in the late 1990s, Microsoft Deployment Toolkit (MDT) and later System Center Configuration Manager Operating System Deployment in the 2000s, all assumed the same SAM. Sean Metcalf's December 2015 SYSVOL retrospective walks the era end-to-end and explains why every shop in the world ended up with a single password [14].

The operational reality kept the pattern alive. Help-desk needed one known credential to break-glass a laptop that had wandered off the corporate network for six months. Field technicians needed one known credential to swap a failed hard drive on a roof-top kiosk in Houston without phoning home. A known-to-the-org local-admin password was the only realistic fallback path, and the alternative -- a different password per machine, stored somewhere retrievable -- required a retrieval primitive Microsoft had not yet shipped.

The threat model that made the trade-off catastrophic did not get articulated by Microsoft itself until December 2012, in version 1 of the Pass-the-Hash whitepaper [4]. The chain was already common knowledge in offensive-security circles: phish a single user, run Benjamin Delpy's 2011-vintage Mimikatz to pull credentials from LSASS, capture the NT hash of the built-in Administrator account, replay that hash to every other host via psexec or wmiexec, and pivot up to the first server an enterprise admin has touched. MITRE catalogues the default-account abuse as T1078.001 [15] and the hash-replay step as T1550.002 [5]. The whitepaper's recommended controls included exactly the architecture Microsoft would eventually ship as LAPS: per-machine random local-admin passwords, rotated frequently, retrievable only by an authorised principal.

The third-party prehistory matters because it set the terms Microsoft would eventually use. PolicyMaker, the engineering parent of what became Group Policy Preferences, was a product of DesktopStandard Corporation that Microsoft acquired in October 2006 [14]. Thycotic was founded in 1996 by Jonathan Cogley and shipped its Secret Server vault from the mid-2000s [16]; Lieberman Software (later acquired by Bomgar in January 2018) had operated as Lieberman and Associates since 1978 [17]; Quest Software was founded in 1987 in Newport Beach, California and was a public company well before the mid-2000s LAPS prehistory began -- its August 14, 1999 NASDAQ IPO saw its shares surge to $47 in a single Wall Street session [@wikipedia-quest; @latimes-quest-ipo-1999]. None of those vendors solved the local-admin-on-every-Windows-machine problem from inside the OS, and Microsoft's own first-party tooling -- restricted groups, logon scripts, Group Policy Object security templates -- offered no rotation primitive at all. The gap was not a knowledge gap; it was a first-party-feature gap.

In February 2008, Microsoft shipped Windows Server 2008. With it came Group Policy Preferences -- and with GPP came a "Local Users and Groups" preference that could push a per-machine local-admin password from a domain GPO to every endpoint in scope. It was the first first-party rotation mechanism Microsoft had ever shipped. It made the problem dramatically worse.

3. Decoration Is Not Encryption: GPP cpassword (2008-2012)

Microsoft Server 2008 reached release-to-manufacturing in February 2008. Group Policy Preferences shipped with it. The new "Local Users and Groups" preference -- alongside Scheduled Tasks, Services, Data Sources, Drive Maps, and Printers -- could push a password from a GPO down to every endpoint in scope. The password went into an XML file in SYSVOL, the domain's replicated policy share. SYSVOL was world-readable to every authenticated user in the domain. The password was AES-256-CBC encrypted in the XML, in a field called cpassword. The key was a 32-byte value published in [MS-GPPREF] section 2.2.1.1.4 [2], in Microsoft's own Open Specifications protocol corpus -- as a feature, so that third-party Group Policy implementations could interoperate.

SYSVOL

A file share replicated to every Domain Controller in an Active Directory domain, used to distribute Group Policy templates and logon scripts. The default share permissions allow Read access to every Authenticated User in the forest. Any file placed in SYSVOL is, operationally, readable by every domain user.

cpassword

The XML attribute defined by [MS-GPPREF] that carries an encrypted password inside a Group Policy Preferences item. The encryption is AES-256-CBC with a 16-byte zero IV and a static 32-byte key published in the same protocol specification. The name is short for "ciphertext password" and was the canonical search term for finding deployed credentials in SYSVOL between 2012 and 2026.

Group Policy Client-Side Extension (CSE)

A loadable component on each Windows endpoint that processes one class of Group Policy setting. Each preference type (Local Users and Groups, Scheduled Tasks, Services, etc.) is implemented by its own CSE, which runs during the Group Policy refresh cycle. CSEs read the policy XML out of SYSVOL, decrypt any cpassword field locally, and apply the setting to the host.

Microsoft was not unaware. On April 22, 2009, the Group Policy Team blog re-posted (and updated) a piece by Linda Moore titled "Passwords in Group Policy Preferences (Updated)" [18]. The phrasing is unambiguous.

"the password is not secured. Because the password is stored in SYSVOL, all authenticated users have read access to it." -- Linda Moore, Group Policy Team blog, April 22, 2009 [18]

The post recommended a list of mitigations: prefer secure mechanisms, audit who can read the SYSVOL share, prefer not to use the field at all. None of those mitigations could rotate the key. None could revoke the static AES-256 key value published in [MS-GPPREF]. Microsoft was telling its customers, in 2009, three years and eight months before the public weaponisation, that the credential they were storing was decryptable by every user in the domain by design.

Three years later, the offensive-security community spent twelve weeks turning the publication into a default-on red-team primitive.

In April and May of 2012, Emilien Girault of Sogeti ESEC published a Python decryptor on the firm's research blog [19]. The site has since been retired and the canonical reference is the Wayback Machine capture. In mid-May 2012, Chris Campbell (@obscuresec) published Get-GPPPassword.ps1, a PowerShell port that fetched the relevant XML from SYSVOL, decoded the base64, and called .NET's AES primitives with the published key [1]. The script was folded into PowerSploit at Exfiltration/Get-GPPPassword.ps1, where its header still reads "Author: Chris Campbell (@obscuresec)" [20] and explicitly credits Emilien Girault for the underlying research. In June 2012, Ben Campbell (the rewtdance.blogspot.com blog handle), working with scriptmonkey (a named collaborator with his own blog at blog.owobble.co.uk), extended the attack to all six XML wire-format carriers that [MS-GPPREF] permits [21]. The rewtdance post body credits the collaboration verbatim: "Working with scriptmonkey (http://blog.owobble.co.uk/), who already had a DC configured, we verified this theory." On July 25, 2012, the Metasploit module post/windows/gather/credentials/gpp.rb landed [22] with five co-authors: Ben Campbell, Loic Jaquemet, scriptmonkey, theLightCosine, and mubix. A companion auxiliary scanner, auxiliary/scanner/smb/smb_enum_gpp.rb, was authored independently by Joshua D. Abraham of Praetorian [23].

The whole exercise was twelve lines of code. The interesting part was not the cryptography. The interesting part was that the operation was decryption-by-reference: with a published key, the AES envelope was not protecting a secret, it was carrying a secret in a format the protocol specification told everyone how to read.

The 32-byte AES key, as published by Microsoft in [MS-GPPREF] 2.2.1.1.4
4e 99 06 e8  fc b6 6c c9  fa f4 93 10  62 0f fe e8
f4 96 e8 06  cc 05 79 90  20 9b 09 a4  33 b6 6c 1b

These bytes are reproduced verbatim from Microsoft's published [MS-GPPREF] Group Policy Preferences specification [2]. They have appeared in the public Microsoft Open Specifications corpus since the [MS-GPPREF] protocol document was first published as part of the Windows Server 2008 protocol-documentation programme; the earliest tangible third-party reuse of the key dates to the April-July 2012 Sogeti / obscuresec / rewtdance / Metasploit research chain [@sogeti-2012-wayback; @obscuresec-gpp-2012; @rewtdance-gpp-2012; @metasploit-gpp]. The key is not a secret; it is an interoperability primitive.

Python Twelve-line cpassword decryptor (illustrative)
import base64
# Pure-Python AES illustration (no third-party dependency).
# In a real script, use a library; this is for demonstration of how trivial the
# operation is once the key is public.

KEY_HEX = (
"4e9906e8fcb66cc9faf49310620ffee8"
"f496e806cc057990209b09a433b66c1b"
)

def restore_b64_padding(s):
return s + "=" * (-len(s) % 4)

def decrypt_cpassword_demo(cpassword_b64):
# Steps (no actual AES here; this is to show the public algorithm):
# 1. Restore base64 padding stripped by Microsoft.
# 2. Decode to ciphertext bytes.
# 3. AES-256-CBC decrypt with the published 32-byte KEY and a 16-byte zero IV.
# 4. Strip the PKCS#7 padding and UTF-16-LE decode the plaintext.
ciphertext = base64.b64decode(restore_b64_padding(cpassword_b64))
return f"would AES-256-CBC decrypt {len(ciphertext)} bytes with the public key"

print(decrypt_cpassword_demo("j1Uyj3Vx8TY9LtLZil2uAuZkFQA/4latT76ZwgdHdhw"))

Press Run to execute.

Ctrl + scroll to zoom
A domain user reads SYSVOL, decrypts the AES-256 ciphertext with the published key, and pivots via Pass-the-Hash. Twelve lines of code. No CVE was ever assigned, because no vulnerability existed in the cryptographic sense -- the key was public on purpose.

By 2013, "GPP cpassword finding" was a standard early-engagement primitive on every internal pentest, captured in Sean Metcalf's December 2015 retrospective on the class: this is what happens when an "encryption" feature is shipped with a published key [14]. MITRE catalogues the class as T1552.006 under Unsecured Credentials: Group Policy Preferences [24]. Microsoft's first first-party rotation primitive had taken a problem -- one shared password, recoverable from the helpdesk -- and made it strictly worse: one shared password, recoverable from a SYSVOL read by any user in the forest.

Encryption with a published key is plaintext with extra steps. The cryptography is not broken; the threat model is. AES-256-CBC is a perfectly good block cipher. But the only secret in a symmetric encryption envelope is the key; once the key is public, "AES-encrypted" is a notation, not a protection. The cpassword field was not a vulnerability in the bug sense -- there was no defect to patch, because the disclosure was deliberate. The "fix," when it came, could change the editor UI but could not change the key.

On May 13, 2014, Microsoft shipped MS14-025 to close the hole. It did, and it did not.

4. The Patch With a Tail: MS14-025 (May 13, 2014)

Microsoft Security Bulletin MS14-025 / KB2962486 shipped on Patch Tuesday, May 13, 2014 -- seven Patch Tuesdays after the Sogeti / obscuresec / rewtdance (Ben Campbell with scriptmonkey) / Metasploit weaponisation chain crossed the threshold from research toy to default-on red-team primitive [@ms14-025-bulletin; @ms14-025-kb]. The bulletin closed the hole. Half-closed it. The lesson the half is teaching took twelve years to land.

What MS14-025 did: it removed the password input field from the Group Policy editor user interface for five preference categories -- Local Users and Groups, Scheduled Tasks, Services, Data Sources, and Drive Maps [25]. The Remote Server Administration Tools (RSAT) update disabled the creation of new GPP items containing a cpassword field at all. The CVE assigned to the issue was CVE-2014-1812 [6]. The bulletin's own Executive Summary called the underlying class an Elevation of Privilege vulnerability and explained that "an attacker who successfully exploited the vulnerability could decrypt the password stored in the Group Policy preference" [6].

What MS14-025 did not do is more important than what it did.

It did not delete existing Groups.xml, Services.xml, ScheduledTasks.xml, DataSources.xml, or Drives.xml from any SYSVOL anywhere. It did not rotate the credentials those XML files contained. It could not revoke the 32-byte AES key published in [MS-GPPREF] 2.2.1.1.4, because the protocol-specification publication was permanent under Microsoft's Open Specifications Promise [2]. And the editor UI fix had an asymmetry with the wire format that practitioners had to discover on their own: the bulletin and KB enumerated five preference types, but [MS-GPPREF] permits a cpassword field in six XML carriers. The sixth is Printers\Printers.xml, which Microsoft's UI never exposed a password field for and which the bulletin therefore did not name -- but which Ben Campbell's June 2012 enumeration with scriptmonkey had already flagged as an exploitable carrier [21].

The bulletin's own Additional Action Required section made the cleanup story explicit.

"Customers with existing Group Policies that use Group Policy preferences to set passwords will need to take additional action to remove those policies." -- Microsoft Security Bulletin MS14-025, Additional Action Required [6]

The fix-and-no-cleanup pattern was not new in 2014. What was new was the time horizon the pattern would persist over. MS14-025 disabled new authoring in May 2014; in 2026, twelve years later, PingCastle's A-PwdGPO rule still finds residual Groups.xml files in production Active Directory [7]. MITRE catalogues the same primitive as T1552.006 [24]. There is no first-party Microsoft cmdlet to find or remediate the artefacts. Practitioners have built Get-GPPDeployedPasswords scripts; PingCastle ships the scan; Semperis Purple Knight ships a similar one. Microsoft does not.

The five-preference / six-XML reconciliation matters for audit completeness. MS14-025's KB enumerates the five preference categories whose editor UI accepted a password [25]. The wire format documented in [MS-GPPREF] permits a cpassword field in those five plus Printers.xml [21]. A SYSVOL audit that greps only the five named files will miss the sixth carrier. A 2026 audit must search across all six XML names.

A vulnerability mitigation without a remediation pass leaves a multi-decade tail. MS14-025 is the canonical example: the editor UI was hot-patched in May 2014, no SYSVOL artefacts were deleted, no credentials were rotated, the underlying AES key was not revocable, and a third-party scanner cohort (PingCastle, Purple Knight, BloodHound) had to fill the gap that Microsoft never closed. The architectural lesson recurs in section 6 (legacy-LAPS coexistence with Windows LAPS), in section 10 (the open-problems list still names un-cleaned SYSVOL cpassword artefacts as problem one), and in section 11 (audit step 1 is always "sweep SYSVOL first"). A patch that does not clean up after itself becomes a permanent feature of the threat model.

One year after the half-fix, Microsoft shipped the actual fix. It was deployable on every endpoint -- if you were willing to install an MSI on every endpoint, extend the schema, and accept that the password lived in plaintext in Active Directory.

5. The First Real Fix and Its Own Attack Class: Legacy Microsoft LAPS (May 1, 2015 to April 2023)

On May 1, 2015, Microsoft Security Advisory 3062591 announced "Local Administrator Password Solution (LAPS) Now Available" [8]. The advisory page is now only available on the Wayback Machine; the modern Download Center entry for the legacy MSI carries a deprecation note dated to Windows 11 23H2 [26]. The deliverable was a 1.6 MB LAPS.x64.msi (and a smaller x86 sibling). It was not in the operating system. You had to install it on every endpoint. The architecture was simple, the deployment was painful, and the engineering core had not actually been written by Microsoft.

Inside the MSI was Jiri Formacek's AdmPwd. The provenance is on the project's GitHub README, verbatim: "This is source code for AdmPwd project that has been previously hosted on MSDN gallery -- project has been used as base for Microsoft branded LAPS solution." [27]. The often-omitted prehistory is that Microsoft Services had been quietly recommending AdmPwd to customers for years before the 2015 release; what Microsoft Security shipped was a packaging exercise on top of a working open-source primitive.

The architecture, attribute by attribute, looked like this. The legacy LAPS Group Policy Client-Side Extension lived in admpwd.dll. It ran on every Group Policy refresh -- the standard 90-minute interval with up to 30 minutes of randomised jitter on member computers. When the local password's age exceeded PasswordAgeDays (default 30 days, not one day), the CSE generated a new random password, set it on the local Administrator account via the Security Account Manager, and wrote the plaintext to the computer object's ms-Mcs-AdmPwd attribute in Active Directory [9]. A second attribute, ms-Mcs-AdmPwdExpirationTime, held a Windows FILETIME timestamp of when the next rotation was due.

CONFIDENTIAL attribute (AD schema searchFlags 0x80)

A bit in the searchFlags value of an Active Directory schema attribute that removes the attribute from the default Read Property permission set. To read a CONFIDENTIAL attribute, a principal needs not just Read Property but also the CONTROL_ACCESS extended right. The legacy LAPS schema extension set searchFlags |= 0x80 on ms-Mcs-AdmPwd so that ordinary "Read All Properties" delegations on the OU did not silently confer the password.

The good architectural news: the password was no longer in SYSVOL, and the directory's access control could be tighter than the SYSVOL share's read-everywhere default. The bad architectural news arrived in three layers.

First, the deployment surface was the cap on the legacy generation's coverage. To make legacy LAPS work in a forest, an administrator had to (a) Update-AdmPwdADSchema once per forest to add the two attributes, (b) Set-AdmPwdComputerSelfPermission per OU so that the computer accounts could write their own attributes, (c) install LAPS.x64.msi on every endpoint, (d) install the ADMX template on every administrative workstation, and (e) configure a GPO with PasswordAgeDays, complexity, and length. Any step missed left a host out of scope. PingCastle's coverage rules continue to report on incomplete LAPS deployments precisely because the failure mode is silent: missing the MSI on a single OU produced no error, just a host with the same local-Administrator password it had been imaged with [7].

Second, the directory-side ACL had a delegation footgun. The CONFIDENTIAL bit gates ordinary reads; it does not gate the "All Extended Rights" delegation. Helpdesk OUs routinely delegate "All Extended Rights" so that helpdesk technicians can reset passwords on user accounts in their scope. The same "All Extended Rights" grant, applied to a computer OU, silently includes the CONTROL_ACCESS right -- which is exactly what reading ms-Mcs-AdmPwd requires. Sean Metcalf's August 2016 ADSecurity write-up documented the class in detail and noted that Microsoft shipped Find-AdmPwdExtendedRights as an audit primitive but did not block the delegation pattern at the schema layer [9]. The fix was operational: audit every "All Extended Rights" delegation on every computer OU, then remove the ones that did not need to read LAPS passwords. The fix was not architectural.

Third, SpecterOps formalised the class as a primary BloodHound primitive. On August 7, 2018, BloodHound 2.0 shipped with the ReadLAPSPassword edge as one of its four named new attack primitives -- alongside CanRDP, ExecuteDCOM, and AllowedToDelegate [10]. The current edge documentation covers both the legacy ms-Mcs-AdmPwd and the modern msLAPS-* attribute paths [28]. The edge runs from a user or a group to a computer and indicates that LAPS is installed and the principal can read the password for the local Administrator account from LDAP. Inside a typical enterprise graph, the edge is dense.

ReadLAPSPassword (BloodHound edge)

A directed edge in the BloodHound attack graph from a security principal to a computer object, indicating that the principal can read the LAPS-managed local Administrator password on that computer via LDAP. The edge collects the legacy ms-Mcs-AdmPwd reachability and the modern msLAPS-Password / msLAPS-EncryptedPassword reachability into a single semantic. Introduced in BloodHound 2.0 on August 7, 2018 [@specterops-bh2; @bloodhound-edge-readlaps].

"The ReadLAPSPassword edge runs from a user or a group to a computer and indicates that LAPS is likely installed on the target computer and the principal can read the password for the local administrator account from LDAP." -- SpecterOps, BloodHound 2.0 announcement, August 7, 2018 [10]

The companion attribute ms-Mcs-AdmPwdExpirationTime is not CONFIDENTIAL -- it is enumerable by every Authenticated User in the forest. That makes it a coverage-leak telemetry primitive: an attacker can query the attribute across every computer object and learn which hosts are managed by LAPS and which are not. The unmanaged hosts are the ones to attack first.
Ctrl + scroll to zoom
Legacy LAPS stores the password in ms-Mcs-AdmPwd marked CONFIDENTIAL (searchFlags 0x80). Reading it should require the CONTROL_ACCESS extended right. The All-Extended-Rights delegation pattern, common on helpdesk OUs, silently confers that right -- which is why Find-AdmPwdExtendedRights exists.

The other structural limit was the directory's own integrity boundary. The password sat in plaintext in the directory. A stolen NTDS.dit -- obtained via DCSync, NTDSUtil dump, or physical theft of a DC's disk -- exposed every managed local-Administrator password in the forest at once. There was no encryption-at-rest in legacy LAPS, by design. The trust model was "the directory is tier 0 and DCSync is a domain-compromise event already," which is operationally true and architecturally lazy.

Microsoft fixed both of those structural defects on April 11, 2023. The fix shipped in the operating system, with no MSI. We come to it next.

6. The In-Box Era: Windows LAPS (April 11, 2023 to Present)

Patch Tuesday, April 11, 2023. The April cumulative update for Windows 11 22H2 was KB5025239. The Windows 11 21H2 update was KB5025224. Windows 10 22H2 was KB5025221. Windows Server 2022 was KB5025230. Windows Server 2019 was KB5025229. The Server Annual Channel shipped it too. Windows Server 2016 was, and remains, explicitly excluded -- the per-SKU April-2023 cumulative-update KB numbers are catalogued in the Tenable retrospective on the Windows LAPS GA wave [3] and the official Microsoft LAPS overview page [11]. The MSI was gone. The admpwd.dll Client-Side Extension was gone. In its place: exactly three OS binaries -- laps.dll for core LAPS logic, lapscsp.dll for the Microsoft Intune Configuration Service Provider, and lapspsh.dll for the LAPS PowerShell module -- all shipped together, all part of the OS, all available without installing anything [@ms-laps-concepts-overview; @tc-windows-laps-ga-2023]. The Microsoft Learn laps-concepts-overview page enumerates the three binaries verbatim and lists no fourth.

The most consequential architectural change is the one most often missed.

The new schema added six attributes to the Computer object: msLAPS-Password (the plaintext-fallback location), msLAPS-EncryptedPassword (the CNG-DPAPI-wrapped ciphertext blob), msLAPS-EncryptedPasswordHistory (rotation history), msLAPS-PasswordExpirationTime, msLAPS-EncryptedDSRMPassword (Directory Services Restore Mode account on a DC), and msLAPS-EncryptedDSRMPasswordHistory [29]. The DSRM pair is a Windows-LAPS-only capability; legacy LAPS never covered Domain Controller DSRM accounts. The schema extension is performed once per forest by Update-LapsADSchema, which is idempotent and coexists with the legacy ms-Mcs-AdmPwd attribute [30].

A seventh attribute, msLAPS-CurrentPasswordVersion, exists in the Windows Server 2025 forest schema only. It is added automatically when the first Windows Server 2025 Domain Controller is promoted -- not by running Update-LapsADSchema -- and is used by laps.dll to mitigate a virtual-machine-snapshot torn-state class. The attribute is read-only as far as the LAPS feature is concerned and is not part of the ReadLAPSPassword BloodHound edge's calculus [29].

Encryption-at-rest with CNG DPAPI

The load-bearing addition is encryption of the password before it leaves the client. The mechanism is the CNG DPAPI group key-protector (still commonly called DPAPI-NG in Microsoft's older documentation) [31]. The client generates the new local-Administrator password, then wraps the plaintext against a security principal SID using the Active Directory Key Distribution Service (KDS) root key infrastructure. The wrapped blob is the only thing the LDAP write places into msLAPS-EncryptedPassword. To decrypt, a reader Kerberos-authenticates to the KDC; only members of the configured principal group at decryption time can derive the protector. The directory itself never sees plaintext, and a stolen NTDS.dit yields ciphertext only [29].

CNG DPAPI (DPAPI-NG) group key-protector

A protection mechanism in Windows's CNG (Cryptography API: Next Generation) Data Protection API in which a payload is encrypted against a security principal -- typically an AD group SID -- rather than against a local user. Decryption is gated by Kerberos authentication and the principal's group membership at the time of decryption [31]. Microsoft Learn currently spells the primitive "CNG DPAPI" on the canonical reference; older Microsoft documentation and Win32 references continue to use the shorthand "DPAPI-NG". They are the same primitive.

There are two policy settings that gate the encryption path, and the failure modes are operationally important.

The backup-directory choice

BackupDirectory (Windows LAPS policy)

The CSP / GPO node BackupDirectory selects where Windows LAPS writes the rotated password. The three valid values are 0 (do not back up; passwords rotate locally but are not retrievable), 1 (Microsoft Entra ID via the deviceLocalCredentials resource on Microsoft Graph), and 2 (Active Directory via the msLAPS-* attribute set). The values are mutually exclusive per device; a hybrid-joined device can choose either backend but not both [@ms-laps-policy-settings; @ms-laps-entra-scenarios].

The Entra-backup path went generally available on October 23, 2023 [12]. With BackupDirectory = 1, the local LAPS component posts the rotated password to the deviceLocalCredentials resource on the device object in Microsoft Entra ID via the Microsoft Graph API [32]. Retrieval is via Get-LapsAADPassword (a thin wrapper over the Graph endpoint), the Entra portal Devices blade, or a direct GET /directory/deviceLocalCredentials/{deviceId} call [33].

The Entra-backup path has a seven-day minimum for PasswordAgeDays. The AD-backup path's minimum is one day. A tier-0 fleet that targets daily rotation on Entra-joined endpoints will not get daily rotation -- Entra-side policy validation rejects the value. Section 7's baseline table reflects this asymmetry.

Policy surface and the FQ-anchored corrections

Windows LAPS is configurable via Group Policy (for AD-joined hosts), the LAPS Configuration Service Provider at ./Device/Vendor/MSFT/LAPS/Policies/* for Intune-managed hosts [34], local policy, or the legacy LAPS GPO if PolicySourceMode selects emulation mode. The settings include BackupDirectory, PasswordComplexity (values 1 through 8), PasswordLength, PasswordAgeDays, PostAuthenticationActions, PostAuthenticationResetDelay, AdministratorAccountName, PassphraseLength, ADPasswordEncryptionEnabled, ADPasswordEncryptionPrincipal, and ADBackupDSRMPassword. On Windows 11 24H2 and Windows Server 2025 and later, the policy surface adds Automatic Account Management settings: AutomaticAccountManagementEnabled, AutomaticAccountManagementNameOrPrefix, AutomaticAccountManagementRandomizeName, AutomaticAccountManagementTarget, and AutomaticAccountManagementEnableAccount [@ms-laps-policy-settings; @ms-laps-account-modes].

PostAuthenticationActions

The action Windows LAPS performs after the managed account has authenticated to the host. Valid values are 1 (reset the password), 3 (reset and sign out the interactive session; default), 5 (reset and reboot, with a one-minute reboot delay), and 11 (reset, sign out, and terminate remaining processes; Windows 11 24H2 / Windows Server 2025 and later). The action fires after PostAuthenticationResetDelay hours have elapsed since the authentication that triggered it [13].

PostAuthenticationResetDelay defaults to 24 hours. The range is 0 to 24 hours; a value of 0 disables the post-authentication action entirely [13]. A tier-0 fleet aiming to close the screenshotted-password OPSEC tail aggressively will configure this down to 1 hour; tier-2 deployments typically leave it at 8 or 24.

PasswordComplexity values 5 through 8 (Windows 11 24H2+ / Windows Server 2025+)

PasswordComplexity values 1 through 4 are character-class modes (uppercase only; uppercase plus lowercase; uppercase plus lowercase plus numbers; and -- value 4, the default -- all four character classes). Value 5 is not a "no vowels or numbers" mode, despite a common folk attribution; it is the "improved readability" four-class variant of value 4, equivalent to value 4 with the visually ambiguous glyphs I, O, Q, l, o, 0, 1 removed and the symbols :, =, ?, * added [35]. Microsoft's own documented example password for value 5 is vnJ!!?MTb5=U7Y -- which retains vowels and digits 2 through 9. Values 6, 7, and 8 are passphrase modes drawn from a Microsoft-curated wordlist derived from the EFF Diceware wordlists [@eff-dice; @eff-wordlists-2016] with internal modifications. The published word counts after Microsoft's curation are 7776 / 1276 / 1276 for modes 6 / 7 / 8 respectively; the EFF originals (the EFF Long Wordlist, EFF Short Wordlist #1, and EFF Short Wordlist #2 published July 2016) are 7776 / 1296 / 1296 [@eff-dice; @eff-wordlists-2016]. Values 5 through 8 are all gated on Windows 11 24H2 / Windows Server 2025 and later -- not only values 6-8. The cited Microsoft Learn page reads verbatim for value 5: "The PasswordComplexity setting of '5' is only supported in Windows 11 24H2, Windows Server 2025, and later releases." [35]. Passphrase modes exist for DSRM-account scenarios where the password must be typed by a human under duress; the article's section 7 baseline recommends them for tier-0 break-glass accounts.

PowerShell surface and one important cmdlet name

The native LAPS PowerShell module ships eight cmdlets the article calls out by name: Get-LapsADPassword, Reset-LapsPassword, Update-LapsADSchema, Set-LapsADAuditing, Set-LapsADComputerSelfPermission, Set-LapsADReadPasswordPermission, Set-LapsADResetPasswordPermission, and Find-LapsADExtendedRights [@ms-laps-ps-overview; @ms-laps-get-adpassword]. The auditing cmdlet is Set-LapsADAuditing -- not Set-LapsADAuditingSettings, which does not exist as a cmdlet name [36]. The Entra-backup retrieval cmdlet is Get-LapsAADPassword, a wrapper around Microsoft Graph.

Migration coexistence

Legacy LAPS and Windows LAPS can coexist on the same host only if they target different local accounts. The documented coexistence pattern is to run legacy LAPS against the built-in RID 500 Administrator while introducing Windows LAPS against a named secondary local-admin account, then retire the legacy MSI once Windows LAPS coverage is verified [30]. The cross-pointer in section 11 details the seven-step migration sequence.

Ctrl + scroll to zoom
Windows LAPS runs on a hard-coded ~1-hour background timer in laps.dll. Encryption to AD requires DFL of Server 2016 or higher AND BackupDirectory = 2 AND ADPasswordEncryptionEnabled = True (the default per the Microsoft Learn policy-settings page); any failed precondition silently falls back to plaintext in msLAPS-Password.

With the in-box era settled, what does a 2026 deployment actually look like? A short list of policy settings, and a slightly longer list of footguns.

7. The 2026 Baseline as a Settings Table

Architecture is interesting. Audits are not. Here is the 2026 settings table that, in production, separates a deployment that meets its goal from one that quietly does not. Every row carries the policy node, the documented default, the recommended tier-2 value (a typical end-user fleet), the recommended tier-0 value (Domain Controllers and break-glass), and the citation. Cross-check the row against the Microsoft Learn policy-settings page before you ship it.

PolicyDefaultRecommended (tier 2)Recommended (tier 0)WhyCitation
BackupDirectory0 (no backup)2 (AD) for AD-joined and hybrid-joined; 1 (Entra) for pure Entra-joinedsame as tier 2One directory per device; AD for hybrid where on-prem identity is canonical[13]
PasswordComplexity4 (all character classes)46 (3-word passphrase) for accounts a human must type under duress (DSRM / break-glass); 4 for automated retrievalPassphrases for human typing; character-set for tool-only retrieval. Values 5 through 8 are gated on Windows 11 24H2 / Windows Server 2025 and later: value 5 is the "improved-readability" four-class variant of 4 (not a "no vowels" mode); values 6/7/8 are passphrase modes with Microsoft-curated EFF-derived wordlists of 7776 / 1276 / 1276 entries (EFF originals: 7776 / 1296 / 1296)[@ms-laps-passwords-passphrases; @eff-dice; @eff-wordlists-2016]
PasswordLength142424Eliminates the rainbow-table threat class[35]
PasswordAgeDays30 (1-day minimum AD; 7-day minimum Entra; 365-day max)301 (AD) / 7 (Entra; lower fails policy validation)Caps the blast radius of an undetected credential theft to one rotation window[13]
PostAuthenticationActions3 (reset + sign out)33, or 11 on Win 11 24H2+ if process termination is requiredCloses the screenshot-leak OPSEC tail on the next managed-account interactive logon. Value 11 is not "force shutdown without warning" -- it is reset + sign out + terminate remaining processes with the same two-minute warning as 3[13]
PostAuthenticationResetDelay24 (hours)81Trade-off between operational task completion and exposure window[13]
ADPasswordEncryptionEnabledTrue per Microsoft Learn's defaults table -- not off-by-defaultTrue, configured explicitly so the choice is visible in policy audits and the DFL prerequisite is verifiedsameThe genuine failure mode is silent fallback to plaintext when DFL is below Server 2016 or BackupDirectory is not 2, not a default-off bit[@ms-laps-policy-settings; @ms-laps-csp]
ADPasswordEncryptionPrincipalDomain Admins of the computer's domain when unspecifiedDedicated LAPS-DPAPI-Decryptors group, not Domain Adminssame, with PIM-gated activationDecryption authority is delegated separately from LDAP read; minimise membership[29]
AdministratorAccountNameempty (manages built-in RID 500)empty on Server SKUs; named account (e.g. lapsadmin) on Client SKUs with the built-in disabledOn Win 11 24H2 / WS2025+, prefer Automatic Account Management with random name and disabled-by-defaultDefeats predictable-RID-500 enumeration[@ms-laps-policy-settings; @ms-laps-account-modes]
ADBackupDSRMPasswordFalsen/a (member servers)True on Domain ControllersBrings DSRM-account management into LAPS scope -- a capability legacy LAPS never had[29]

The audit-primitives sub-table

The decision of which tool answers which question is, in practice, the difference between a LAPS deployment that meets its goal and one that quietly does not. The five (and a half) primitives:

PrimitiveQuestion it answersPrimary source
BloodHound ReadLAPSPassword edgeWhich principals can read the LAPS password on which computer objects, transitively across the graph?[28]
PingCastle A-LAPS-Not-InstalledDoes this domain have any LAPS solution installed for the native local administrator account?[7]
PingCastle A-LAPS-Joined-ComputersCan a user who manually domain-joined a computer (via mS-DS-CreatorSID ownership) still read that computer's LAPS password?[7]
PingCastle A-PwdGPODoes this domain still have residual GPP cpassword artefacts in SYSVOL? (MITRE T1552.006)[@pingcastle-rules; @mitre-t1552-006]
Windows event 4662 on msLAPS-* (SACL via Set-LapsADAuditing)Who read which LAPS attribute on which computer object, and when?[@ms-laps-set-adauditing; @ms-laps-ps-overview]
Entra audit log + Graph GET /directory/deviceLocalCredentials/{deviceId} readsWho retrieved which LAPS password from Microsoft Entra ID (BackupDirectory = 1), and when?[@ms-graph-localcredinfo; @ms-laps-entra-scenarios]

No Microsoft Defender for Identity alert in the current public taxonomy names LAPS specifically [38]; instead, lean on the event 4662 SACL primitive plus advanced hunting in the IdentityDirectoryEvents table for principal-pattern anomalies. Microsoft's Compromised Credentials and Lateral Movement categories surface the downstream behaviour when a stolen LAPS password gets used.

JavaScript LAPS coverage verifier (illustrative; mirrors the logic of a Get-LapsADPassword sweep)
// In production, run: Get-LapsADPassword -Identity * | Where-Object {
//   $_.ExpirationTimestamp -lt (Get-Date) -or $_.Source -eq 'Plaintext'
// }
// This in-browser demo mirrors the same logic against an array of mock computer objects.

const ONE_DAY_MS = 86400000;
const computers = [
{ name: "WS-001", msLapsExpiry: Date.now() + 5 * ONE_DAY_MS, encrypted: true  },
{ name: "WS-002", msLapsExpiry: Date.now() - 2 * ONE_DAY_MS, encrypted: true  },
{ name: "WS-003", msLapsExpiry: null,                        encrypted: false },
{ name: "WS-004", msLapsExpiry: Date.now() + 1 * ONE_DAY_MS, encrypted: false },
];

const gaps = computers.flatMap(c => {
const issues = [];
if (c.msLapsExpiry === null)           issues.push("no password stored");
else if (c.msLapsExpiry < Date.now())  issues.push("expired (overdue rotation)");
if (!c.encrypted)                      issues.push("plaintext (msLAPS-Password)");
return issues.length ? [`${c.name}: ${issues.join(", ")}`] : [];
});

console.log(gaps.length === 0
? "All computers have current, encrypted LAPS passwords"
: "Coverage gaps:\n  " + gaps.join("\n  "));

Press Run to execute.

The AdministratorAccountName decision deserves one paragraph of its own. On Server SKUs, the built-in Administrator (RID 500) is enabled by default, and leaving the policy empty manages it -- this is what most deployments want. On Client SKUs the built-in is disabled by default; many shops create a named admin account (a common convention is lapsadmin) and set AdministratorAccountName to that name. On Windows 11 24H2 and Windows Server 2025 and later, the better answer is Automatic Account Management: set AutomaticAccountManagementEnabled = 1, AutomaticAccountManagementRandomizeName = 1, and AutomaticAccountManagementEnableAccount = 0, and the host will auto-create a randomised-name disabled-by-default local-admin account that Windows LAPS owns end to end [39]. The result is that an attacker enumerating local accounts cannot guess the LAPS-managed account name from RID 500, RID 1000, or any other predictable identifier.

This is the baseline. But LAPS is not the only answer to "who knows the local admin password." For three classes of fleet, the right answer is something else.

8. When LAPS Is Not the Right Tool

Three classes of fleet should not -- or should not only -- run Windows LAPS. The first wants a workflow LAPS does not offer. The second wants no standing local admin at all. The third is orthogonal: it changes the in-session elevation surface without changing the recoverable break-glass.

Third-party Privileged Access Management (PAM) vaults. Delinea Secret Server [40], CyberArk Endpoint Privilege Manager [41], and BeyondTrust Password Safe are the dominant 2026 commercial offerings in the category. The case for running a PAM vault alongside (or instead of) Windows LAPS is rarely about cryptography and almost always about workflow. PAM vaults bring multi-factor authentication on checkout, full session recording, dual-approval gates for high-risk accounts, and cross-OS scope (Windows, macOS, Linux, network gear, hypervisors) under one ACL model. The total cost of ownership is higher than LAPS; the security model, properly deployed, is comparable. Many shops run both: Windows LAPS for the workstation floor, PAM for tier-0 break-glass with session recording. The split is a workflow trade-off, not an architectural one.

Zero standing local admin plus Entra PIM JIT elevation. Tier-0 fleets that have reached the "no routine local admin" architectural state disable the built-in RID 500 entirely and gate every admin operation through just-in-time elevation. Microsoft Entra Privileged Identity Management [37] supports the eligibility / activation / approval workflow at scale: an operator is eligible for an admin role, activates it for a bounded duration with optional MFA and ticket reference, and an approver signs off on the activation if policy requires. Windows LAPS coexists in this model as the absolute-last-resort break-glass mechanism -- for the case where Entra itself is down, the network is partitioned, and a human has to walk to a console and type a password. The architectural alignment is with MITRE T1078.001 (Default Accounts) [15]: if the default account is permanently disabled and only re-enabled under PIM workflow, the entire technique class is bounded by the PIM activation log.

Windows 11 25H2 Administrator Protection. Per-elevation transient admin sessions arrived as a Tech Community preview in late 2025 [42]. The feature creates a temporary, isolated "shadow admin" identity for the duration of each elevation prompt, brokering UAC-class elevation through a per-elevation token that is destroyed when the elevated process exits. This is orthogonal to LAPS, not a replacement. Administrator Protection addresses in-session UAC elevation; Windows LAPS addresses the recoverable break-glass password for off-network and non-bootable recovery. The two systems answer different questions. Conflating them produces designs that drop LAPS in favour of Administrator Protection and then discover, six months later, that there is no recovery primitive for a laptop the user has dropped off the corporate network for a year.

SituationRecommended method
On-premises AD-joined, no Entra IDA -- in-box Windows LAPS with AD backup
Microsoft Entra hybrid-joined, on-prem AD authoritativeA -- Microsoft's current hybrid recommendation
Pure Entra-joined, no on-prem ADB -- in-box Windows LAPS with Entra ID backup
Stuck on Windows Server 2016 (excluded from Windows LAPS)C -- legacy MSI LAPS until OS migration completes
In active migration from legacy LAPS to Windows LAPSC in side-by-side mode with different managed accounts
Non-Windows scope (Linux, macOS, network gear) needs unified vaultingD -- third-party PAM vault, often alongside A/B
Regulated industry requiring session recording / MFA checkoutD alongside A/B
Tier-0 fleet with a zero-standing-credential goal and Entra ID P2E -- PIM-gated JIT elevation layered on A or B
Windows 11 fleet wanting in-session credential-theft mitigationF -- Administrator Protection alongside A/B (orthogonal)
BYOD, workgroup, or unmanaged endpointsNone of A through F -- enrollment is the answer, not LAPS
Ctrl + scroll to zoom
Pick the right tool for the fleet. Methods A and B are the in-box defaults for AD-joined and Entra-joined respectively; Methods D and E layer on top; Methods C and F have narrow remaining roles.

All five answers above -- methods A through F -- have a structural ceiling. There is one bound none of them can break.

9. What LAPS Structurally Cannot Solve

Every recoverable-secret system has a privileged reader. Whether you call it ADPasswordEncryptionPrincipal, a "CyberArk vault admin," or a "PIM eligible approver," somebody can break the glass -- which means somebody can compromise the glass. This is a lower bound, not an implementation defect.

The eleven-year arc converged on a tight bound. It did not abolish the underlying problem. Four structural limits are worth naming, because each maps onto a real residual attack surface in 2026 deployments.

Bound 1: at least one reader exists, by construction. Symbolically, readers1|\text{readers}| \geq 1. CNG DPAPI's group-key-protector substitution does not eliminate the privileged class; it relocates the trust boundary. The boundary moves from "every principal with LDAP read on the attribute" (legacy LAPS) to "every principal in the configured ADPasswordEncryptionPrincipal group at decryption time" (Windows LAPS). The relocation tightens the bound by orders of magnitude in typical fleets -- a LAPS-DPAPI-Decryptors group with five members beats an "All Extended Rights on the helpdesk OU" delegation with five hundred -- but it does not move the bound to zero. The directory that stores the LAPS secret remains a tier-0 asset, and the decryptor group remains a tier-0 principal class.

Every recoverable secret has a privileged reader. The architectural game is to make the reader class small, audited, time-bounded, and reachable from the directory only through Kerberos. The game is not to make the reader class empty. That game has no winning move.

Bound 2: the out-of-protocol OPSEC tail. Once a plaintext password leaves the directory -- pasted into a helpdesk ticket, screenshotted into a Slack DM, stored in a shared KeePass database that the team forgot to rotate -- the protocol's rotation knob is the only remaining mitigation. PostAuthenticationActions only fires after the next managed-account interactive logon [13]; pre-logon exposure is bounded only by PasswordAgeDays. A password screenshotted into a chat log at 10:14 AM and never used is the password on that endpoint for the remainder of the configured rotation window, regardless of whether anyone has noticed the leak. The protocol does not, and cannot, solve "the password is now in a chat log."

Bound 3: unmanaged and BYOD endpoints. A machine that is neither AD-joined nor Microsoft Intune-managed has no LAPS policy applied to it. Personal-device BYO MAM scope is outside the LAPS protection model entirely. The fix for these endpoints is enrollment, not LAPS. A non-trivial portion of the residual local-admin-password risk in 2026 is concentrated on the long tail of unmanaged endpoints that exist precisely because management was politically or contractually infeasible. The protocol does not solve this; governance solves this.

Bound 4: verification asymmetry. The directory's audit log says what it chose to log. An unprivileged observer cannot verify enforcement from outside the directory. This is the structural ceiling that motivates external audit primitives -- PingCastle [7], BloodHound [28], Defender for Identity [38] -- because they sit outside the directory's own self-report. The bound cannot be closed inside the protocol; only an out-of-band attestation primitive can certify enforcement to a party that does not trust the directory.

Somebody has to break the glass. The decryptor group is the new tier-0 asset; LAPS bounds the problem, it does not abolish it. The eleven-year arc was a convergence on a tighter bound, not an arrival at a clean answer. The right framing for the 2026 baseline is "the residual attack surface is now the actual attack surface, rather than an artefact of incomplete shipping." That is real progress -- it just is not closure.

Some of those structural bounds map onto open problems with no clean 2026 answer. We close on six of them.

10. Open Problems in 2026

Six open problems in local-admin password management for which no first-party Microsoft answer ships in 2026. Each is one paragraph, framed as "what is the question," "what has been tried," and "what is the current best partial result."

Open questionWhat has been triedCurrent best partial result
Legacy SYSVOL cpassword cleanup at scaleMS14-025 (UI disable, no remediation); PingCastle scanning; community Get-GPPDeployedPasswordsThird-party scan-and-manual-delete; no first-party cmdlet ships in the OS
Cross-tenant / cross-directory LAPS coverage reportMicrosoft Intune compliance reports; manual Get-LapsADPassword and Get-LapsAADPassword joinsDIY KQL across two directories; no unified portal report
Hybrid-joined BackupDirectory ambiguityMicrosoft Learn guidance ("AD for hybrid")Most shops configure both and reconcile downstream
Win 11 25H2 Administrator Protection and LAPS interactionTech Community guidance; Microsoft Learn architectural notesOperate them as orthogonal, with no architectural integration
LDAP channel binding / signing enforcement migrationMicrosoft KB4520412 enforcement push 2020-2024; cross-platform tool updatesSome Linux pentest tooling still incomplete; bloodyAD / lapsv2decrypt lead the field [45]
Retrieval-event audit gap (cross-directory)Event 4662 SACL via Set-LapsADAuditing; Entra audit log; Defender for Identity huntingDIY KQL unification across AD + Entra; no unified audit pane

1. Legacy SYSVOL cpassword cleanup at scale. MS14-025 disabled new authoring twelve years ago; it never deleted what it patched [6]. No first-party Find-GPPPassword or Remove-GPPPassword cmdlet ships in the OS in 2026. PingCastle's A-PwdGPO rule and Semperis Purple Knight's equivalent scanner fill the gap [7]. The 2026 answer is: scan with a third-party tool, rotate the discovered credentials in whatever account-management primitive owns them, then delete the XML. The open question is why Microsoft has not shipped this in the twelve years since the bulletin. The blast-radius argument from 2014 -- "we cannot risk auto-deleting policy XMLs from SYSVOL" -- is now strictly weaker than the cleanup-tail argument that the residual artefacts keep showing up on internal pentest reports a decade later.

2. Cross-tenant and cross-directory LAPS coverage view. No portal-level "every Entra-joined and every AD-joined device that does not have a current LAPS password" report exists. Microsoft Intune compliance reports help on the Intune-managed side; Get-LapsADPassword -Identity * covers the AD side; Get-LapsAADPassword covers the Entra side. There is no single pane that unifies them. The 2026 answer is custom KQL or PowerShell that joins the three result sets on a normalised device identifier. The bottleneck is identity: Intune device IDs, AD objectGuid values, and Entra deviceId values are three different surrogate keys, and a fleet's mapping table is its own engineering investment.

3. Hybrid-joined BackupDirectory ambiguity. Microsoft Learn's current guidance is that hybrid-joined devices should typically use BackupDirectory = 2 (AD) when on-premises AD is the canonical identity store, and may use BackupDirectory = 1 (Entra) when Intune is the primary policy-delivery mechanism [33]. In practice, the documentation hedges, and many shops configure both directions (one via GPO, one via Intune CSP) and rely on the per-device evaluation order to pick one. The result is a coverage-verification problem: a device that is "configured for AD backup" by GPO and "configured for Entra backup" by CSP can end up with the password in either backend, and the source of truth depends on policy precedence rules most operators do not memorise.

4. Windows 11 25H2 Administrator Protection and LAPS interaction. Administrator Protection's per-elevation transient admin tokens and Windows LAPS's recoverable break-glass password are operationally adjacent but architecturally disjoint [42]. The documentation covers each feature on its own; the interaction matrix -- "what does a LAPS-managed RID 500 look like under Administrator Protection on a Win 11 25H2 host" -- is not laid out in one place. Tier-0 architects who want both behaviours have to assemble the answer from two product pages.

5. LDAP channel binding and signing enforcement migration. Microsoft has been hardening LDAP channel binding through a multi-year 2020-2024 enforcement push tracked under KB4520412 [45]. The original March 10, 2020 update introduced Channel Binding Token (CBT) signing events 3039, 3040, and 3041; the manual enablement step was removed on November 14, 2023 for Windows Server 2022 and on January 9, 2024 for Windows Server 2019, after which the hardening became the default posture; starting with Windows Server 2022 23H2, all new versions ship with the full set of changes in the KB applied [45]. Tooling that does not speak LDAPS-with-channel-binding will break when enforcement reaches its terminal state. Modern attack-graph tooling -- bloodyAD [46] and the lapsv2decrypt reference implementation [47] -- has tracked the changes. Not every Linux pentest stack has. Practitioners building Linux-based LAPS retrieval pipelines should validate their stack against the channel-binding-required posture before the enforcement wave reaches them.

6. The retrieval-event audit gap (cross-directory). Active Directory does not natively log every read of msLAPS-EncryptedPassword; Set-LapsADAuditing installs a SACL that emits Directory Service event 4662 for configured attribute reads [36]. Microsoft Entra ID logs LAPS retrieval through its own audit log, surfaced via the Graph endpoint [32]. The two log streams have different schemas, different timestamp normalisations, and different principal identifiers. Cross-pane unification of "who read which LAPS password when" across both backends is a DIY engineering problem in 2026. Microsoft Defender for Identity surfaces some of the AD-side reads under the Compromised Credentials and Lateral Movement categories [38] but does not name LAPS specifically in the public alert taxonomy.

The threshold-cryptography open problem (an mm-of-nn Shamir scheme over the LAPS password protector, with m2m \geq 2 in tier-0 fleets) is theoretically closed by the 1979 Shamir secret-sharing construction. The deployment-side block is that no Microsoft-shipped primitive wires the construction to the LAPS rotation pipeline. Adjacent shipping primitives (Azure Managed HSM key-release [43], Azure Confidential Ledger [44]) exist on the Azure side, but the integration with on-premises LAPS clients is not on any public roadmap. The companion posts on DPAPI internals (#20) and Defender for Identity (#87) cover adjacent territory but do not close this gap.

None of those six dissolves the architectural lesson the eleven-year arc taught: the right defaults take a decade to ship. Here is the practitioner field manual for the meantime.

11. Practitioner Field Manual and FAQ

What follows is a seven-step deployment list, three named sidebars that surface the most common misconceptions, and a seven-question FAQ. Lift the step list verbatim into your deployment runbook; the sidebars exist because the article would not be defensible without them.

The audit-and-migrate seven-step list

  1. Audit SYSVOL for cpassword first. Run PingCastle's A-PwdGPO (MITRE T1552.006) [@pingcastle-rules; @mitre-t1552-006] before touching anything else. A Windows triage one-liner -- findstr /s /i cpassword \\domain\SYSVOL\*.xml -- will land on most environments in under a minute. Remediate the discovered XML files (rotate the underlying account passwords, then delete the XMLs) before deploying Windows LAPS so the attack surface and the defence are not co-evolving in the same window.
  2. Extend the AD schema for Windows LAPS. Run Update-LapsADSchema once per forest from a Domain Admin context. The cmdlet is idempotent and coexists with the legacy ms-Mcs-AdmPwd attribute on the same Computer object [30].
  3. Delegate. Run Set-LapsADComputerSelfPermission on each target OU so that computer accounts can write their own msLAPS-* attributes. Audit existing "All Extended Rights" delegations with Find-LapsADExtendedRights and remove any that do not have an explicit operational justification [48]. This is the legacy-LAPS lesson applied to the new attribute set.
  4. Configure encryption-at-rest. Verify that the forest's Domain Functional Level is Windows Server 2016 or higher. Configure ADPasswordEncryptionEnabled = 1 explicitly even though the default is True -- the explicit configuration makes the choice visible in policy audits and forces the operator to verify the DFL prerequisite [13]. Assign ADPasswordEncryptionPrincipal to a dedicated LAPS-DPAPI-Decryptors group, not Domain Admins [29].
  5. Deploy policy. GPO for AD-joined, Intune CSP for Entra-joined and hybrid-joined [34]. Settings as per section 7's baseline table. Validate via Get-LapsADPassword -Identity <computer> against a representative sample of hosts after the first one-hour rotation timer has fired [49].
  6. Migrate from legacy LAPS. Use the documented coexistence pattern: the legacy MSI's CSE keeps running against the built-in RID 500, the new in-box LAPS takes over against a named secondary local-admin account, then retire the legacy ms-Mcs-AdmPwd schema readers and uninstall the MSI once Windows LAPS coverage is verified [30]. The legacy MSI's installation is blocked on Windows 11 23H2 and later [26].
  7. Continuous audit. PingCastle for coverage rules (A-LAPS-Not-Installed, A-LAPS-Joined-Computers, and the GPP A-PwdGPO) [7]; BloodHound for the ReadLAPSPassword edge across the graph [28]; Defender for Identity for downstream behaviour under Compromised Credentials and Lateral Movement [38]; and a custom KQL on the Entra audit log for LapsPasswordRetrieved events. None of these is optional in a deployment that intends to detect compromise.

A recurring misattribution credits MS16-072 / KB3163622 / CVE-2016-3223 (June 14, 2016) [@ms16-072-bulletin; @ms16-072-kb; @cve-2016-3223] with closing the legacy LAPS attribute-readability issue. It does not. MS16-072 is a Group Policy retrieval-context fix: it moved user-side GPO fetch into the computer's security context to defeat a man-in-the-middle class on policy traffic. The actual LAPS attribute-readability issue -- "All Extended Rights" delegations silently including CONTROL_ACCESS on the CONFIDENTIAL ms-Mcs-AdmPwd attribute -- has no Microsoft-assigned CVE or bulletin. The canonical write-up is Sean Metcalf's August 2016 ADSecurity piece [9], and the operational primitive is SpecterOps's ReadLAPSPassword BloodHound edge [28].

Microsoft Entra hybrid joined devices are workstations joined to both an on-premises AD domain and Microsoft Entra ID. The LAPS conversation about hybrid joined is a BackupDirectory choice. Microsoft Entra hybrid runbook workers, on the other hand, are an Azure Automation primitive -- worker processes that execute Automation runbooks against on-premises resources. They share a word and nothing else. A LAPS policy targeted at "hybrid devices" means hybrid joined; it has nothing to do with hybrid runbook workers. The article's section 8 includes the same disambiguation because operators conflate them with surprising frequency.

MS14-025 disabled new authoring but did not delete the artefacts [6]. The artefacts persist because SYSVOL replication is conservative -- nothing in the forest's design deletes anything from SYSVOL just because the editor UI was hot-patched on the administrative workstation. A fresh PingCastle scan against a long-lived forest will routinely surface 2010-era Groups.xml files [7], and the third-party scanner cohort is the only practical defence. The one-shot remediation pattern is: find with A-PwdGPO, rotate the underlying password via the replacement tool (Windows LAPS for built-in local admin; a PAM vault for service accounts that were stored in GPP), then delete the Groups.xml and let SYSVOL replication propagate the deletion.

Frequently asked questions

Does Windows 11 25H2 Administrator Protection replace LAPS?

No. Administrator Protection addresses in-session UAC-class elevation by brokering each elevation through a per-elevation transient shadow-admin identity [42]; it does not provide a recoverable break-glass password for an off-network or non-bootable endpoint. The two systems are orthogonal and Microsoft recommends running them together on Windows 11 25H2 fleets. Replacing LAPS with Administrator Protection produces designs that lose the recovery primitive for laptops that have wandered off the corporate network for a year.

If I encrypt with DPAPI-NG, why do I still need to delegate the AD ACL tightly?

Defence in depth, plus a coverage-leak primitive. An LDAP reader who is not in ADPasswordEncryptionPrincipal gets only an opaque ciphertext blob [29] -- but the same reader can still enumerate which computer objects have a current msLAPS-EncryptedPassword, which gives them target-selection telemetry on managed-versus-unmanaged hosts. The canonical write-up of this class is Sean Metcalf's August 2016 ADSecurity piece on the legacy ms-Mcs-AdmPwdExpirationTime attribute [9], and the architectural lesson carries forward to Windows LAPS unchanged.

Can attackers still decrypt cpassword in 2026?

Yes, in seconds. The 32-byte AES-256-CBC key is published verbatim in [MS-GPPREF] section 2.2.1.1.4 of Microsoft's Open Specifications corpus [2] and that publication is permanent under the Open Specifications Promise. Any residual Groups.xml (or five sibling carriers including the asymmetric Printers.xml [21]) in SYSVOL that contains a cpassword attribute is operationally plaintext. The 2026 answer is to find them with PingCastle's A-PwdGPO rule [7] and remediate -- not to expect the artefacts to expire on their own.

Will Windows LAPS rotate the password on every login?

No. The rotation cycle is the PasswordAgeDays interval (default 30 days, minimum 1 on AD backup, minimum 7 on Entra backup) [13]. After authentication, PostAuthenticationActions (default 3 = reset + sign out) fires once the PostAuthenticationResetDelay window (default 24 hours) has elapsed. Value 11 (Windows 11 24H2 / Server 2025+) adds termination of remaining processes; it is not a forced shutdown without warning -- the standard two-minute warning still applies and SMB sessions are deleted.

Does LAPS work for the built-in Administrator (RID 500) when the account is disabled?

Yes. LAPS rotates the password on a disabled account; the account simply cannot be used to log on until it is enabled. The break-glass runbook is: enable the account, retrieve the LAPS password, perform the recovery, rotate immediately, re-disable. On Windows 11 24H2 and Windows Server 2025 and later, Microsoft's recommendation is to enable Automatic Account Management with a randomised name and AutomaticAccountManagementEnableAccount = 0 so the managed account ships disabled-by-default with a non-predictable name [39]. The pattern defeats predictable-RID-500 enumeration entirely.

Where does the password go for an Entra-joined device with no on-prem AD?

Microsoft Entra ID. With BackupDirectory = 1 [13], the local LAPS component posts the rotated password to the deviceLocalCredentials resource on the Entra device object via Microsoft Graph [32]. Retrieval is via Get-LapsAADPassword (a wrapper around the Graph endpoint), the Microsoft Entra portal Devices blade, or a direct GET /directory/deviceLocalCredentials/{deviceId} call [33]. Read permission requires the Cloud Device Administrator or Intune Service Administrator Entra role.

Is the BloodHound LAPS edge called CanReadGMSAPassword?

No. CanReadGMSAPassword is the edge for Group Managed Service Accounts -- a different Active Directory feature with a different ACL on a different attribute (msDS-GroupMSAMembership). The correct LAPS edge is ReadLAPSPassword, introduced in BloodHound 2.0 on August 7, 2018 [10], and the current edge documentation covers both the legacy ms-Mcs-AdmPwd and the modern msLAPS-* attribute paths [28].

The companion posts in this series cover Pass-the-Hash itself (#76), DPAPI internals (#20), Microsoft Entra Privileged Identity Management (#90), Active Directory tiering (#72), Microsoft Defender for Identity (#87), and BloodHound (#77). Each of those is referenced in this article at the point where the topic would otherwise demand a digression; each has its own deep treatment elsewhere.

Twenty years. Eleven years of which separated Microsoft's December 2012 articulation of the architecture from the April 11, 2023 in-box default [@ms-pth-whitepaper; @tc-windows-laps-ga-2023]. Four residual attack surfaces -- delegated-decryptor compromise, the pre-rotation OPSEC tail, BYOD endpoints, and the multi-decade MS14-025 cleanup tail [6] -- still resist the architecture rather than fall to it. One through-line: this is what shipping the right default a decade late looks like. The right defaults are now in the box. The directory is still tier 0. Somebody still has to break the glass. The architectural game from here is not to invent a new generation; it is to make sure the one we finally have is actually deployed, audited, and clean.

References

  1. Chris Campbell (2012). GPP Password Retrieval with PowerShell. https://obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
  2. Microsoft [MS-GPPREF]: Group Policy: Preferences Extension Data Structure -- 2.2.1.1.4 Password Encryption. https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gppref/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be
  3. Microsoft (2023). By popular demand: Windows LAPS available now!. https://techcommunity.microsoft.com/blog/windows-itpro-blog/by-popular-demand-windows-laps-available-now/3788747
  4. Microsoft (2012). Mitigating Pass-the-Hash (PtH) Attacks and Other Credential Theft Techniques (whitepaper). https://www.microsoft.com/en-us/download/details.aspx?id=36036
  5. MITRE ATT&CK T1550.002 -- Use Alternate Authentication Material: Pass the Hash. https://attack.mitre.org/techniques/T1550/002/
  6. Emilien Girault (2012). Exploiting Windows 2008 Group Policy Preferences -- Sogeti ESEC (Wayback). https://web.archive.org/web/2012/http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
  7. Ben Campbell (2012). Exploiting Windows 2008 Group Policy Preferences (rewtdance). https://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
  8. Ben Campbell, Loic Jaquemet, scriptmonkey, theLightCosine, & mubix Metasploit post/windows/gather/credentials/gpp.rb (source). https://raw.githubusercontent.com/rapid7/metasploit-framework/master/modules/post/windows/gather/credentials/gpp.rb
  9. Microsoft (2014). Microsoft Security Bulletin MS14-025 -- Vulnerability in Group Policy Preferences Could Allow Elevation of Privilege (2962486). https://learn.microsoft.com/en-us/security-updates/securitybulletins/2014/ms14-025
  10. Vincent Le Toux PingCastle Active Directory Healthcheck Rules List. https://www.pingcastle.com/PingCastleFiles/ad_hc_rules_list.html
  11. Microsoft (2015). Microsoft Security Advisory 3062591 -- Local Administrator Password Solution (LAPS) Now Available (Wayback). https://web.archive.org/web/20160325192229/https://technet.microsoft.com/en-us/library/security/3062591.aspx
  12. Sean Metcalf (2016). Securing Windows Workstations: Developing a Secure Baseline -- LAPS attribute readability. https://adsecurity.org/?p=3164
  13. Andy Robbins (2018). BloodHound 2.0. https://specterops.io/blog/2018/08/07/bloodhound-2-0/
  14. Microsoft What is Windows LAPS?. https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-overview
  15. Microsoft (2023). Windows Local Administrator Password Solution with Microsoft Entra ID is now generally available. https://techcommunity.microsoft.com/t5/microsoft-entra-azure-ad-blog/windows-local-administrator-password-solution-with-microsoft/ba-p/3911999
  16. Microsoft Configure policy settings for Windows LAPS. https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-management-policy-settings
  17. Sean Metcalf (2015). Finding Passwords in SYSVOL & Exploiting Group Policy Preferences. https://adsecurity.org/?p=2288
  18. MITRE ATT&CK T1078.001 -- Valid Accounts: Default Accounts. https://attack.mitre.org/techniques/T1078/001/
  19. KuppingerCole Analysts Jonathan Cogley -- Speaker profile (Thycotic founder, 1996). https://www.kuppingercole.com/speakers/985
  20. Wikipedia contributors Lieberman Software. https://en.wikipedia.org/wiki/Lieberman_Software
  21. Wikipedia contributors Quest Software. https://en.wikipedia.org/wiki/Quest_Software
  22. Los Angeles Times (1999). Quest Software Surges in Wall Street Debut. https://www.latimes.com/archives/la-xpm-1999-aug-14-ca-65519-story.html
  23. Linda Moore (2009). Passwords in Group Policy Preferences (Updated) -- Group Policy Team blog (Wayback). https://web.archive.org/web/20160421193157/https://blogs.technet.microsoft.com/grouppolicy/2009/04/22/passwords-in-group-policy-preferences-updated/
  24. Chris Campbell PowerSploit Get-GPPPassword.ps1 (source). https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Get-GPPPassword.ps1
  25. Joshua D. Abraham Metasploit auxiliary/scanner/smb/smb_enum_gpp.rb (source). https://raw.githubusercontent.com/rapid7/metasploit-framework/master/modules/auxiliary/scanner/smb/smb_enum_gpp.rb
  26. MITRE ATT&CK T1552.006 -- Unsecured Credentials: Group Policy Preferences. https://attack.mitre.org/techniques/T1552/006/
  27. Microsoft (2014). KB2962486 -- MS14-025: Vulnerability in Group Policy Preferences could allow elevation of privilege. https://support.microsoft.com/kb/2962486
  28. Microsoft Local Administrator Password Solution (legacy MSI download). https://www.microsoft.com/en-us/download/details.aspx?id=46899
  29. Jiri Formacek jformacek/admpwd (GitHub repository). https://github.com/jformacek/admpwd
  30. Microsoft (2016). Microsoft Security Bulletin MS16-072 -- Security Update for Group Policy (3163622). https://learn.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-072
  31. Microsoft (2016). KB3163622 -- MS16-072 changes the security context with which user group policies are retrieved. https://support.microsoft.com/kb/3163622
  32. MITRE CVE-2016-3223 -- Group Policy elevation of privilege via MITM. https://www.cve.org/CVERecord?id=CVE-2016-3223
  33. SpecterOps BloodHound edge: ReadLAPSPassword. https://bloodhound.specterops.io/resources/edges/read-laps-password
  34. Microsoft Windows LAPS architecture. https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-concepts-overview
  35. Microsoft Windows LAPS migration scenarios. https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-scenarios-migration
  36. Microsoft CNG DPAPI. https://learn.microsoft.com/en-us/windows/win32/seccng/cng-dpapi
  37. Microsoft Windows LAPS for Microsoft Entra ID scenarios. https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-scenarios-azure-active-directory
  38. Microsoft Microsoft Graph -- deviceLocalCredentialInfo: get. https://learn.microsoft.com/en-us/graph/api/devicelocalcredentialinfo-get
  39. Microsoft LAPS Configuration Service Provider (CSP). https://learn.microsoft.com/en-us/windows/client-management/mdm/laps-csp
  40. Microsoft Windows LAPS account management modes. https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-concepts-account-management-modes
  41. Microsoft Windows LAPS passwords and passphrases. https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-concepts-passwords-passphrases
  42. Electronic Frontier Foundation EFF Dice-Generated Passphrases. https://www.eff.org/dice
  43. Joseph Bonneau (2016). EFFs New Wordlists for Random Passphrases. https://www.eff.org/deeplinks/2016/07/new-wordlists-random-passphrases
  44. Microsoft Manage Windows LAPS by using PowerShell. https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-management-powershell
  45. Microsoft Get-LapsADPassword (PowerShell reference). https://learn.microsoft.com/en-us/powershell/module/laps/get-lapsadpassword
  46. Microsoft Set-LapsADAuditing (PowerShell reference). https://learn.microsoft.com/en-us/powershell/module/laps/set-lapsadauditing
  47. Microsoft Configure Microsoft Entra Privileged Identity Management. https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-configure
  48. Microsoft Microsoft Defender for Identity security alerts. https://learn.microsoft.com/en-us/defender-for-identity/alerts-overview
  49. Delinea Secret Server. https://delinea.com/products/secret-server
  50. CyberArk Endpoint Privilege Manager. https://www.cyberark.com/products/endpoint-privilege-manager/
  51. Microsoft Administrator protection on Windows 11. https://techcommunity.microsoft.com/blog/windows-itpro-blog/administrator-protection-on-windows-11/4303482
  52. Microsoft Azure Key Vault Managed HSM secure key release policy grammar. https://learn.microsoft.com/en-us/azure/key-vault/managed-hsm/policy-grammar
  53. Microsoft Azure Confidential Ledger overview. https://learn.microsoft.com/en-us/azure/confidential-ledger/overview
  54. Microsoft 2020, 2023 and 2024 LDAP channel binding and LDAP signing requirements for Windows (KB4520412). https://support.microsoft.com/en-us/topic/2020-2023-and-2024-ldap-channel-binding-and-ldap-signing-requirements-for-windows-kb4520412-ef185fb8-00f7-167d-744c-f299a66fc00a
  55. CravateRouge bloodyAD -- Active Directory privilege escalation swiss army knife (GitHub). https://github.com/CravateRouge/bloodyAD
  56. Adam Chester lapsv2decrypt -- Windows LAPS v2 encrypted-blob decryptor (GitHub). https://github.com/xpn/RandomTSScripts/tree/master/lapsv2decrypt