Handling Unicode Username Substitution in Windows Active Directory Authentication


2 views

When working with Windows Active Directory authentication, you might encounter a peculiar behavior where usernames containing special Unicode characters (like š, č, or ž) can authenticate successfully even when the actual AD account uses their ASCII equivalents. This occurs because of Windows' built-in character normalization during authentication.

The Windows authentication subsystem implements Unicode normalization when processing usernames. Specifically:

  • Non-ASCII characters in usernames are converted to their closest ASCII equivalents
  • This happens before the authentication request reaches the domain controller
  • The conversion follows Windows' internal character mapping tables

For example, these username variations would all resolve to the same AD account:

myšpecialuser → myspecialuser
mýspecialuser → myspecialuser
myßpecialuser → myspecialuser

Microsoft implemented this feature for backward compatibility and user convenience in international environments. However, for security-conscious organizations, this can create potential issues:

  • Multiple username variations can access the same account
  • Possible confusion in audit logs where different forms appear
  • Potential for user impersonation in some scenarios

To enforce strict username matching, you can modify the following registry setting on domain controllers:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
"DisableUnicodeCharacterTranslation"=dword:00000001

After applying this change, you'll need to:

  1. Restart the domain controller
  2. Clear the Kerberos ticket cache (klist purge) on client machines

You can test the behavior change with this PowerShell script:

# Test Unicode username authentication
function Test-ADUnicodeAuth {
    param(
        [string]$Username,
        [string]$Password
    )

    $cred = New-Object System.Management.Automation.PSCredential(
        $Username,
        (ConvertTo-SecureString $Password -AsPlainText -Force)
    )

    try {
        Start-Process -FilePath "cmd.exe" -Credential $cred -NoNewWindow -ErrorAction Stop
        Write-Host "Authentication SUCCESSFUL for $Username"
    } catch {
        Write-Host "Authentication FAILED for $Username"
    }
}

# Test with both Unicode and ASCII versions
Test-ADUnicodeAuth -Username "myšpecialuser" -Password "P@ssw0rd"
Test-ADUnicodeAuth -Username "myspecialuser" -Password "P@ssw0rd"

For organizations that need to maintain this behavior but want better control, consider modifying the userPrincipalName attribute in AD to include both forms:

# PowerShell: Add alternative UPN suffixes
Get-ADUser -Identity myspecialuser | Set-ADUser -Add @{
    "proxyAddresses" = "SMTP:myšpecialuser@domain.com"
}

When disabling Unicode substitution, be aware of these implications:

  • Users with non-ASCII characters in their actual usernames will be affected
  • Existing scripts or applications relying on the substitution behavior may break
  • Multi-forest environments might require consistent configuration across all domains

In Windows Active Directory (AD), you might encounter a puzzling scenario: users can log in with special characters (e.g., myšpecialuser) even when the actual username doesn't contain those characters (e.g., myspecialuser). This happens because Windows performs character normalization during authentication, treating certain special characters as their ASCII equivalents.

Windows uses the NormalizeString API during authentication, which follows Unicode normalization rules. For example:

  • š (U+0161) may be normalized to s
  • é (U+00E9) may become e

This behavior is intentional for usability but can create security concerns when strict username matching is required.

To enforce exact username matching, you can modify the msDS-Other-Settings attribute in AD:

# PowerShell: Disable normalization for a specific domain
Set-ADObject -Identity "DC=yourdomain,DC=com" -Replace @{
    "msDS-Other-Settings" = "AllowUnicodeCharacters=0"
}

Or via Group Policy:

  1. Open gpedit.msc
  2. Navigate to: Computer Configuration → Windows Settings → Security Settings → Local Policies → Security Options
  3. Set "Network security: Do not allow anonymous enumeration of SAM accounts" to Enabled

Test with PowerShell to confirm normalization is disabled:

# Attempt login with normalized characters
$cred = New-Object System.Management.Automation.PSCredential("myšpecialuser", (ConvertTo-SecureString "Password123" -AsPlainText -Force))
try {
    Start-Process -FilePath "cmd.exe" -Credential $cred -NoNewWindow -ErrorAction Stop
    Write-Host "Login succeeded (normalization active)"
} catch {
    Write-Host "Login failed (normalization disabled)"
}

For applications, implement strict validation:

// C# example: Validate exact username match
public bool ValidateUsername(string inputUsername, string adUsername) 
{
    return string.Compare(inputUsername, adUsername, 
                         StringComparison.Ordinal) == 0;
}

While disabling normalization improves accuracy, consider:

  • Potential impact on legitimate users with special characters
  • Whether to apply this setting domain-wide or per-application
  • Audit logs to monitor login attempts with normalized characters