LAPSPassword
Summary
Description
Identification
function Find-LAPSPassword {
[CmdletBinding()]
param ( [string]$SearchBase = $null,[string]$OutputPath = "LAPSPassword.csv")
# Load ActiveDirectory module if not already loaded
Import-Module ActiveDirectory
Write-Host "Gathering Active Directory computer objects and inspecting ACLs for explicit LAPS password read permissions..."
# Access Control Type of Access Control Entry (Allow)
$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow;
# Active Directory Rights of Access Control Entry (ExtendedRight is used for specific GUIDs)
$ActiveDirectoryRights = [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight;
$LAPSPasswordPermissionGuid = $null
try {
$RootDSE = [ADSI]"LDAP://RootDSE"
$SchemaNamingContext = $RootDSE.schemaNamingContext
$msMcsAdmPwdAttr = [ADSI]"LDAP://CN=ms-Mcs-AdmPwd,$SchemaNamingContext"
$LAPSPasswordPermissionGuid = New-Object System.Guid($msMcsAdmPwdAttr.schemaIDGUID)
if ($LAPSPasswordPermissionGuid -eq '00000000-0000-0000-0000-000000000000'){
Throw "ms-Mcs-AdmPwd attribute cannot be found. Ensure LAPS is successfully installed and schema is extended."
}
Write-Host "Successfully retrieved LAPS password attribute GUID: '$LAPSPasswordPermissionGuid'."
}
catch {
Write-Error "Failed to retrieve LAPS password attribute GUID. $($_.Exception.Message)"
Write-Error "Cannot proceed. Please ensure LAPS is installed and the schema is extended, and you have permissions to read the schema."
return
}
$adComputerParams = @{
Filter = "*"
Properties = "nTSecurityDescriptor"
ErrorAction = "Stop"
}
if ($SearchBase) {
$adComputerParams.Add("SearchBase", $SearchBase)
Write-Host "Searching for computer objects within '$SearchBase'."
} else {
Write-Host "Searching for all computer objects in the domain."
}
$foundAcls = @()
try {
$objectsToScan = Get-ADComputer @adComputerParams
if (-not $objectsToScan) {
Write-Output "No Active Directory computer objects found matching the criteria."
return
}
foreach ($obj in $objectsToScan) {
$ComputerDistinguishedName = $obj.DistinguishedName;
try {
$acl = Get-Acl -Path "AD:$ComputerDistinguishedName"
foreach ($ace in $acl.Access) {
if ($ace.AccessControlType -eq $AccessControlType -and
($ace.ActiveDirectoryRights -band $ActiveDirectoryRights) -and # Use -band for bitwise comparison
($ace.ObjectType -eq $LAPSPasswordPermissionGuid)) {
$foundAcls += [PSCustomObject]@{
'Vulnerable Computer' = $ComputerDistinguishedName
'Internal Threat' = $ace.IdentityReference.Value
}
}
}
}
catch {
Write-Warning "Could not retrieve ACL for '$ComputerDistinguishedName': $($_.Exception.Message)"}
}
}
catch {
Write-Error "Failed to retrieve Active Directory computer objects: $($_.Exception.Message)"
return
}
# Export the results to CSV if any were found
if ($foundAcls.Count -gt 0) {
Write-Host "Found $($foundAcls.Count) Active Directory computer object(s) with explicit LAPS password read permissions (excluding default admin groups and built-in accounts)."
try {
# Filter out duplicate entries before exporting based on both columns
$foundAcls | Sort-Object -Unique 'Vulnerable Computer', 'Internal Threat' | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
Write-Output "Results exported successfully to '$OutputPath'"
}
catch {
Write-Error "Failed to export results to CSV file '$OutputPath': $($_.Exception.Message)"
}
} else {
Write-Output "No Active Directory computer objects found with explicit LAPS password read permissions (excluding default admin groups and built-in accounts)."
}
}Exploitation
Windows


Linux


Mitigation


Detection
Event ID
Description
Fields/Attributes
References
References
Last updated
Was this helpful?
