UserAccountControl은 Active Directory(AD)에서 사용자 및 컴퓨터 개체의 가장 핵심적인 속성 중 하나입니다. 이 속성은 계정이 활성 상태인지 잠겨 있는지, 다음 로그온 시 암호 변경 옵션이 설정되어 있는지, 사용자가 암호를 변경할 수 있는지 등 도메인 내 계정의 상태를 결정합니다. 하지만 모든 관리자가 UserAccountControl 속성이 어떻게 동작하고 AD에서 어떤 용도로 사용되는지 정확히 이해하고 있는 것은 아닙니다.
Active Directory의 UserAccountControl 속성/플래그
ADUC(Active Directory 사용자 및 컴퓨터, dsa.msc) 콘솔에서 아무 AD 계정이나 열고 계정(Account) 탭으로 이동해 보세요. 계정 옵션(Account Options) 섹션의 사용자 속성 그룹에 주목하면 다음과 같은 옵션들을 확인할 수 있습니다:
- 다음 로그온 시 사용자가 반드시 암호를 변경해야 함
- 사용자가 암호를 변경할 수 없음
- 암호 만료 없음 — 기본적으로 AD의 도메인 암호 정책은 사용자가 주기적으로 암호를 변경하도록 요구합니다.
- 되돌릴 수 있는 암호화를 사용하여 암호 저장 (보안상 권장하지 않음)
- 계정 사용 안 함
- 대화형 로그온에 스마트 카드 필요
- 계정이 중요하므로 위임할 수 없음
- 이 계정에 Kerberos DES 암호화 유형 사용
- 이 계정이 Kerberos AES 128/256비트 암호화 지원
- Kerberos 사전 인증 필요 없음
이러한 각각의 사용자 계정 속성은 본질적으로 1(True) 또는 0(False) 값을 가질 수 있는 비트 값(플래그)입니다. 그러나 이러한 값들은 별도의 AD 속성으로 저장되지 않고, 대신 UserAccountControl 속성 하나로 관리됩니다.
위에서 언급한 모든 옵션의 총합이 UserAccountControl 속성 값에 저장됩니다. 여러 개별 속성으로 나누어 저장하는 대신 단일 AD 속성을 사용하는 방식입니다. UserAccountControl은 일종의 비트마스크(bitmask)로, 각 비트가 개별 플래그이며 On(True) 또는 Off(False) 값을 가집니다. 활성화된 계정 옵션에 따라 사용자마다 서로 다른 UserAccountControl 값이 부여됩니다. 현재 속성 값은 특성 편집기(Attribute Editor) 탭이나 PowerShell의 Get-ADUser cmdlet을 통해 확인할 수 있습니다:
get-aduser jkelly -properties *|select name,UserAccountControl | ft
이 예제에서 속성 값은 0x10202(10진수로 66050)입니다. 과연 이 숫자들은 무엇을 의미할까요?
UserAccountControl 플래그 표
아래 표는 AD 계정에 사용 가능한 플래그 목록입니다. 각 플래그는 특정 UserAccountControl 비트에 해당하며, 최종 UserAccountControl 값은 모든 플래그 값의 합입니다.
| UserAccountControl 플래그 | HEX 값 | 10진수 값 |
|---|---|---|
| SCRIPT (로그온 스크립트 실행) | 0x0001 | 1 |
| ACCOUNTDISABLE (계정 사용 안 함) | 0x0002 | 2 |
| HOMEDIR_REQUIRED (홈 폴더 필수) | 0x0008 | 8 |
| LOCKOUT (계정 잠김) | 0x0010 | 16 |
| PASSWD_NOTREQD (암호 불필요) | 0x0020 | 32 |
| PASSWD_CANT_CHANGE (사용자의 암호 변경 금지) | 0x0040 | 64 |
| ENCRYPTED_TEXT_PWD_ALLOWED (되돌릴 수 있는 암호화로 암호 저장) | 0x0080 | 128 |
| TEMP_DUPLICATE_ACCOUNT (기본 계정이 다른 도메인에 있는 사용자의 계정) | 0x0100 | 256 |
| NORMAL_ACCOUNT (기본 계정, 일반적인 활성 계정) | 0x0200 | 512 |
| INTERDOMAIN_TRUST_ACCOUNT | 0x0800 | 2048 |
| WORKSTATION_TRUST_ACCOUNT | 0x1000 | 4096 |
| SERVER_TRUST_ACCOUNT | 0x2000 | 8192 |
| DONT_EXPIRE_PASSWORD (암호가 만료되지 않는 사용자 계정) | 0x10000 | 65536 |
| MNS_LOGON_ACCOUNT | 0x20000 | 131072 |
| SMARTCARD_REQUIRED (네트워크 로그온 시 스마트 카드 필요) | 0x40000 | 262144 |
| TRUSTED_FOR_DELEGATION | 0x80000 | 524288 |
| NOT_DELEGATED | 0x100000 | 1048576 |
| USE_DES_KEY_ONLY | 0x200000 | 2097152 |
| DONT_REQ_PREAUTH (Kerberos 사전 인증 불필요) | 0x400000 | 4194304 |
| PASSWORD_EXPIRED (사용자 암호 만료됨) | 0x800000 | 8388608 |
| TRUSTED_TO_AUTH_FOR_DELEGATION | 0x1000000 | 16777216 |
| PARTIAL_SECRETS_ACCOUNT | 0x04000000 | 67108864 |
UserAccountControl 값 계산 예시
예를 들어, 암호 변경 요구 옵션이 비활성화된 일반 계정이 있다고 가정해 보겠습니다. userAccountControl 값은 다음과 같이 계산됩니다:
NORMAL_ACCOUNT (512) + DONT_EXPIRE_PASSWORD (65536) = 66048
따라서 앞선 예제의 userAccountControl 값(66050)은 다음과 같이 구해진 것입니다:
NORMAL_ACCOUNT (512) + DONT_EXPIRE_PASSWORD (65536) + ACCOUNTDISABLE (2) = 66050
비활성화된 사용자 계정의 userAccountControl 값은 514입니다:
NORMAL_ACCOUNT (512) + ACCOUNTDISABLE (2) = 514
참고로, 대표적인 도메인 개체들의 기본 UserAccountControl 값은 다음과 같습니다:
- 일반 AD 사용자: 0x200 (512)
- 도메인 컨트롤러: 0x82000 (532480)
- 워크스테이션/서버: 0x1000 (4096)
LDAP 필터로 특정 계정 조회하기
LDAP 필터를 사용하면 특정 useraccountcontrol 값을 가진 AD 개체만 선택할 수 있습니다. 예를 들어, 활성(일반) 계정만 표시하려면:
Get-ADUser -Properties * -ldapFilter "(useraccountcontrol=512)"
비활성화된 모든 사용자 계정 목록을 표시하려면:
Get-ADUser -Properties * -ldapFilter "(useraccountcontrol=514)"
암호 만료 없음 옵션이 설정된 계정 목록은 다음과 같이 조회합니다:
Get-ADUser -Properties * -ldapFilter "(useraccountcontrol=66048)"
필요한 비트들을 표에서 더한 후 다음 명령으로 AD 개체를 선택할 수도 있습니다:
$UserAccountControl_hex= 0x10000 + 0x0080 + 0x200000
Get-ADUser -Filter {UserAccountControl -band $UserAccountControl_hex}
PowerShell 스크립트로 UserAccountControl 값 디코딩하기
좀 더 편리하게 사용하기 위해 UserAccountControl 비트마스크 값을 사람이 읽기 쉬운 형태로 자동 변환해 주는 도구가 있으면 좋겠죠? UserAccountControl은 비트마스크이므로 각 비트에 텍스트 설명을 매핑하는 간단한 PowerShell 함수를 작성해 보겠습니다. 이 함수는 UserAccountControl 속성의 10진수 값을 입력받아 활성화된 계정 옵션 목록을 반환합니다.
UserAccountControl 값을 읽기 쉬운 형태로 변환하기 위해 작성한 PowerShell 함수 DecodeUserAccountControl은 다음과 같습니다:
Function DecodeUserAccountControl ([int]$UAC)
{
$UACPropertyFlags = @(
"SCRIPT",
"ACCOUNTDISABLE",
"RESERVED",
"HOMEDIR_REQUIRED",
"LOCKOUT",
"PASSWD_NOTREQD",
"PASSWD_CANT_CHANGE",
"ENCRYPTED_TEXT_PWD_ALLOWED",
"TEMP_DUPLICATE_ACCOUNT",
"NORMAL_ACCOUNT",
"RESERVED",
"INTERDOMAIN_TRUST_ACCOUNT",
"WORKSTATION_TRUST_ACCOUNT",
"SERVER_TRUST_ACCOUNT",
"RESERVED",
"RESERVED",
"DONT_EXPIRE_PASSWORD",
"MNS_LOGON_ACCOUNT",
"SMARTCARD_REQUIRED",
"TRUSTED_FOR_DELEGATION",
"NOT_DELEGATED",
"USE_DES_KEY_ONLY",
"DONT_REQ_PREAUTH",
"PASSWORD_EXPIRED",
"TRUSTED_TO_AUTH_FOR_DELEGATION",
"RESERVED",
"PARTIAL_SECRETS_ACCOUNT",
"RESERVED",
"RESERVED",
"RESERVED",
"RESERVED",
"RESERVED",
"RESERVED"
)
return (0..($UACPropertyFlags.Length) | ?{$UAC -bAnd [math]::Pow(2,$_)} | %{$UACPropertyFlags[$_]}) -join " | "
}
이제 66050이라는 UserAccountControl 값이 무엇을 의미하는지 확인해 보겠습니다:
DecodeUserAccountControl 66050
실행 결과, 이 사용자에게 다음 플래그들이 활성화되어 있음을 확인할 수 있습니다:
ACCOUNTDISABLE | NORMAL_ACCOUNT | DONT_EXPIRE_PASSWORD
동일한 스크립트를 Get-ADUser 또는 Get-ADComputer cmdlet과 함께 사용하면 AD 계정 정보를 조회하는 즉시 UserAccountControl 값을 실시간으로 디코딩할 수 있습니다:
get-aduser ms-pam -properties *|select @{n='UsrAcCtrl';e={DecodeUserAccountControl($_.userAccountControl)}}
ACCOUNTDISABLE | NORMAL_ACCOUNT | DONT_EXPIRE_PASSWORD
get-adcomputer rome-dc01 -properties *|select @{n='UsrAcCtrl';e={DecodeUserAccountControl($_.userAccountControl)}}
SERVER_TRUST_ACCOUNT | TRUSTED_FOR_DELEGATION
PowerShell로 AD의 UserAccountControl 속성 설정하는 방법
Set-ADUser와 Set-ADComputer PowerShell cmdlet을 사용하면 Active Directory에서 UserAccountControl 속성의 개별 옵션을 변경할 수 있습니다. 두 cmdlet 모두 다음과 같은 전용 파라미터를 제공합니다:
- AccountNotDelegated
- AllowReversiblePasswordEncryption
- CannotChangePassword
- ChangePasswordAtLogon
- KerberosEncryptionType
- PasswordNeverExpires
- PasswordNotRequired
- PrincipalsAllowedToDelegateToAccount
참고로 AD의 컴퓨터 계정 암호는 컴퓨터와 도메인 간의 신뢰 관계를 유지하는 역할을 합니다.
사용자 옵션을 변경하려면 다음과 같은 명령을 사용합니다:
Set-ADUser jkelly –CannotChangePassword:$true -PasswordNeverExpires:$true
또는 범용 cmdlet인 Set-ADAccountControl을 사용할 수도 있습니다:
Set-ADAccountControl -Identity jkelly -CannotChangePassword $True -PasswordNeverExpires $True
또한 UserAccountControl 속성에 원하는 값을 직접 지정하여 두 가지 계정 옵션을 한 번에 활성화할 수도 있습니다:
Set-ADUser jkelly -Replace @{UserAccountControl= 66048}