Private/ConvertFrom-KrbAccountControl.ps1
|
#Requires -Version 7.4 function ConvertFrom-KrbAccountControl { <# .SYNOPSIS Extracts the userAccountControl flags that affect Kerberos encryption type selection .DESCRIPTION userAccountControl carries several bits that change how the KDC treats an account's encryption types, and they are not visible in msDS-SupportedEncryptionTypes at all. An assessment that reads only the encryption-type attribute will misjudge every account that has one of these set. The four that matter here: - USE_DES_KEY_ONLY (0x200000). Overrides the encryption-type attribute entirely and confines the account to single DES. Windows Server 2008 R2 and later refuse DES by default, so an account carrying this bit is usually already broken or is being kept alive by a domain-wide DES allowance that hardening will remove. Clearing the bit is not sufficient on its own - the password must also be reset, because no AES key was ever derived. - NOT_DELEGATED, TRUSTED_FOR_DELEGATION and TRUSTED_TO_AUTH_FOR_DELEGATION. A delegation-enabled account fans an encryption-type failure out across every backend it reaches, so its blast radius is larger than its own client count suggests. - DONT_REQUIRE_PREAUTH (0x400000). Pre-authentication is where the client's chosen encryption type is exercised, so an account that skips it produces no PreAuthEncryptionType evidence and has to be assessed from service tickets alone. - ACCOUNTDISABLE (0x2). A disabled account cannot break anything, and including disabled accounts in a risk count is the fastest way to make a report look alarming and be ignored. .PARAMETER UserAccountControl [System.Object] (Mandatory, Pipeline: ByValue) The raw userAccountControl value. .EXAMPLE PS> ConvertFrom-KrbAccountControl -UserAccountControl 2097664 DESCRIPTION: Decodes an account with USE_DES_KEY_ONLY set OUTPUT: UseDesKeyOnly true, alongside the other Kerberos-relevant flags USE CASE: Explaining why an account's encryption-type attribute is being ignored by the KDC .OUTPUTS KrbEtypeInsight.AccountControl .NOTES Author: Jeffrey Stuhr Blog: https://www.techbyjeff.net LinkedIn: https://www.linkedin.com/in/jeffrey-stuhr-034214aa/ TROUBLESHOOTING: - DES-only accounts: .\Troubleshooting\Common\DES-Only-Accounts.md .LINK MS-ADTS 2.2.16, userAccountControl bit values https://learn.microsoft.com/openspecs/windows_protocols/ms-adts/1446ae76-b9d5-4d4c-bf7f-1c7e26f47d9e #> [CmdletBinding()] [OutputType('KrbEtypeInsight.AccountControl')] param( [Parameter(Mandatory, ValueFromPipeline)] [AllowNull()] [object]$UserAccountControl ) process { $uac = ConvertTo-KrbInt32 -Value $UserAccountControl if ($null -eq $uac) { # Absent means not read, not zero. Every flag comes back null so that a caller # cannot conclude "delegation is not enabled" from an attribute it never asked for. return [PSCustomObject]@{ PSTypeName = 'KrbEtypeInsight.AccountControl' Value = $null Disabled = $null UseDesKeyOnly = $null DontRequirePreAuth = $null TrustedForDelegation = $null TrustedToAuthForDelegation = $null NotDelegated = $null PasswordNeverExpires = $null IsWorkstationTrust = $null IsServerTrust = $null IsInterdomainTrust = $null } } [PSCustomObject]@{ PSTypeName = 'KrbEtypeInsight.AccountControl' Value = $uac Disabled = [bool]($uac -band 0x0000002) UseDesKeyOnly = [bool]($uac -band 0x0200000) DontRequirePreAuth = [bool]($uac -band 0x0400000) TrustedForDelegation = [bool]($uac -band 0x0080000) TrustedToAuthForDelegation = [bool]($uac -band 0x1000000) NotDelegated = [bool]($uac -band 0x0100000) PasswordNeverExpires = [bool]($uac -band 0x0010000) IsWorkstationTrust = [bool]($uac -band 0x0001000) IsServerTrust = [bool]($uac -band 0x0002000) IsInterdomainTrust = [bool]($uac -band 0x0000800) } } } |