- Дата публикации
Как Microsoft Sentinel ловит «классические» AI‑агенты, которых не видит Entra Agent ID
Что нового
На Build 2026 Microsoft официально зафиксировала новую реальность: индустрия уходит от эпохи приложений к эпохе агентов. Вместе с этим Microsoft выкатил целый стек для безопасности таких агентов — от разработки до продакшена.
Ключевые новинки на стороне идентичности:
-
Microsoft Entra Agent ID
- Статус: GA (general availability).
- Даёт AI‑агентам полноценные цифровые личности — как у пользователей.
- Расширяет на агентов:
- Conditional Access (условный доступ),
- Identity Protection for Agents (поведенческая аналитика и аномалии),
- полный аудит всех действий.
-
Жёсткое разделение агентов на два типа:
- Modern agents — созданы через платформу Agent ID, имеют:
- собственный Agent ID,
- «чертёж» идентичности (identity blueprint),
- полный журнал аудита,
- защиту Identity Protection и политику Conditional Access для агентов.
- Classic agents — всё, что существовало раньше или создаётся в обход платформы:
- сервисные принципы и app registrations, через которые работают AI‑агенты;
- Copilot Studio‑агенты, созданные до включения Agent ID;
- самописные автоматизации, которые ходят в Microsoft Graph по client credentials.
- Modern agents — созданы через платформу Agent ID, имеют:
-
Новый фокус для SOC: Microsoft Sentinel как единственный радар для «классики»
- Entra Agent ID не защищает classic agents.
- Большинство существующих не‑человеческих идентичностей в тенанте — это именно classic agents:
- сервисные принципы для пайплайнов,
- интеграции,
- скрипты,
- старые Copilot Studio‑боты.
- Для них поведенческая защита и аномалии доступны только через SIEM, то есть через Microsoft Sentinel.
-
Две готовые детекции для Sentinel:
- Detection 1: отслеживание добавления новых секретов/сертификатов к приложению или сервисному принципу (MITRE T1098.001).
- Detection 2: вход классического агента с IP‑адреса, который ему раньше не был свойственен (MITRE T1078.004).
Как это работает
Modern vs Classic: где проходит граница
Modern agents:
- создаются только через платформу Entra Agent ID;
- каждый агент привязан к agent identity blueprint;
- получают:
- собственный Agent ID,
- автоматическое построение поведенческого базлайна,
- Identity Protection for Agents (анализ аномалий),
- Conditional Access для агентов,
- полные журналы аудита.
Classic agents:
- всё, что не прошло через Agent ID:
- обычные service principals и app registrations;
- Copilot Studio‑агенты, созданные до включения Agent ID;
- любые скрипты и автоматизации, которые используют client credentials для доступа к Graph.
- в реестре агентов Entra помечены как «Has Agent ID: No»;
- не попадают под Identity Protection for Agents и Conditional Access for Agents.
Проблема: именно classic agents обычно:
- численно превышают количество человеческих аккаунтов;
- не используют MFA (и не могут в классическом смысле);
- могут получать новые креденшелы так, что это не видно в портале Azure без детального аудита.
Где Sentinel закрывает дыру
Пока вы не мигрировали classic agents на Agent ID, единственный способ увидеть их рискованное поведение — телеметрия в SIEM. Microsoft Sentinel получает данные из Microsoft Entra и строит детекции по логам.
Три ключевые таблицы с сигналами:
-
AADServicePrincipalSignInLogs
- Логирует аутентификацию сервисных принципов.
- Это входы по client credentials: без пользователя, без MFA, только секрет или сертификат.
-
AADManagedIdentitySignInLogs
- Аналогично, но для Managed Identity.
-
AuditLogs
- Все изменения в каталоге Entra.
- Важное событие для персистентности: добавление нового секрета или сертификата к приложению или сервисному принципу.
Критичный момент конфигурации:
- Логи входов сервисных принципов и Managed Identity по умолчанию не стримятся в Sentinel.
- Их нужно явно включить в Diagnostic Settings Entra, которые отправляют данные в Log Analytics workspace.
- Многие команды пишут правила детекции, но не включают эти категории — в итоге таблицы пустые.
Detection 1: новый секрет или сертификат на сервисном принципе
Сценарий атаки:
- злоумышленник получает доступ к привилегированному пользователю или приложению;
- добавляет новый секрет/сертификат к уже существующему сервисному принципу с полезными правами в Graph;
- дальше использует этот ключ, даже если пароль пользователя сменили или сессии сбросили.
Это чистая реализация MITRE T1098.001 — Account Manipulation: Additional Cloud Credentials.
Код KQL‑запроса из материала:
// Detection 1: new secret or certificate added to an application or service principal
// 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
Как это работает:
OperationNameфильтрует три возможные формы события:- Add service principal,
- Add service principal credentials,
- Update application - Certificates and secrets management.
- Через
modifiedPropertiesвыбирается изменение KeyDescription. set_difference(NewKeys, OldKeys)проверяет, что ключ добавили, а не удалили.- Простая ротация старого секрета не триггерит правило.
Откуда ложные срабатывания:
- легитимная ротация ключей;
- CI/CD и инфраструктура‑как‑код, которые создают креденшелы приложений.
Главный признак для triage:
- инициатор, а не цель:
- если секрет добавил сервисный аккаунт пайплайна в привычное время — это норма;
- если то же действие сделал интерактивный администратор ночью или аккаунт, который раньше никогда не трогал креденшелы приложений — это повод разбираться.
Detection 2: классический агент заходит с нового IP
Сервисные принципы обычно ведут себя предсказуемо:
- работают из ваших Azure‑регионов или фиксированных IP‑диапазонов;
- не «путешествуют» как люди.
Если сервисный принцип, который всегда логинился только из ваших адресов, внезапно появляется с другого IP, это сильный сигнал утечки секрета.
MITRE: T1078.004 — Valid Accounts: Cloud Accounts.
KQL‑запрос:
// Detection 2: classic-agent service principal signing in from a previously unseen 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
Как это устроено:
- Строится персональный базлайн IP‑адресов для каждого
AppIdза последние 14 дней (baseline). - Дальше анализируется последний 1 день (
detection). - Любой успешный логин (
ResultType == "0") с IP, которого нет вKnownIPSet, попадает в выборку.
Нюансы настройки:
- Новые сервисные принципы ещё не имеют истории, поэтому появятся в выборке при первом входе.
- Обычно это полезно увидеть хотя бы один раз.
- Если шумно — можно исключать
AppId, созданные менее чем 14 дней назад.
- Если агенты выходят в интернет через плавающие cloud‑IP, лучше:
- расширить сравнение до AS‑номера;
- или использовать allow‑list известных диапазонов.
- Иначе будете ловить собственную инфраструктуру.
Что это значит для вас
Если вы отвечаете за безопасность в Microsoft 365 / Azure
-
Признайте, что большинство ваших агентов — «классика»
- Все старые Copilot Studio‑боты, пайплайны, интеграции и скрипты, которые ходят в Graph — это classic agents.
- Они почти всегда:
- без MFA,
- с долгоживущими секретами,
- с правами, которые никто давно не ревьюил.
-
Не рассчитывайте только на Entra Agent ID
- Agent ID отлично защищает новых агентов, созданных по всем правилам.
- Но пока вы не мигрировали старые сервисные принципы на платформу Agent ID, они остаются «в тени».
- Для них реальная защита — это детекции в Sentinel.
-
Минимальный план на неделю:
- Включите в Entra Diagnostic Settings стриминг:
- AADServicePrincipalSignInLogs;
- AADManagedIdentitySignInLogs;
- AuditLogs (если ещё не включены).
- Задеплойте Detection 1 в Sentinel.
- Вытащите список всех сервисных принципов, которым добавляли креденшелы за последние 90 дней.
- Этот список почти всегда оказывается неожиданно интересным: там часто всплывают забытые интеграции и подозрительные админские действия.
- Включите в Entra Diagnostic Settings стриминг:
-
Как использовать детекции на практике
- Detection 1:
- завяжите алерты на инициаторов, которые не входят в список ожидаемых сервисных аккаунтов CI/CD;
- для «нормальных» пайплайнов — настройте suppression или отдельный low‑severity сигнал.
- Detection 2:
- заведите allow‑list IP‑диапазонов для ваших дата‑центров и egress‑узлов;
- всё, что приходит извне — в отдельный high‑severity инцидент.
- Detection 1:
-
Где не стоит переоценивать этот подход
- Эти KQL‑детекции не заменяют Identity Protection for Agents:
- нет автоматического машинного анализа паттернов поведения;
- нет интеграции с Conditional Access для автоматических блокировок.
- Это «страховка» для классических агентов и временный костыль, пока вы не перевели их на Agent ID.
- Эти KQL‑детекции не заменяют Identity Protection for Agents:
Если вы строите собственных AI‑агентов
- Для новых проектов:
- создавайте агентов сразу через Entra Agent ID;
- не используйте «голые» сервисные принципы без Agent ID, если это можно избежать.
- Для существующих проектов:
- инвентаризируйте все объекты в Entra, у которых Has Agent ID: No;
- приоритизируйте миграцию тех, у кого:
- высокие права в Graph;
- доступ к критичным данным и операциям.
Доступность и ограничения
- Всё описанное относится к экосистеме Microsoft Entra + Microsoft Sentinel.
- Для работы нужен:
- тенант Microsoft Entra (бывший Azure AD);
- рабочее пространство Log Analytics;
- развёрнутый Microsoft Sentinel.
- В России доступ к этим сервисам может потребовать VPN и юридическую оценку рисков. Это нужно учитывать при планировании.
Место на рынке
Здесь речь не про очередной LLM, а про связку Entra Agent ID + Microsoft Sentinel как платформу для безопасности AI‑агентов.
Роль продуктов:
- Entra Agent ID — даёт современным AI‑агентам полноценную идентичность и «вшитую» аналитику поведения.
- Microsoft Sentinel — закрывает слепую зону для классических агентов, которые пока живут на сервисных принципах и managed identity.
На рынке SIEM‑решений и облачных IAM‑платформ это выглядит так:
- многие вендоры SIEM могут обрабатывать логи OAuth‑клиентов и сервисных аккаунтов;
- но глубокая связка именно с Entra Agent ID и понятие modern vs classic agents — это специфическая история Microsoft.
Прямых численных сравнений с другими SIEM или IAM в исходных данных нет. Главное отличие подхода Microsoft здесь — в том, что:
- Entra Agent ID берёт на себя защиту новых агентов «из коробки»;
- Sentinel даёт возможность дотянуться до старых сервисных принципов за счёт KQL‑детекций.
Как запустить
1. Включаем нужные логи в Entra
- Зайдите в Microsoft Entra admin center.
- Откройте раздел Diagnostic settings для каталога.
- Убедитесь, что в Log Analytics workspace, к которому подключён Sentinel, стримятся категории:
- AuditLogs;
- SignInLogs;
- Service principal sign-in logs (AADServicePrincipalSignInLogs);
- Managed identity sign-in logs (AADManagedIdentitySignInLogs).
Без этого KQL‑запросы из статьи просто не увидят нужные события.
2. Detection 1: новый ключ у сервисного принципа или приложения
Создайте в Sentinel Analytics rule на основе KQL из раздела выше:
// Detection 1: new secret or certificate added to an application or service principal
// 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
Рекомендации по настройке:
- Период анализа: 5–15 минут.
- Severity: High для не‑ожидаемых инициаторов.
- Добавьте allow‑list для сервисных аккаунтов CI/CD.
3. Detection 2: первый вход с нового IP для классического агента
Создайте второе правило в Sentinel с этим KQL:
// Detection 2: classic-agent service principal signing in from a previously unseen 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
Рекомендации:
- Оставьте
baseline = 14dиdetection = 1dкак стартовые значения. - Добавьте фильтрацию по известным IP‑диапазонам, если ваши агенты живут в нескольких регионах.
- Severity: Medium–High, в зависимости от критичности прав конкретного сервисного принципа.
Финальный ориентир: цель не в том, чтобы вечно поддерживать зоопарк детекций для classic agents. Цель — сократить их количество, перевести критичные сервисные принципы на Entra Agent ID и оставить эти правила как страховку для всего, что по разным причинам так и останется «классикой».