파워셸 시리즈의 여덟 번째 포스팅입니다. 윈도우 시스템 관리의 핵심이지만, 너무 방대하고 느려서 아무도 열어보고 싶어 하지 않는 **'이벤트 뷰어(Event Viewer)'**를 파워셸로 정복하는 방법을 다룹니다.
수만 줄의 로그 속에서 "누군가 내 PC에 접속하려다 실패한 기록" 같은 치명적인 보안 이벤트를 1초 만에 찾아내는 보안 로그 분석 자동화 기술을 소개합니다.
윈도우 운영체제는 PC에서 일어나는 모든 일을 '이벤트 로그(Event Log)'라는 블랙박스에 기록합니다. 프로그램 오류, 시스템 부팅, 그리고 누군가의 로그인 시도까지 모든 것이 저장되죠.
하지만 윈도우 기본 도구인 **'이벤트 뷰어'**를 실행해 보신 분들은 아실 겁니다. 로딩은 끔찍하게 느리고, 로그는 수만 개가 쌓여 있어 내가 원하는 정보를 찾는 것이 모래사장 바늘 찾기보다 어렵다는 사실을요.
오늘은 파워셸(PowerShell)의 강력한 필터링 기능을 이용해, 굼뜬 이벤트 뷰어 없이 단 한 줄의 명령어로 보안 위협(로그인 실패)을 감지하고 리포트로 만드는 기술을 알아보겠습니다.
1. Get-EventLog는 잊어라, Get-WinEvent가 표준이다
많은 블로그나 예제에서 Get-EventLog를 사용하라고 가르칩니다. 하지만 이는 구형 명령어입니다. 최신 윈도우 환경에서는 훨씬 빠르고 강력한 **Get-WinEvent**를 사용하는 것이 표준입니다.
- Get-EventLog: 구형(Classic) 로그만 조회 가능, 속도가 느림.
- Get-WinEvent: 신형(ETW) 로그 포함 모든 로그 조회 가능, 해시테이블 필터링 지원으로 압도적으로 빠름.
우리는 전문가답게 Get-WinEvent를 사용하여 로그를 분석해 보겠습니다.
2. 핵심 원칙: "왼쪽에서 걸러라 (Filter Left)"
파워셸로 대용량 로그를 다룰 때 가장 중요한 성능 원칙입니다.
- 나쁜 예 (Filter Right):
- # 로그 10만 개를 다 가져온 뒤에 파이프라인으로 넘겨서 필터링 (매우 느림) Get-WinEvent -LogName Security | Where-Object { $_.Id -eq 4625 }
- 좋은 예 (Filter Left):
- # 윈도우 API 단계에서 4625번만 쏙 골라서 가져옴 (매우 빠름) Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625}
로그 데이터는 매우 방대하므로, 반드시 데이터를 가져오는 단계에서 필요한 것만 요청해야 시스템 부하를 줄일 수 있습니다.
3. [실전 프로젝트] 로그인 실패(무차별 대입 공격) 감지 스크립트
해커나 악성 스크립트가 시스템 침투를 시도할 때 가장 먼저 남는 흔적이 바로 **'로그인 실패(Event ID 4625)'**입니다. 최근 24시간 동안 발생한 로그인 실패 기록을 추출하여, 누가 언제 접속을 시도했는지 분석하는 스크립트를 작성해 보겠습니다.
※ 주의: 보안 로그(Security)를 조회하려면 반드시 파워셸을 관리자 권한으로 실행해야 합니다.
스크립트 코드 작성
# 분석할 시간 범위 설정 (최근 24시간)
$startTime = (Get-Date).AddHours(-24)
Write-Host "최근 24시간 동안의 로그인 실패 기록을 분석 중입니다..." -ForegroundColor Cyan
# 1. 고속 필터링(FilterHashtable)을 이용해 이벤트 추출
# LogName='Security' : 보안 로그
# Id=4625 : 로그인 실패 이벤트 ID
# StartTime : 검색 시작 시간
try {
$failedEvents = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4625
StartTime = $startTime
} -ErrorAction Stop
}
catch {
Write-Host "발견된 로그인 실패 기록이 없습니다. 시스템이 안전합니다." -ForegroundColor Green
exit
}
# 2. 로그 메시지 상세 분석 및 객체 변환
$report = $failedEvents | ForEach-Object {
# 이벤트 메시지는 텍스트 덩어리이므로 XML로 변환하여 데이터를 정밀하게 추출합니다.
$xml = [xml]$_.ToXml()
$eventData = $xml.Event.EventData.Data
# XML 데이터 중 필요한 정보만 골라냅니다.
# (Name 속성을 기준으로 값을 찾습니다)
$targetAccount = ($eventData | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
$ipAddress = ($eventData | Where-Object { $_.Name -eq 'IpAddress' }).'#text'
$failureReason = ($eventData | Where-Object { $_.Name -eq 'Status' }).'#text'
# 결과 객체 생성
[PSCustomObject]@{
Time = $_.TimeCreated.ToString("yyyy-MM-dd HH:mm:ss")
User = $targetAccount
IP_Address = $ipAddress
Failure_Code = $failureReason
}
}
# 3. 결과 출력 및 CSV 저장
# 화면에 표 형태로 출력
$report | Format-Table -AutoSize
# CSV 파일로 저장 (오늘 날짜 파일명)
$fileName = "Security_Audit_$(Get-Date -Format 'yyyyMMdd').csv"
$report | Export-Csv -Path $fileName -NoTypeInformation -Encoding UTF8
Write-Host "분석 결과가 [$fileName] 파일로 저장되었습니다." -ForegroundColor Yellow
코드 핵심 분석 (E-E-A-T 기술 포인트)
- Event ID 4625: 윈도우 보안 감사에서 가장 중요한 ID 중 하나입니다. 암호가 틀렸거나, 계정이 잠겼거나, 존재하지 않는 아이디로 로그인했을 때 기록됩니다.
- XML 파싱 ($_.ToXml()): Get-WinEvent의 기본 Message 속성은 긴 텍스트로 되어 있어 아이디나 IP 주소만 콕 집어내기가 어렵습니다. 이를 XML 형식으로 변환하면 데이터 구조가 명확해져서, 정규표현식 없이도 정확하게 **타겟 계정(TargetUserName)**과 **접속 IP(IpAddress)**를 추출할 수 있습니다. 이는 고급 파워셸 사용자의 팁입니다.
- ErrorAction Stop: 로그가 하나도 없을 때 Get-WinEvent는 에러를 뱉습니다. 이를 try-catch로 감싸서 "기록 없음 = 안전함"이라는 긍정적인 메시지로 처리했습니다.
4. 응용: 시스템 오류 로그(Error)만 모아보기
보안 로그뿐만 아니라, 시스템이 왜 불안정한지 원인을 찾을 때도 유용합니다. 응용프로그램(Application) 로그 중 '오류(Error)' 등급만 뽑아보는 방법입니다.
# 최근 1시간 동안 발생한 응용프로그램 오류 조회
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
Level = 2 # 1:Critical, 2:Error, 3:Warning, 4:Information
StartTime = (Get-Date).AddHours(-1)
} | Select-Object TimeCreated, Id, Message | Format-List
서버가 갑자기 느려지거나 프로그램이 튕길 때, 이 명령어를 실행하면 범인이 누구인지(어떤 모듈에서 에러가 났는지) 즉시 확인할 수 있습니다.
마치며
이벤트 뷰어는 느리고 답답하지만, 파워셸을 거치면 가장 강력한 보안 감사 도구가 됩니다. 오늘 만든 스크립트를 하루에 한 번씩 실행되도록 예약해 두면, 내 PC나 서버를 누가 엿보고 있는지 매일 아침 리포트로 받아볼 수 있습니다.
특히 외부에서 접속이 가능한 서버를 운영 중이라면, IP_Address 필드를 확인하여 낯선 해외 IP가 찍혀있지 않은지 반드시 점검해 보시기 바랍니다.
다음 포스팅에서는 이 모든 자동화 스크립트(파일 정리, 서비스 복구, 로그 분석)를 **"작업 스케줄러와 파워셸을 연동하여 매일 아침 자동으로 실행하는 방법"**에 대해 알아보겠습니다. 단순히 등록하는 것을 넘어, 파워셸 실행 정책(Execution Policy) 문제를 우회하는 실무 팁을 소개합니다.