SyncLAPSPassword
SyncLAPSPassword
Summary
FSProtect ACL Alias
SyncLAPSPassword
AD Alias
Replicating Directory Changes and Replicating Directory Changes in Filtered Set
Affected Object Types
Domains
Exploitation Certainty
Certain
AD Right
Extended Right
AD Permission Guid
1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 and 89e95b76-444d-4c62-991a-0facbeda640c
Description
The SyncLAPSPassword
permission in Active Directory (AD) grants an account the ability to query and synchronize credentials managed by the Local Administrator Password Solution (LAPS). LAPS periodically randomizes and stores local administrator account passwords in AD attributes (e.g., msLAPS-Password
), mitigating credential theft and lateral movement. When properly controlled with strict DACL configurations, this permission ensures that only authorized security principals can access these sensitive credentials, preserving LAPS’s security benefits.
However, if SyncLAPSPassword
is misconfigured, it poses a critical security risk. A malicious actor who obtains this right can enumerate all LAPS-managed passwords, thereby gaining local administrative access to numerous domain-joined systems. Leveraging these credentials, the attacker can execute lateral attacks, exfiltrate sensitive data, and establish persistent footholds. Ultimately, this exploitation can facilitate unauthorized access, enable privilege escalation, and lead to a complete compromise of the network’s integrity.
Identification
PowerShell
Active Directory Module
Using the ActiveDirectory PowerShell module, you can enumerate SyncLAPSPassword
entries.
1. Find-SyncLAPSPassword function
function Find-SyncLAPSPassword {
[CmdletBinding()]
param ( [string]$OutputPath = "SyncLAPSPassword.csv")
Import-Module ActiveDirectory -ErrorAction Stop
Write-Host "Gathering Active Directory domain ACLs and inspecting for explicit DS-Replication-Get-Changes and DS-Replication-Get-Changes-Filtered permissions..."
$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow;
$ActiveDirectoryRights = [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight;
# Guids of DS-Replication-Get-Changes and DS-Replication-Get-Changes-Filtered permissions
# https://learn.microsoft.com/en-us/windows/win32/adschema/r-ds-replication-get-changes
$DSReplicationGuid = "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2";
# https://learn.microsoft.com/en-us/windows/win32/adschema/r-ds-replication-get-changes-filtered
$DSReplicationFilteredGuid = "89e95b76-444d-4c62-991a-0facbeda640c";
$TargetDistinguishedName = $null
try {
$TargetDistinguishedName = (Get-ADDomain).DistinguishedName
Write-Host "Targeting current domain: '$TargetDistinguishedName'."
}
catch {
Write-Error "Failed to determine the current domain's Distinguished Name. Cannot proceed."
return
}
$foundAcls = @()
try {
$aces = (Get-Acl -Path "AD:$TargetDistinguishedName").Access |
Where-Object {
$_.AccessControlType -eq $AccessControlType -and
($_.ActiveDirectoryRights -band $ActiveDirectoryRights)
}
$aces |
Group-Object -Property IdentityReference |
Where-Object {
($_.Group.ObjectType -contains $DSReplicationGuid) -and
($_.Group.ObjectType -contains $DSReplicationFilteredGuid)
} |
ForEach-Object {
$foundAcls += [PSCustomObject]@{
'Domain' = $TargetDistinguishedName
'Internal Threat' = $_.Name
}
}
}
catch {
Write-Error "Failed to retrieve ACL for '$TargetDistinguishedName' or process permissions: $($_.Exception.Message)"
return
}
if ($foundAcls.Count -gt 0) {
Write-Host "Found $($foundAcls.Count) security principal(s) with explicit DS-Replication-Get-Changes and DS-Replication-Get-Changes-Filtered permissions on '$TargetDistinguishedName' (excluding default admin groups and built-in accounts)."
try {
$foundAcls | Sort-Object -Unique Domain, '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 security principals found with explicit DS-Replication-Get-Changes and DS-Replication-Get-Changes-Filtered permissions on '$TargetDistinguishedName' (excluding default admin groups and built-in accounts)."
}
}
2. Scan the domain
Find-SyncLAPSPassword
.NET Directory Services
By leveraging PowerShell’s built-in .NET DirectoryServices namespace, you can enumerate SyncLAPSPassword
entries without relying on any external modules or dependencies.
1. Find-SyncLAPSPasswordSimple function
function Find-SyncLAPSPasswordSimple {
[CmdletBinding()]
param( [string]$Target = $null, [string]$OutputPath = "SyncLAPSPassword.csv")
$allowType = [System.Security.AccessControl.AccessControlType]::Allow
$extRight = [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight
$getChanges = [guid]"1131f6aa-9c07-11d1-f79f-00c04fc2dcd2"
$getFilt = [guid]"89e95b76-444d-4c62-991a-0facbeda640c"
try {
if ($Target) {
$targetDN = $Target
} else {
$root = New-Object System.DirectoryServices.DirectoryEntry("LDAP://RootDSE")
$targetDN = $root.Properties["defaultNamingContext"].Value
}
$entry = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$targetDN")
}
catch {
Write-Error "Failed to bind to target '$Target': $_"
return
}
try {
$acl = $entry.ObjectSecurity
$aces = $acl.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier])
}
catch {
Write-Error "Failed to read ACL from '$targetDN': $_"
return
}
$seen = @{}
foreach ($ace in $aces) {
if ($ace.AccessControlType -ne $allowType) { continue }
if (-not ($ace.ActiveDirectoryRights -band $extRight)) { continue }
if ($ace.IsInherited) { continue }
$objGuid = [guid]$ace.ObjectType
if (($objGuid -ne $getChanges) -and ($objGuid -ne $getFilt)) { continue }
$who = try { $ace.IdentityReference.Translate([System.Security.Principal.NTAccount]).Value } catch { $ace.IdentityReference.Value }
if (-not $seen.ContainsKey($who)) {
$seen[$who] = New-Object System.Collections.Generic.HashSet[guid]
}
[void]$seen[$who].Add($objGuid)
}
$results = foreach ($k in $seen.Keys) {
if ($seen[$k].Contains($getChanges) -and $seen[$k].Contains($getFilt)) {
[PSCustomObject]@{
Domain = $targetDN
'Internal Threat' = $k
}
}
}
if ($results) {
$results | Sort-Object Domain,'Internal Threat' -Unique | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
} else {
Write-Output "No security principals found with both DS-Replication-Get-Changes and DS-Replication-Get-Changes-Filtered on '$targetDN'."
}
}
2. Scan the domain
Find-SyncLAPSPasswordSimple
Active Directory Users and Computers
1. Open Active Directory Users and Computers
on your Windows server.
2. Right-click on the domain name.
3. Select Properties from the context menu.
4. In the Properties window, navigate to the Security tab.
5. Click on the Advanced button to open the Advanced Security Settings dialog.
6. In the Advanced Security Settings window, locate and select the relevant Access Control Entry (ACE) for the user or group you wish to configure.
7. Click Edit to modify the selected ACE.
8. In the permissions list, locate and check the option Replicating Directory Changes
and Replicating Directory Changes in Filtered Set
.
9. Click OK to save your changes and close the dialogs.

Exploitation
This vulnerability can be exploited on Windows systems using tools like Dirsync, while on Linux systems, tools such as Impacket can be effectively used for exploitation.
Windows
An attacker can perform SyncLAPSPassword
attack with this cmdlet on Windows. (You should download and import DirSync PowerShell module (https://github.com/simondotsh/DirSync) before running the command)
Sync-LAPS -LDAPFilter '(samaccountname=<SAM Account name of Computer>)'
Example:
Sync-LAPS -LDAPFilter '(samaccountname=vm01$)'

Linux
You can open a powershell session and run PowerShell commands on Linux systems with this cmdlet (Impacket tools should be installed before running command)
impacket-psexec '<domain>/<user login name>:<password>@<IP Address>'
Example:
impacket-psexec 'FORESTALL/Attacker:[email protected]'
For PowerShell commands and scripts you can write PowerShell to shell, and it will open PowerShell session.

Mitigation
Access Control Entries identified as dangerous should be removed by following the steps below.
1. Open Active Directory Users and Computers
, and activate the Advanced Features
option.
2. Double-click the affected domain and open Security
tab.
3. In this tab, click Advanced
button and open the dangerous Access Control Entries.
4. Remove the Replicating Directory Changes
and Replicating Directory Changes in Filtered Set
rights.
5. Click the OK
and Apply
buttons to saving changes.

Detection
Adding new Access Control Entries on the Active Directory objects changes the ntSecurityDescriptor
attribute of the objects themselves. These changes can be detected with the 5136 and 4662 Event IDs to identify dangerous modifications.
5136
A directory service object was modified.
AttributeLDAPDisplayName = nTSecurityDescriptor AND ObjectType contains: 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 (DS-Replication-Get-Changes 89e95b76-444d-4c62-991a-0facbeda640c (DS-Replication-Get-Changes-Filtered)
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5136
4662
An operation was performed on an object.
AccessList, AccessMask and ObjectType contains the same two GUIDs above
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662
1644
LDAP query logged
Search filters containing msLAPS-Password and ms-Mcs-AdmPwd
https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/ldap-queries-run-slowly
References
Last updated
Was this helpful?