Azure Active Directory 구성 감사은(는) 무엇을 하나요?
사용 시기
- Azure 테넌트의 ID 구성에 대한 보안 평가를 수행할 때
- 규정 준수 감사에서 인증 정책, MFA 적용, 역할 할당 검토가 필요할 때
- 합병 또는 인수 후 새 Azure 테넌트를 온보딩할 때
- 의심스러운 로그인 활동 또는 손상된 계정을 조사할 때
- 조건부 액세스 정책이 ID 기반 공격을 적절히 보호하는지 확인할 때
사용하지 말아야 할 경우: 온-프레미스 Active Directory 감사(PingCastle 또는 BloodHound AD 사용), ID 컨텍스트 없는 Azure 리소스 수준 RBAC 감사, 실시간 위협 탐지( Microsoft Defender for Identity 사용).
사전 요구 사항
- 대상 Microsoft Entra ID 테넌트의 Global Reader 또는 Security Reader 역할
- Microsoft Graph PowerShell SDK 설치됨 (
Install-Module Microsoft.Graph) - 대상 테넌트에 인증된 Az CLI (
az login --tenant TENANT_ID) - 자동 평가를 위한 ScoutSuite (Azure 공급자 구성 완료)
- Azure AD 감사 로그 및 로그인 로그 액세스 (Azure AD Premium P1/P2 필요)
워크플로
1단계: 테넌트 구성 및 보안 기본값 열거
보안 기본값 및 레거시 인증 상태를 포함한 테넌트의 기준 ID 보안 설정을 평가합니다.
# Microsoft Graph에 연결
Connect-MgGraph -Scopes "Directory.Read.All","Policy.Read.All","AuditLog.Read.All"
# 테넌트 세부 정보 가져오기
Get-MgOrganization | Select-Object DisplayName, Id, VerifiedDomains
# 보안 기본값 활성화 여부 확인
Get-MgPolicyIdentitySecurityDefaultEnforcementPolicy | Select-Object IsEnabled
# 인증 방법 정책 나열
Get-MgPolicyAuthenticationMethodPolicy | ConvertTo-Json -Depth 5
# 조건부 액세스를 통해 레거시 인증 상태 확인
Get-MgIdentityConditionalAccessPolicy | Where-Object {
$_.Conditions.ClientAppTypes -contains "exchangeActiveSync" -or
$_.Conditions.ClientAppTypes -contains "other"
} | Select-Object DisplayName, State
2단계: 권한 있는 역할 할당 감사
디렉터리 역할 할당을 검토하여 과도한 권한을 가진 사용자, 영구 관리자 계정 및 위험한 역할 구성을 식별합니다.
# 모든 전역 관리자 할당 나열
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/directoryRoles/filterByIds" \
--body '{"ids":["62e90394-69f5-4237-9190-012177145e10"]}' | \
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/directoryRoles?filter=displayName eq 'Global Administrator'" \
--query "value[0].id" -o tsv
# Graph API를 사용하여 모든 권한 있는 역할 할당 나열
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments?\$expand=principal" \
--query "value[*].{Role:roleDefinitionId, Principal:principal.displayName, PrincipalType:[email protected]}" \
-o table
# 여러 관리자 역할을 가진 사용자 확인
az ad user list --query "[].{UPN:userPrincipalName, DisplayName:displayName}" -o table
# 관리자 역할 할당이 있는 서비스 주체 나열
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments?\$filter=principalOrganizationId eq 'TENANT_ID'" \
-o json
3단계: 조건부 액세스 정책 검토
MFA 적용, 장치 준수 및 위치 기반 제한과 관련된 조건부 액세스 정책의 적용 범위 차이를 감사합니다.
# 모든 조건부 액세스 정책 나열
Get-MgIdentityConditionalAccessPolicy | Select-Object DisplayName, State, @{
N='GrantControls'; E={$_.GrantControls.BuiltInControls -join ', '}
} | Format-Table -AutoSize
# 보고 전용 모드(적용되지 않음)의 정책 식별
Get-MgIdentityConditionalAccessPolicy | Where-Object {$_.State -eq "enabledForReportingButNotEnforced"} |
Select-Object DisplayName
# MFA 적용 범위 확인
Get-MgIdentityConditionalAccessPolicy | Where-Object {
$_.GrantControls.BuiltInControls -contains "mfa"
} | Select-Object DisplayName, State, @{
N='Users'; E={$_.Conditions.Users.IncludeUsers -join ', '}
}
# 그룹을 제외하는 정책 찾기 (잠재적 우회)
Get-MgIdentityConditionalAccessPolicy | Where-Object {
$_.Conditions.Users.ExcludeGroups.Count -gt 0
} | Select-Object DisplayName, @{
N='ExcludedGroups'; E={$_.Conditions.Users.ExcludeGroups -join ', '}
}
4단계: 오래된 계정 및 게스트 사용자 식별
최근에 로그인하지 않은 계정, 활성 역할 할당이 있는 비활성화된 계정 및 위험한 게스트 사용자 구성을 찾습니다.
# 90일 이상 로그인하지 않은 사용자 찾기
az ad user list --query "[?signInActivity.lastSignInDateTime < '2025-11-25T00:00:00Z'].{UPN:userPrincipalName, LastSignIn:signInActivity.lastSignInDateTime, Enabled:accountEnabled}" -o table
# 모든 게스트 사용자 나열
az ad user list --filter "userType eq 'Guest'" \
--query "[].{UPN:userPrincipalName, DisplayName:displayName, CreatedDate:createdDateTime}" \
-o table
# 권한 있는 역할을 가진 게스트 사용자 찾기
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments?\$expand=principal" \
--query "value[?principal.userType=='Guest'].{Role:roleDefinitionId,Guest:principal.userPrincipalName}" \
-o table
# MFA가 비활성화된 계정 확인
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/reports/authenticationMethods/userRegistrationDetails" \
--query "value[?!isMfaRegistered].{UPN:userPrincipalName,MfaRegistered:isMfaRegistered}" \
-o table
5단계: 위험한 활동에 대한 로그인 로그 분석
비정상적인 인증 패턴, 실패한 MFA 챌린지 및 위험한 로그인 탐지를 식별하기 위해 로그인 로그를 검토합니다.
# 지난 7일 간의 위험한 로그인 가져오기
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/auditLogs/signIns?\$filter=riskLevelDuringSignIn ne 'none' and createdDateTime ge 2026-02-16T00:00:00Z" \
--query "value[*].{User:userPrincipalName,Risk:riskLevelDuringSignIn,IP:ipAddress,App:appDisplayName,Status:status.errorCode}" \
-o table
# 익숙하지 않은 위치에서의 로그인 가져오기
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/auditLogs/signIns?\$filter=riskEventTypes_v2/any(r:r eq 'unfamiliarFeatures')" \
--query "value[*].{User:userPrincipalName,Location:location.city,IP:ipAddress}" \
-o table
# 레거시 인증 로그인 확인
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/auditLogs/signIns?\$filter=clientAppUsed ne 'Browser' and clientAppUsed ne 'Mobile Apps and Desktop clients'" \
--query "value[*].{User:userPrincipalName,ClientApp:clientAppUsed,Status:status.errorCode}" \
-o table
6단계: ScoutSuite 자동 평가 실행
Azure 테넌트 구성 전반에 걸쳐 포괄적인 자동 검사를 위해 ScoutSuite를 실행합니다.
# Azure에 대해 ScoutSuite 실행
python3 -m ScoutSuite azure --cli \
--report-dir ./scoutsuite-azure-report \
--all-subscriptions
# 생성된 HTML 보고서 검토
open ./scoutsuite-azure-report/azure-report.html
주요 개념
| 용어 | 정의 |
|---|---|
| Microsoft Entra ID | 인증 및 권한 부여를 제공하는 Microsoft의 클라우드 ID 및 액세스 관리 서비스 (이전 Azure Active Directory) |
| 조건부 액세스 | 사용자, 장치, 위치, 위험과 같은 신호를 평가하여 MFA, 장치 준수, 액세스 차단과 같은 액세스 제어를 적용하는 정책 엔진 |
| 보안 기본값 (Security Defaults) | MFA 등록을 적용하고, 레거시 인증을 차단하며, 권한 있는 작업을 보호하는 Microsoft의 기준 ID 보호 설정 |
| 권한 있는 ID 관리 (PIM) | 승인 워크플로 및 시간 제한 역할 활성화를 통해 적시 권한 있는 액세스를 가능하게 하는 Azure AD Premium P2 기능 |
| 레거시 인증 (Legacy Authentication) | MFA를 지원하지 않는 이전 인증 프로토콜(POP3, IMAP, SMTP, ActiveSync)로, 자격 증명 공격에 악용됩니다. |
| 위험한 로그인 (Risky Sign-In) | 불가능한 이동, 익숙하지 않은 위치, 맬웨어 연결 IP 등 로그인 이상 징후를 탐지하는 Microsoft Entra ID 보호 |
도구 및 시스템
- Microsoft Graph API: Entra ID 구성, 정책, 역할 및 감사 로그를 쿼리하는 기본 프로그래밍 인터페이스
- Microsoft Graph PowerShell SDK: Entra ID 관리 및 보안 감사 작업을 위한 PowerShell 모듈
- ScoutSuite: IAM, 스토리지, 네트워킹 및 ID 검사를 위한 Azure 공급자를 지원하는 멀티 클라우드 감사 도구
- AzureADRecon: 포괄적인 Azure AD 정찰 및 보안 평가 보고를 위한 커뮤니티 도구
- Microsoft Defender for Identity: ID 기반 위협 및 손상된 자격 증명을 탐지하는 클라우드 기반 보안 솔루션
일반적인 시나리오
시나리오: 인수 후 Azure 테넌트 보안 평가
컨텍스트: 회사를 인수한 후 보안 팀은 기업 Entra ID와 통합하기 전에 Azure 테넌트 ID 보안 상태를 평가해야 합니다.
접근 방식:
- 모든 전역 관리자를 열거하고 관리자 역할의 개인 계정 확인
- 조건부 액세스 정책을 검토하여 관리자뿐만 아니라 모든 사용자에게 MFA가 적용되는지 확인
- 권한 있는 액세스 권한이 있는 게스트 사용자를 식별하여 타사 공급업체 과도한 권한 부여 가능성 확인
- 자격 증명 공격의 대상이 될 수 있는 오래된 계정(90일 이상 로그인 없음) 확인
- MFA를 우회하는 레거시 인증 사용 여부를 로그인 로그에서 검토
- 보안 기본값 또는 이에 상응하는 CA 정책이 레거시 인증 프로토콜을 차단하는지 확인
- 테넌트 통합 전에 우선 순위에 따른 수정 단계가 포함된 위험 보고서 생성
주의사항: 위험한 로그인 탐지 및 PIM에는 Azure AD Premium P2가 필요합니다. 인수한 테넌트가 낮은 라이선스 티어를 사용하는 경우 많은 ID 보호 기능을 사용할 수 없습니다. 파트너 테넌트의 게스트 사용자는 표준 역할 할당 쿼리에서 볼 수 없는 동적 그룹을 통해 암시적 액세스 권한을 가질 수 있습니다.
출력 형식
Azure Active Directory 보안 감사 보고서
===============================================
테넌트: acme-acquired.onmicrosoft.com
테넌트 ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890
감사 날짜: 2026-02-23
라이선스: Azure AD Premium P2
ID 구성:
보안 기본값: 비활성화됨 (조건부 액세스 사용 중)
조건부 액세스 정책: 12 (8개 적용, 3개 보고 전용, 1개 비활성화)
레거시 인증 차단: 부분적 (관리자만 차단됨)
권한 있는 액세스:
전역 관리자: 8 (권장: <= 4)
영구 관리자 할당: 6 (PIM 활성화 불필요)
관리자 권한이 있는 서비스 주체: 3
권한 있는 역할을 가진 게스트 사용자: 2
계정 위생:
전체 사용자: 1,247
오래된 계정(90일 이상): 89
게스트 사용자: 234
MFA 미등록 사용자: 156
로그인 위험:
위험한 로그인(최근 30일): 34
레거시 인증 로그인(최근 7일): 67
불가능한 이동 탐지: 5
익숙하지 않은 위치 로그인: 12
중요 발견 사항:
1. 영구 할당된 전역 관리자 8명 (PIM 사용 권장)
2. 비관리자 사용자에 대해 레거시 인증이 차단되지 않음
3. MFA 미등록 사용자 156명
4. 권한 있는 역할 관리자 역할을 가진 게스트 사용자 2명