Debugging “net user /domain” Error 5 (Access Denied) in AD Environments with Modified ACLs


4 views

When your net user username /domain command fails with ERROR_ACCESS_DENIED (5) in an Active Directory environment with customized ACLs, you're likely dealing with permission issues at the SAMR (Security Account Manager Remote) protocol level. The key smoking gun appears in network traces as a failed SAMR OpenDomain call for the BUILTIN domain (S-1-5-32).

Using Wireshark, we can observe the exact failure point:

Frame 33: SAMR Request: OpenDomain
    Opnum: 6
    DomainHandle: 00000000
    DesiredAccess: 0x00020094 (MAXIMUM_ALLOWED)

Frame 34: SAMR Response: OpenDomain
    ReturnCode: STATUS_ACCESS_DENIED (0xC0000022)

The net user command requires these minimum permissions on domain objects:

  • List Contents (LC) - For enumeration
  • Read Properties (RP) - For attribute access
  • Read Permissions (RC) - For security descriptor checks

Here's how to test permissions programmatically:

# Test AD user read permissions
function Test-ADUserReadAccess {
    param(
        [string]$TargetUser,
        [string]$TestUser,
        [string]$DomainController
    )
    
    $cred = Get-Credential -UserName $TestUser -Message "Enter credentials"
    $searcher = New-Object DirectoryServices.DirectorySearcher
    $searcher.SearchRoot = "LDAP://$DomainController"
    $searcher.Filter = "(sAMAccountName=$TargetUser)"
    $searcher.Credential = $cred
    
    try {
        $result = $searcher.FindOne()
        return $true
    }
    catch [System.UnauthorizedAccessException] {
        return $false
    }
}

For environments with strict privacy controls, consider these approaches:

  1. Delegated Auth Endpoint:
    # Create constrained delegation
    dsacls "OU=ServiceAccounts,DC=domain,DC=com" /I:S /G "DOMAIN\QueryService:(RP;WP;LC;;user)"
  2. Attribute-Specific Permissions:
    # Grant read access to specific attributes only
    dsacls "CN=Users,DC=domain,DC=com" /G "DOMAIN\Helpdesk:(RP;;;user)"

Enable detailed auditing on your domain controllers:

auditpol /set /subcategory:"DS Access" /success:enable /failure:enable

Then parse security logs for Event ID 4662 (object access attempts) with XML filtering:

<QueryList>
  <Query Id="0" Path="Security">
    <Select Path="Security">
      *[EventData[Data[@Name='AccessMask'] and (Data='0x20094')]]
    </Select>
  </Query>
</QueryList>

When executing net user username /domain in environments with modified Active Directory ACLs (specifically where Everyone:Read permissions are removed and List Object Mode is enabled), administrators frequently encounter:

System error 5 has occurred.
Access is denied.

Network traces reveal the failure occurs during SAMR protocol operations. Key observations from packet analysis:

Frame 33: SAMR OpenDomain Request for BUILTIN (S-1-5-32)
Frame 34: SAMR Response with STATUS_ACCESS_DENIED (0xC0000022)

The net user command requires these minimum permissions to function properly:

  • DS-List-Contents on the target domain
  • Read Property on user objects
  • Read Property on group objects (for membership enumeration)

This script helps verify effective permissions:

# Requires ActiveDirectory module
Import-Module ActiveDirectory

$userDN = (Get-ADUser $env:USERNAME).DistinguishedName
$acl = Get-Acl "AD:\$userDN"

# Check critical ACEs
$acl.Access | Where-Object {
    $_.IdentityReference -like "*Everyone*" -or
    $_.IdentityReference -like "*Authenticated Users*"
} | Format-Table IdentityReference,AccessControlType,ActiveDirectoryRights

For environments with strict privacy requirements, implement these selective permissions:

# Example: Grant minimum required permissions
dsacls "OU=Users,DC=domain,DC=com" /G "DOMAIN\Helpdesk:(RP;WP;CR;LC;SW;LO;RC;user)"
dsacls "CN=Users,DC=domain,DC=com" /G "DOMAIN\Helpdesk:(RP;WP;CR;LC;SW;LO;RC;user)"

When standard tools fail, consider these approaches:

# LDAP direct query
$searcher = [ADSISearcher]"(samAccountName=$username)"
$searcher.PropertiesToLoad.AddRange("memberOf","displayName")
$result = $searcher.FindOne()

# ADSI COM alternative
$user = [ADSI]"LDAP://CN=$username,CN=Users,DC=domain,DC=com"
$user.Get("memberOf") | ForEach-Object {
    [ADSI]"LDAP://$_" | Select-Object -ExpandProperty name
}