목록으로

Programming Notes

Microsoft Sentinel에서 AI 에이전트 및 비인간 ID 탐지하기: 클래식 에이전트의 사각지대

Build 2026을 통해 방향성이 공식화되었습니다. 업계는 '앱의 시대'에서 '에이전트의 시대'로 이동하고 있으며, Microsoft는 키노트의 상당 부분을 에이전트의 라이프사이클 전반(취약점 발견부터 운영 환경의 거버넌스까지)을 보호하는 데 할애했습니다. ID 측면의 핵심은 현재 일반 공급(GA)된 Microsoft Entra Agent ID입니다. 이를 통해 AI 에이전트는 '일등 시민(First-class)'으로서의 ID를 부여받으며, 조건부 액세스(Conditional Access), ID 보호(Identity Protection) 및 전체 감사 로그 기능을 확장 적용받게 됩니다.

새로운 방식으로 구축된 에이전트들에게는 분명 희소식입니다. 하지만 이것이 전체 그림은 아니며, 이 간극이야말로 대부분의 보안 운영 센터(SOC)가 가장 먼저 타격을 입게 될 지점입니다.

현대적 에이전트는 보호되지만, 클래식 에이전트는 그렇지 않습니다.

Entra Agent ID는 두 종류의 에이전트 사이에 명확한 선을 긋습니다.

**현대적 에이전트(Modern agents)**는 Agent ID 플랫폼을 통해 생성되며, 각각 에이전트 ID 청사진을 기반으로 합니다. 고유한 Agent ID, 전체 감사 추적, 그리고 에이전트의 정상 활동 기준을 수립하고 이상 징후를 자동으로 플래깅하는 '에이전트용 ID 보호' 기능을 포함한 전체 거버넌스 역량을 갖추고 있습니다.

**클래식 에이전트(Classic agents)**는 그 이전에 만들어진 모든 것이거나 플랫폼 외부에서 구축된 것들입니다. 예를 들어 일반 서비스 주체(Service Principal)나 앱 등록으로 구현된 AI 에이전트, Agent ID가 활성화되기 전에 생성된 Copilot Studio 에이전트, 또는 클라이언트 자격 증명을 사용하여 Graph를 호출하는 자체 제작 자동화 도구 등이 여기에 해당합니다. Entra 에이전트 레지스트리에서 이들은 "Has Agent ID: No"로 표시됩니다. 이 플래그가 중요한 이유는 Agent ID 보호 기능이 실제 Agent ID를 보유한 ID에만 적용되기 때문입니다. 즉, 클래식 에이전트는 에이전트용 ID 보호 및 조건부 액세스의 범위 밖에 있습니다.

여기서 껄끄러운 진실이 드러납니다. 현재 운영 중인 비인간 ID(파이프라인 뒤의 서비스 주체, 통합 도구, 스크립트, 플랫폼 도입 전의 Copilot Studio 봇 등)는 거의 모두 클래식 에이전트입니다. 이들은 대개 인간 계정보다 수가 많고, 실질적인 의미의 다요소 인증(MFA)이 없으며, 자격 증명이 추가되어도 Azure 포털에 즉시 나타나지 않습니다. 새로운 플랫폼의 보호 기능은 이들에게 닿지 않습니다. 여러분이 이들을 마이그레이션하기 전까지, 이 집단에 대한 탐지 범위를 확보할 수 있는 유일한 곳은 SIEM(Sentinel)뿐입니다.

따라서 이것이 Agent ID는 할 수 없지만 Sentinel이 해야 할 일입니다. 즉, 플랫폼이 아직 보호할 수 없는 클래식 서비스 주체 기반 에이전트의 위험한 행동을 탐지하는 것입니다.

보유한 텔레메트리와 사람들이 자주 잊는 스위치 하나

대부분의 신호는 세 가지 테이블에 담겨 있습니다.

  1. AADServicePrincipalSignInLogs: 에이전트와 자동화 도구가 사용하는 클라이언트 자격 증명 기반의 서비스 주체 인증을 기록합니다. 사용자도 없고 MFA도 없으며, 앱이 암호(Secret)나 인증서를 보유하고 있음을 증명할 뿐입니다.
  2. AADManagedIdentitySignInLogs: 관리 ID(Managed Identity)에 대해 동일한 역할을 수행합니다.
  3. AuditLogs: 디렉터리 변경 사항을 기록합니다. 여기에는 지속성(Persistence) 확보에 가장 중요한 '애플리케이션 또는 서비스 주체에 새 자격 증명 추가' 이벤트가 포함됩니다.

본격적인 작업에 앞서 실무적인 경고를 하나 드리자면, 서비스 주체 및 관리 ID 로그인 로그는 기본적으로 스트리밍되지 않습니다. 워크스페이스로 데이터를 보내는 Entra 진단 설정에서 해당 범주를 명시적으로 활성화해야 합니다. 많은 팀이 탐지 규칙을 작성하고도 정작 테이블이 비어 있다는 사실을 확인하지 않아 놓치곤 합니다. 이 부분부터 먼저 확인하십시오.

탐지 1: 서비스 주체 또는 앱에 새 자격 증명 추가

기존 서비스 주체에 암호나 인증서를 추가하는 것은 Microsoft 클라우드에서 가장 깔끔한 지속성 확보 기법 중 하나입니다. 공격자는 권한이 있는 사용자나 앱을 탈취한 뒤, 유용한 Graph 권한을 이미 가진 서비스 주체에 신규 자격 증명을 심어 넣습니다. 이렇게 하면 암호 재설정이나 세션 취소 후에도 액세스 권한을 유지할 수 있습니다. 이는 MITRE ATT&CK의 **T1098.001 (Account Manipulation: Additional Cloud Credentials)**에 해당합니다. 클래식 에이전트의 경우, 이를 감시하는 ID 보호 베이스라인이 없기 때문에 특히 치명적입니다.

// 탐지 1: 애플리케이션 또는 서비스 주체에 새 암호 또는 인증서 추가됨
// MITRE T1098.001 - Account Manipulation: Additional Cloud Credentials
AuditLogs
| where OperationName has_any ("Add service principal", "Certificates and secrets management")
| where Result =~ "success"
| extend Initiator = coalesce(
        tostring(InitiatedBy.user.userPrincipalName),
        tostring(InitiatedBy.app.displayName))
| extend InitiatorIp = tostring(InitiatedBy.user.ipAddress)
| mv-apply Target = TargetResources on (
    where Target.type =~ "Application"
    | extend TargetName  = tostring(Target.displayName),
             TargetId    = tostring(Target.id),
             KeyChanges  = Target.modifiedProperties
  )
| mv-apply Prop = KeyChanges on (
    where tostring(Prop.displayName) =~ "KeyDescription"
    | extend NewKeys = parse_json(tostring(Prop.newValue)),
             OldKeys = parse_json(tostring(Prop.oldValue))
  )
| extend AddedKeys = set_difference(NewKeys, OldKeys)
| where array_length(AddedKeys) > 0
| project TimeGenerated, Initiator, InitiatorIp, TargetName, TargetId, AddedKeys
| order by TimeGenerated desc

작업 필터는 로그에서 이 이벤트가 나타나는 세 가지 형태("Add service principal", "Add service principal credentials", "Update application - Certificates and secrets management")를 모두 잡아냅니다. modifiedProperties 파싱을 통해 KeyDescription 변경 사항을 분리하고, set_difference를 사용하여 단순히 기존 자격 증명을 교체(삭제 후 추가)하는 것이 아니라 실제로 키가 '추가'되었는지 확인하여 오탐을 줄입니다.

정상적인 자격 증명 교체나 자동화된 배포(CI/CD, IaC) 과정에서 오탐이 발생할 수 있습니다. 판별의 핵심은 '수행자(Initiator)'입니다. 일반적인 시간에 배포 파이프라인의 서비스 계정에 의해 추가된 자격 증명은 일상적인 일입니다. 하지만 업무 시간 외에 대화형 관리자 계정에 의해, 혹은 평소 앱 자격 증명을 만지지 않던 계정에 의해 수행된 변경은 반드시 확인해야 합니다. 타겟이 아닌 **수행자를 허용 목록(Allow-list)**에 넣으십시오.

탐지 2: 클래식 에이전트가 처음 보는 IP에서 로그인

항상 특정 Azure 리전에서만 인증하던 서비스 주체가 갑자기 새로운 곳에서 로그인을 시도한다면, 이는 자격 증명이 유출되어 다른 곳에서 사용되고 있다는 강력한 신호입니다. 서비스 주체는 네트워크 행동 패턴이 매우 안정적이고 단조롭기 때문에, '처음 보는 IP'는 떠돌아다니는 인간 사용자보다 훨씬 더 명확한 지표가 됩니다. 이것은 현대적 에이전트가 Agent ID를 통해 무료로 받는 '행동 베이스라인' 기능을 클래식 에이전트를 위해 KQL로 재구현한 것입니다. (MITRE T1078.004 - Valid Accounts: Cloud Accounts)

// 탐지 2: 클래식 에이전트 서비스 주체가 이전에 보지 못한 IP에서 로그인함
// MITRE T1078.004 - Valid Accounts: Cloud Accounts
let baseline  = 14d;
let detection = 1d;
let KnownIPs =
    AADServicePrincipalSignInLogs
    | where TimeGenerated between (ago(baseline + detection) .. ago(detection))
    | where tostring(ResultType) == "0"
    | summarize KnownIPSet = make_set(IPAddress) by AppId;
AADServicePrincipalSignInLogs
| where TimeGenerated > ago(detection)
| where tostring(ResultType) == "0"
| lookup kind=leftouter KnownIPs on AppId
| where set_has_element(KnownIPSet, IPAddress) == false
| summarize FirstSeen = min(TimeGenerated),
            Resources = make_set(ResourceDisplayName, 10)
  by ServicePrincipalName, AppId, IPAddress
| order by FirstSeen desc

이 쿼리는 지난 2주 동안의 애플리케이션별 소스 IP 베이스라인을 구축한 후, 오늘 해당 집합 이외의 주소에서 발생한 성공적인 로그인을 플래깅합니다. 두 가지 튜닝 팁이 있습니다. 첫째, 완전히 새로운 서비스 주체는 베이스라인이 없으므로 첫 사용 시 탐지됩니다. 이는 대개 한 번쯤 확인해 볼 가치가 있지만, 너무 시끄럽다면 베이스라인 기간보다 생성일이 짧은 AppId를 제외할 수 있습니다. 둘째, 에이전트가 유동적인 클라우드 IP 범위를 사용하는 경우, 정확한 IP 대신 AS 번호(Autonomous System Number)나 알려진 범위 허용 목록을 사용하도록 비교 대상을 넓히십시오. 그렇지 않으면 본인의 인프라를 쫓아다니느라 시간을 허비하게 됩니다.

이 기능은 Agent ID를 대체하는 것이 아니라 보완하는 것입니다!

최종 목표는 이 규칙들을 영원히 실행하는 것이 아니라, 이 규칙이 적용되어야 하는 대상 인구(Population)를 줄이는 것입니다. 테넌트에서 "Has Agent ID: No"로 표시된 에이전트를 인벤토리화하고, 민감한 Graph 권한을 가진 에이전트부터 우선순위를 정하여 Agent ID 플랫폼으로 마이그레이션하십시오. 마이그레이션이 완료되면 수동으로 수행하던 베이스라인 작업을 ID 보호와 조건부 액세스가 대신하게 됩니다. Microsoft는 클래식 에이전트에서 현대적 에이전트로의 마이그레이션 경로를 예고한 바 있습니다. 그전까지는 이 두 가지 탐지 규칙을 필요한 방어 수단이자, 플랫폼으로 이동하지 못하는 대상들을 위한 영구적인 안전망으로 활용하십시오.

이번 주에 딱 한 가지만 해야 한다면, 서비스 주체 로그인 로그 카테고리를 활성화하고, 탐지 1번을 배포한 뒤, 지난 90일 동안 자격 증명이 추가된 모든 서비스 주체 목록을 뽑아보십시오. 그 목록만으로도 예상보다 훨씬 흥미로운 사실들을 발견하게 될 것입니다.

 

감사합니다. Marcel 드림