Active Directory 계정 잠금이란?
IT 헬프데스크에서 일하다 보면, "제 계정이 또 잠겼어요"라는 전화를 안 받아본 사람이 없을 겁니다. Active Directory(AD) 환경에서는 사용자가 일정 횟수 이상 잘못된 비밀번호를 입력하면 계정이 자동으로 잠기게 되는데요, 이건 무차별 대입 공격(Brute-force Attack)을 막기 위한 보안 기능입니다. 하지만 솔직히, 헬프데스크 입장에서는 가장 골치 아픈 문의 중 하나이기도 하죠.
문제는 단순히 계정을 잠금 해제해주는 것만으로는 끝나지 않는다는 점입니다. 같은 사용자가 매주, 심하면 매일 다시 전화를 걸어옵니다. 반복적인 잠금을 진짜로 해결하려면 잠금이 발생한 원인 컴퓨터와 프로세스를 정확히 추적해야 합니다.
이 가이드에서는 이벤트 뷰어, PowerShell, LockoutStatus.exe를 활용해서 계정 잠금의 근본 원인을 체계적으로 찾아내는 방법을 단계별로 다루겠습니다.
계정 잠금이 발생하는 주요 원인
계정 잠금은 사용자가 비밀번호를 잘못 입력하는 것 말고도 의외로 다양한 원인이 있습니다. 경험상, 아래 원인들을 하나씩 점검하면 대부분의 경우 범인을 찾아낼 수 있습니다.
캐시된 자격 증명 (Cached Credentials)
이게 가장 흔한 원인입니다. Windows 자격 증명 관리자(Credential Manager)나 브라우저에 이전 비밀번호가 저장되어 있으면, 비밀번호를 변경한 후에도 시스템이 예전 비밀번호로 계속 인증을 시도합니다. 특히 웹 브라우저의 자동 로그인이나 VPN 클라이언트에 저장된 비밀번호가 범인인 경우가 정말 많습니다.
서비스 계정 및 예약된 작업
Windows 서비스, IIS 앱 풀, SQL Server 에이전트 등이 도메인 계정으로 실행되고 있을 때, 해당 계정의 비밀번호가 변경되면 서비스가 이전 비밀번호로 인증을 계속 시도합니다. 작업 스케줄러(Task Scheduler)에 등록된 예약 작업도 마찬가지고요. 이 경우 잠금이 주기적으로 발생하는 패턴을 보이는데, 예약 작업의 실행 주기와 잠금 시간을 비교해보면 금방 알 수 있습니다.
모바일 기기의 Exchange/이메일 동기화
스마트폰이나 태블릿에 저장된 Exchange ActiveSync 계정이 변경된 비밀번호를 반영하지 못하면, 백그라운드 동기화를 할 때마다 잘못된 자격 증명으로 인증을 시도하면서 계정이 잠깁니다. 사용자가 "아무것도 안 했는데 잠겼어요"라고 하면, 십중팔구 모바일 기기가 원인입니다.
연결이 끊긴 RDP 세션
원격 데스크톱 세션을 로그오프하지 않고 연결만 끊은 상태(disconnect)에서, 해당 세션에 남아 있는 이전 자격 증명이 계속 사용되는 경우입니다. 의외로 놓치기 쉬운 원인이에요.
매핑된 네트워크 드라이브
네트워크 공유 폴더에 연결할 때 저장해둔 자격 증명이 만료되면, Windows가 자동으로 이전 비밀번호를 써서 재연결을 시도합니다.
사전 준비: 감사 정책 설정 확인
계정 잠금 이벤트를 추적하려면 먼저 도메인 컨트롤러(DC)에 감사 정책이 제대로 설정되어 있어야 합니다. 이게 안 되어 있으면 보안 로그에 아무것도 기록이 안 되니까, 반드시 먼저 확인하세요.
감사 정책 활성화 경로
그룹 정책 관리 편집기(gpmc.msc)에서 다음 경로로 이동합니다:
컴퓨터 구성 → 정책 → Windows 설정 → 보안 설정 → 고급 감사 정책 구성 → 감사 정책 → 계정 관리
→ "사용자 계정 관리 감사" → 성공 및 실패 모두 활성화
그리고 다음 항목도 함께 켜줘야 합니다:
계정 로그온 이벤트 → 감사 Kerberos 인증 서비스 → 성공 및 실패
계정 로그온 이벤트 → 감사 자격 증명 유효성 검사 → 성공 및 실패
정책을 변경한 뒤에는 도메인 컨트롤러에서 gpupdate /force 명령을 실행해서 즉시 적용해주세요.
핵심 이벤트 ID 이해하기
계정 잠금 추적에서 가장 중요한 건 관련 이벤트 ID를 정확히 아는 것입니다. 각 이벤트가 서로 다른 정보를 제공하기 때문에, 이걸 조합해서 분석해야 정확한 원인을 파악할 수 있습니다.
| 이벤트 ID | 설명 | 제공 정보 | 기록 위치 |
|---|---|---|---|
| 4740 | 사용자 계정이 잠김 | 대상 계정명, 호출자 컴퓨터 이름(Caller Computer Name) | PDC Emulator DC |
| 4625 | 로그온 실패 | 실패 이유, 원본 IP, 로그온 유형, 프로세스 정보 | 인증 처리 DC |
| 4771 | Kerberos 사전 인증 실패 | 클라이언트 IP 주소, 실패 코드, 서비스 이름 | 인증 처리 DC |
| 4776 | NTLM 자격 증명 유효성 검사 | 원본 워크스테이션, 오류 코드 | 인증 처리 DC |
중요: 이벤트 ID 4740은 PDC Emulator 역할을 가진 도메인 컨트롤러에만 기록됩니다. 다른 DC에서는 볼 수 없으니까, 반드시 PDC Emulator에서 확인해야 합니다. 이걸 모르고 엉뚱한 DC에서 로그를 뒤지다 시간 낭비하는 경우가 꽤 있어요.
1단계: PDC Emulator 도메인 컨트롤러 확인
자, 그러면 본격적으로 추적을 시작해봅시다. 먼저 어떤 DC가 PDC Emulator인지 확인해야 합니다. 이벤트 4740이 여기에만 기록되니까요.
PowerShell로 PDC Emulator 찾기
# PDC Emulator 역할을 가진 도메인 컨트롤러 확인
Get-ADDomainController -Filter * | Where-Object { $_.OperationMasterRoles -contains "PDCEmulator" } | Select-Object Name, IPv4Address
# 또는 간단하게
Get-ADDomain | Select-Object PDCEmulator
2단계: 이벤트 뷰어로 잠금 원인 추적
PDC Emulator DC를 찾았으면, 이제 그 서버에서 이벤트 뷰어를 열어 잠금 이벤트를 확인합니다.
이벤트 뷰어 수동 확인 절차
- PDC Emulator DC에 로그인합니다.
- 이벤트 뷰어(eventvwr.msc)를 실행합니다.
- 왼쪽 창에서 Windows 로그 → 보안을 선택합니다.
- 오른쪽 작업 창에서 "현재 로그 필터링"을 클릭합니다.
- 이벤트 ID에 4740을 입력하고 확인을 클릭합니다.
- 잠금 이벤트 목록에서 대상 사용자를 찾아 더블클릭합니다.
- "호출자 컴퓨터 이름"(Caller Computer Name) 필드를 보면 잠금을 유발한 컴퓨터를 알 수 있습니다.
"호출자 컴퓨터 이름"이 비어 있는 경우
간혹 Caller Computer Name이 공란으로 나타나는 경우가 있는데요, 이건 보통 잠금 요청이 Linux/Unix 서버, 네트워크 어플라이언스(F5 Big-IP, Citrix NetScaler 등), VMware 호스트 같은 비Windows 장치에서 발생했다는 뜻입니다. 이럴 때는 추가 조사가 필요합니다:
- 이벤트 ID 4771을 확인해서 클라이언트 IP 주소를 파악합니다.
- 이벤트 ID 4776에서 원본 워크스테이션 정보를 확인합니다.
- 위 이벤트에서도 정보가 없으면 Netlogon 디버그 로깅을 켜야 합니다 (뒤에서 자세히 다룹니다).
3단계: PowerShell로 체계적으로 추적하기
이벤트 뷰어를 GUI로 하나씩 열어보는 건 솔직히 좀 번거롭습니다. PowerShell을 쓰면 여러 DC를 한 번에 조회할 수 있어서 훨씬 빠르고 효율적입니다.
잠긴 계정 목록 확인
# ActiveDirectory 모듈 로드
Import-Module ActiveDirectory
# 현재 잠긴 모든 계정 검색
Search-ADAccount -LockedOut | Select-Object Name, SamAccountName, LockedOut, LastLogonDate | Format-Table -AutoSize
# 특정 사용자의 잠금 상태 상세 확인
Get-ADUser -Identity "사용자계정명" -Properties LockedOut, BadLogonCount, LastBadPasswordAttempt, AccountLockoutTime |
Select-Object Name, LockedOut, BadLogonCount, LastBadPasswordAttempt, AccountLockoutTime
이벤트 ID 4740으로 잠금 원인 컴퓨터 찾기
# PDC Emulator에서 최근 계정 잠금 이벤트 조회
$PDCEmulator = (Get-ADDomain).PDCEmulator
Get-WinEvent -ComputerName $PDCEmulator -FilterHashtable @{
LogName = 'Security'
Id = 4740
} -MaxEvents 50 | ForEach-Object {
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
TargetAccount = $_.Properties[0].Value
CallerComputer = $_.Properties[1].Value
}
} | Format-Table -AutoSize
특정 사용자의 잠금 이벤트만 필터링
# 특정 사용자의 잠금 이벤트만 검색
$TargetUser = "hong.gildong"
$PDCEmulator = (Get-ADDomain).PDCEmulator
Get-WinEvent -ComputerName $PDCEmulator -FilterHashtable @{
LogName = 'Security'
Id = 4740
} | Where-Object { $_.Properties[0].Value -eq $TargetUser } | ForEach-Object {
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
TargetAccount = $_.Properties[0].Value
CallerComputer = $_.Properties[1].Value
}
} | Format-Table -AutoSize
계정 잠금 즉시 해제
# 특정 계정 잠금 해제
Unlock-ADAccount -Identity "사용자계정명"
# 잠금 해제 확인
Get-ADUser -Identity "사용자계정명" -Properties LockedOut | Select-Object Name, LockedOut
잘못된 로그온 시도(4625) 추적
# 원인 컴퓨터에서 로그온 실패 이벤트 상세 확인
Get-WinEvent -ComputerName "원인컴퓨터명" -FilterHashtable @{
LogName = 'Security'
Id = 4625
} -MaxEvents 20 | ForEach-Object {
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
TargetAccount = $_.Properties[5].Value
LogonType = $_.Properties[10].Value
ProcessName = $_.Properties[18].Value
SourceIP = $_.Properties[19].Value
}
} | Format-Table -AutoSize
여기서 LogonType 값을 보면 잠금이 어떤 경로로 발생했는지 구체적으로 알 수 있습니다:
| LogonType | 설명 | 일반적 원인 |
|---|---|---|
| 2 | 대화형 로그온 | 로컬 콘솔 로그인 |
| 3 | 네트워크 로그온 | 파일 공유, 프린터, 네트워크 리소스 접근 |
| 4 | 배치 로그온 | 예약된 작업(Task Scheduler) |
| 5 | 서비스 로그온 | Windows 서비스 실행 |
| 7 | 잠금 해제 | 워크스테이션 잠금 해제 시도 |
| 8 | 네트워크 클리어텍스트 | IIS 기본 인증 |
| 10 | 원격 대화형 | RDP 원격 데스크톱 연결 |
4단계: Netlogon 디버그 로깅 활용
이벤트 뷰어에서 Caller Computer Name이 비어 있고, 이벤트 4771이나 4776에서도 원인을 못 찾겠다면, 마지막 카드로 Netlogon 디버그 로깅을 활성화해봐야 합니다. 좀 더 깊은 수준의 인증 요청 정보를 볼 수 있거든요.
Netlogon 로깅 활성화
# Netlogon 디버그 로깅 활성화 (DC에서 실행)
nltest /dbflag:0x2080ffff
# Netlogon 서비스 재시작
Restart-Service Netlogon
# 로그 파일 위치: %windir%\debug\netlogon.log
# 로그 확인
Get-Content "$env:windir\debug\netlogon.log" -Tail 100 | Select-String "0xC000006A"
0xC000006A 오류 코드는 "잘못된 비밀번호"를 의미합니다. 해당 로그 라인에서 원본 컴퓨터의 IP 주소를 확인할 수 있어요.
주의: Netlogon 디버그 로깅은 DC에 상당한 I/O 부하를 줍니다. 원인을 파악했으면 반드시 꺼주세요. 켜놓은 채로 까먹으면 나중에 디스크 공간 문제가 생길 수 있습니다.
# Netlogon 디버그 로깅 비활성화 (원인 파악 후 반드시 실행)
nltest /dbflag:0x0
5단계: LockoutStatus.exe 도구 활용
커맨드라인이 익숙하지 않은 분들을 위해, Microsoft에서 제공하는 GUI 도구도 있습니다. Account Lockout and Management Tools 패키지에 포함된 LockoutStatus.exe는 모든 도메인 컨트롤러에서 특정 사용자의 잠금 상태를 한 화면에 보여줍니다.
설치 및 사용 방법
- Microsoft 다운로드 센터에서 Account Lockout and Management Tools (AlTools.exe)를 다운로드합니다.
- 설치 후 LockoutStatus.exe를 실행합니다.
- File → Select Target을 클릭합니다.
- 사용자의 sAMAccountName과 도메인 이름을 입력하고 OK를 클릭합니다.
- 각 DC별 잠금 상태(Locked/Non Locked), 잠금 시간, 원인 컴퓨터(Orig Lock)가 한눈에 표시됩니다.
LockoutStatus 창에서 마우스 오른쪽 버튼을 클릭하면 해당 계정의 잠금 해제나 비밀번호 변경도 바로 할 수 있어서 꽤 편리합니다.
원인별 구체적 해결 방법
잠금 원인 컴퓨터와 프로세스를 파악했다면, 이제 실제로 문제를 해결할 차례입니다. 원인별로 정리해봤습니다.
캐시된 자격 증명 정리
# Windows 자격 증명 관리자에서 저장된 자격 증명 확인
cmdkey /list
# 특정 자격 증명 삭제
cmdkey /delete:대상서버명
# 또는 제어판에서: 제어판 → 사용자 계정 → 자격 증명 관리자
서비스 계정 비밀번호 업데이트
# 특정 계정으로 실행 중인 서비스 찾기
Get-WmiObject Win32_Service | Where-Object { $_.StartName -like "*대상계정*" } |
Select-Object Name, DisplayName, StartName, State | Format-Table -AutoSize
# 서비스 계정 비밀번호 업데이트 후 서비스 재시작
# (services.msc에서 해당 서비스 → 속성 → 로그온 탭에서 비밀번호 변경)
예약 작업 자격 증명 업데이트
# 특정 계정으로 실행되는 예약 작업 찾기
Get-ScheduledTask | Where-Object { $_.Principal.UserId -like "*대상계정*" } |
Select-Object TaskName, TaskPath, @{N='UserId';E={$_.Principal.UserId}} | Format-Table -AutoSize
모바일 기기 Exchange ActiveSync 확인
# Exchange Online에서 ActiveSync 장치 통계 확인
Get-MobileDeviceStatistics -Mailbox "사용자@도메인.com" |
Select-Object DeviceFriendlyName, DeviceOS, LastSuccessSync, LastSyncAttemptTime
자동 모니터링 스크립트 구축
매번 수동으로 확인하는 건 한계가 있습니다. 반복적인 계정 잠금을 사전에 감지하고 싶다면, 자동 모니터링 스크립트를 만들어두는 게 좋습니다. 한 번 세팅해두면 정말 편해요.
계정 잠금 알림 이메일 자동 발송 스크립트
# 계정 잠금 모니터링 및 이메일 알림 스크립트
$PDCEmulator = (Get-ADDomain).PDCEmulator
$SmtpServer = "smtp.회사도메인.com"
$From = "ad-monitor@회사도메인.com"
$To = "helpdesk@회사도메인.com"
# 최근 15분 이내 발생한 잠금 이벤트 검색
$StartTime = (Get-Date).AddMinutes(-15)
$LockoutEvents = Get-WinEvent -ComputerName $PDCEmulator -FilterHashtable @{
LogName = 'Security'
Id = 4740
StartTime = $StartTime
} -ErrorAction SilentlyContinue
if ($LockoutEvents) {
$Body = "다음 계정 잠금이 감지되었습니다:`n`n"
foreach ($Event in $LockoutEvents) {
$Body += "시간: $($Event.TimeCreated)`n"
$Body += "계정: $($Event.Properties[0].Value)`n"
$Body += "원인 컴퓨터: $($Event.Properties[1].Value)`n"
$Body += "---`n"
}
Send-MailMessage -SmtpServer $SmtpServer -From $From -To $To `
-Subject "[AD 알림] 계정 잠금 감지" -Body $Body -Encoding UTF8
}
이 스크립트를 작업 스케줄러에 15분 간격으로 등록하면, 계정 잠금이 발생할 때마다 헬프데스크 팀에 자동으로 알림이 갑니다. 사용자가 전화하기 전에 먼저 파악할 수 있다는 게 큰 장점이죠.
계정 잠금 정책 최적화 권장 사항
잠금 정책은 보안과 사용자 편의성 사이에서 균형을 잡아야 합니다. 너무 타이트하게 설정하면 정상 사용자가 매일 잠기고, 너무 느슨하면 보안에 구멍이 생깁니다. 아래는 실무에서 무난하게 적용할 수 있는 권장 값입니다.
| 정책 항목 | 권장 값 | 설명 |
|---|---|---|
| 계정 잠금 임계값 | 10~15회 | 너무 낮으면 정상 사용자가 자주 잠기고, 너무 높으면 보안 취약 |
| 계정 잠금 기간 | 15~30분 | 자동 해제 시간, 0으로 설정하면 관리자가 수동 해제해야 함 |
| 잠금 카운터 초기화 시간 | 15~30분 | 실패 횟수가 초기화되는 시간 |
세분화된 비밀번호 정책(Fine-Grained Password Policy) 활용
Windows Server 2008 이상에서는 세분화된 비밀번호 정책(FGPP)을 사용해서 특정 그룹에 다른 잠금 정책을 적용할 수 있습니다. 예를 들어, 서비스 계정 그룹에는 더 높은 잠금 임계값을, 관리자 그룹에는 더 엄격한 정책을 적용하는 식이죠. 조직 규모가 좀 되면 거의 필수적으로 도입하게 됩니다.
# 세분화된 비밀번호 정책 생성 예시
New-ADFineGrainedPasswordPolicy -Name "서비스계정-잠금정책" `
-Precedence 10 `
-LockoutThreshold 20 `
-LockoutDuration "00:30:00" `
-LockoutObservationWindow "00:30:00" `
-ComplexityEnabled $true `
-MinPasswordLength 14
# 정책을 특정 그룹에 적용
Add-ADFineGrainedPasswordPolicySubject -Identity "서비스계정-잠금정책" `
-Subjects "서비스계정그룹"
재발 방지를 위한 체크리스트
계정 잠금 문제를 해결했으면, 같은 일이 또 일어나지 않도록 아래 체크리스트를 참고하세요. 개인적으로 비밀번호 변경 후 체크리스트를 사용자에게 안내 메일로 보내는 것도 좋은 방법이라고 생각합니다.
- 비밀번호 변경 후: Windows 자격 증명 관리자에서 이전 자격 증명 삭제
- 비밀번호 변경 후: 모든 모바일 기기에서 Exchange/이메일 비밀번호 즉시 업데이트
- 비밀번호 변경 후: 서비스, 예약 작업, IIS 앱 풀의 자격 증명 업데이트
- 정기 점검: 서비스 계정에 gMSA(Group Managed Service Account) 도입 검토
- 정기 점검: 비밀번호 만료 7일 전 사용자에게 자동 알림 발송
- 모니터링: 잠금 빈도가 높은 계정 목록 주간 리포트 생성
- 보안: 비정상적인 대량 잠금 발생 시 무차별 대입 공격 가능성 조사
자주 묻는 질문 (FAQ)
Q1. 계정이 잠겼는데 잠금 원인 컴퓨터(Caller Computer Name)가 비어 있으면 어떻게 하나요?
비Windows 장치(Linux 서버, F5, Citrix, VMware 호스트 등)에서 잠금 요청이 발생했을 가능성이 높습니다. 이벤트 ID 4771에서 클라이언트 IP 주소를 확인하거나, 그래도 안 보이면 Netlogon 디버그 로깅을 활성화해서 원본 IP를 추적하세요.
Q2. PowerShell 없이 GUI만으로 잠금 원인을 찾을 수 있나요?
네, 가능합니다. PDC Emulator DC에서 이벤트 뷰어를 열고 보안 로그에서 이벤트 ID 4740을 필터링하면 됩니다. Microsoft의 LockoutStatus.exe 도구를 쓰면 모든 DC의 잠금 상태를 GUI로 한 번에 볼 수 있어서 더 편합니다.
Q3. 계정 잠금이 반복적으로 발생하는데 원인을 찾을 수 없습니다.
먼저 사용자에게 최근 비밀번호 변경 여부를 꼭 확인하세요. 변경했다면 자격 증명 관리자(cmdkey /list), 예약 작업, 서비스, 모바일 기기를 전부 점검해야 합니다. 그래도 안 나오면 Netlogon 디버그 로깅을 켜고, 네트워크 모니터링 도구로 해당 계정의 인증 트래픽을 추적해보세요.
Q4. 서비스 계정의 반복 잠금을 영구적으로 방지할 수 있나요?
gMSA(Group Managed Service Account)를 도입하면 됩니다. AD가 자동으로 비밀번호를 관리해주기 때문에, 비밀번호 만료나 불일치로 인한 잠금이 원천적으로 차단됩니다. Windows Server 2012 이상이면 지원되니까, 아직 안 쓰고 계시다면 적극 도입을 권장합니다.
Q5. Microsoft Entra ID(Azure AD)와 온프레미스 AD의 계정 잠금은 서로 영향을 주나요?
Microsoft Entra Domain Services 관리형 도메인에서 잘못된 비밀번호를 시도해도 Entra ID(구 Azure AD) 내 사용자 계정이 잠기지는 않습니다. 잠금은 관리형 도메인 안에서만 적용됩니다. 다만, Entra ID Smart Lockout이라는 별도 기능이 클라우드 인증에 자체 잠금 정책을 적용하는데, 유효한 사용자와 공격자를 구별해서 처리해주는 똑똑한 기능입니다.