Поделиться через


Microsoft Sentinel и Microsoft Teams

Важно!

Microsoft Sentinel теперь имеет интегрированный соединитель. Дополнительные сведения см. в статье Подключение журналов Office 365 к Microsoft Sentinel. Таков рекомендуемый метод для сбора этих журналов; он заменяет собой методы сбора, описанные ниже.

Teams играет центральную роль во взаимодействии и распространении данных в облаке Microsoft 365. Так как служба Teams связана со многими базовыми технологиями в облаке, она может использовать преимущества человеческого и автоматизированного анализа. Это относится как к поиску в журналах, так и при отслеживании собраний в режиме реального времени. Microsoft Sentinel предлагает администраторам эти решения.

Примечание.

Требуется обновление в Microsoft Sentinel? Эта статья как раз для этого.

Sentinel и журналы действий Microsoft Teams

Эта статья посвящена сбору журналов действий Teams в Microsoft Sentinel.

Sentinel позволяет администраторам управлять безопасностью в одном месте. Это включает в себя управление:

  • Сторонними устройствами
  • Защита от угроз (Майкрософт)
  • Рабочими нагрузками Microsoft 365

Книги Sentinel и модули Runbook могут сделать мониторинг безопасности системным. Хорошим первым шагом в этом процессе является сбор необходимых журналов для анализа.

Примечание.

В одном экземпляре Microsoft Sentinel можно использовать несколько подписок Microsoft 365. Это позволит выполнять отслеживание в режиме реального времени и обнаруживать угрозы в архивных файлах журнала. Администраторы смогут выполнять поиск, используя запросы в разных ресурсах, в одной группе ресурсов, в разных группах ресурсов или в другой подписке.

Шаг 1. Сбор журналов Teams: включение журналов аудита в Microsoft 365

Так как Teams регистрирует действия через Microsoft 365, журналы аудита не собираются по умолчанию. Эту функцию можно включить, выполнив следующие шаги. Данные Teams собираются для аудита Microsoft 365 в разделе Audit.General.

Шаг 2. Подключение журналов Office 365 к Microsoft Sentinel

Microsoft Sentinel предоставляет встроенный соединитель для Office 365 журналов, который позволяет принимать данные Teams в Microsoft Sentinel вместе с другими Office 365 данными.

В Microsoft Sentinel включите соединитель данных Office 365. Дополнительные сведения см. в документации по Microsoft Sentinel.

Полезные запросы KQL для поиска

Используйте эти запросы, чтобы познакомиться с данными и средой Teams. Понимание среды и ее поведения — это отличный первый шаг по выявлению подозрительных действий. После этого вы можете перейти к поиску угроз.

Запросы федеративных внешних пользователей

Получите список сайтов Teams с федеративными внешними пользователями. У этих пользователей есть доменное имя и/или суффикс UPN, которые не принадлежат вашей организации.

В этом примере запроса организации принадлежит домен contoso.com.

OfficeActivity
| where TimeGenerated > ago(7d)
| where Operation =~ "MemberAdded"
| where parse_json(Members)[0].Role == 3
| project TeamName, Operation, UserId, Members
| mv-expand bagexpansion=array Members
| evaluate bag_unpack(Members)

Совет

Дополнительные сведения о внешнем и гостевом типах доступа в Teams см. в разделе Общение с пользователями из других организаций или в разделе Типы участников в руководстве по безопасности Teams.

Кто недавно присоединился или чья роль изменена

Запросите определенного пользователя, чтобы проверить, был ли он добавлен в канал Teams за последние 7 дней или в течение недели:

OfficeActivity
| where TimeGenerated > ago(7d)
| where Operation =~ "MemberAdded"
| where Members has "<DisplayName>" or Members has "<UserPrincipalName>"
| project TeamName, Operation, UserId, Members

Сделайте запрос о том, изменилась ли роль пользователя в команде за последние 7 дней:

OfficeActivity
| where TimeGenerated > ago(7d)
| where Operation =~ "MemberRoleChanged"
| project TeamName, Operation, UserId, Members
| mv-expand bagexpansion=array Members
| evaluate bag_unpack(Members)
| where Role == '1'

Внешние пользователи из неизвестных или новых организаций

В Teams вы можете добавлять внешних пользователей в среду или каналы. Организации часто имеют ограниченное количество ключевых партнеров и добавляют пользователей этих партнеров. Эта функция KQL ищет добавленных в команды внешних пользователей из организаций, которые раньше отсутствовали или не добавлялись.

Дополнительные сведения см. в запросе в центре Git сообщества Microsoft Sentinel.

Внешние пользователи, которые были добавлены, а затем удалены

Злоумышленники с определенным уровнем доступа могут добавить новую внешнюю учетную запись в Teams, чтобы получить доступ и извлечь данные. Они также могут быстро удалить этого пользователя, чтобы скрыть получение доступа. Этот запрос используется для поиска внешних учетных записей, которые добавлены в Teams и быстро удалены, чтобы выявить подозрительное поведение.

Дополнительные сведения см. в запросе в центре Git сообщества Microsoft Sentinel.

Добавлен новый бот или приложение

Teams может включать приложения или ботов в команду для расширения набора функций (включая пользовательские приложения и боты). В некоторых случаях приложение или бот могут использоваться для сохраняемости в Teams без необходимости учетной записи пользователя, а также могут получать доступ к файлам и другим данным. Этот запрос используется для поиска новых приложений и ботов в Teams.

Дополнительные сведения см. в запросе в центре Git сообщества Microsoft Sentinel.

Учетные записи пользователей, являющихся владельцами большого количества команд

Злоумышленники, пытающиеся получить дополнительные права, могут назначать себе права владельцев большого количества разнообразных команд. Обычно пользователи создают и владеют несколькими командами, посвященным определенным темам. Этот запрос KQL ищет подозрительные действия.

Дополнительные сведения см. в запросе в центре Git сообщества Microsoft Sentinel.

Удаление большого количества команд одним пользователем

Злоумышленники могут вызывать нарушения в работе и создавать угрозы проектам и данным, удаляя несколько команд. Так как команды обычно удаляются отдельными владельцами, централизованное удаление нескольких команд может быть признаком проблемы. Этот запрос KQL ищет отдельных пользователей, удаляющих несколько команд.

Дополнительные сведения см. в запросе в центре Git сообщества Microsoft Sentinel.

Расширение возможностей охоты на угрозы

С запросами Teams можно использовать объединение запросов из ресурсов, таких как идентификатор Microsoft Entra или другие рабочие нагрузки Office 365. Например, объедините обнаружение подозрительных шаблонов в Microsoft Entra SigninLogs и используйте эти выходные данные при поиске владельцев команд.

let timeRange = 1d;
let lookBack = 7d;
let threshold_Failed = 5;
let threshold_FailedwithSingleIP = 20;
let threshold_IPAddressCount = 2;
let isGUID = "[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}";
let azPortalSignins = SigninLogs
| where TimeGenerated >= ago(timeRange)
// Azure Portal only and exclude non-failure Result Types
| where AppDisplayName has "Azure Portal" and ResultType !in ("0", "50125", "50140")
// Tagging identities not resolved to friendly names
| extend Unresolved = iff(Identity matches regex isGUID, true, false);
// Lookup up resolved identities from last 7 days
let identityLookup = SigninLogs
| where TimeGenerated >= ago(lookBack)
| where not(Identity matches regex isGUID)
| summarize by UserId, lu_UserDisplayName = UserDisplayName, lu_UserPrincipalName = UserPrincipalName;
// Join resolved names to unresolved list from portal signins
let unresolvedNames = azPortalSignins | where Unresolved == true | join kind= inner (
   identityLookup ) on UserId
| extend UserDisplayName = lu_UserDisplayName, UserPrincipalName = lu_UserPrincipalName
| project-away lu_UserDisplayName, lu_UserPrincipalName;
// Join Signins that had resolved names with list of unresolved that now have a resolved name
let u_azPortalSignins = azPortalSignins | where Unresolved == false | union unresolvedNames;
let failed_signins = (u_azPortalSignins
| extend Status = strcat(ResultType, ": ", ResultDescription), OS = tostring(DeviceDetail.operatingSystem), Browser = tostring(DeviceDetail.browser)
| extend FullLocation = strcat(Location,'|', LocationDetails.state, '|', LocationDetails.city)
| summarize TimeGenerated = makelist(TimeGenerated), Status = makelist(Status), IPAddresses = makelist(IPAddress), IPAddressCount = dcount(IPAddress), FailedLogonCount = count()
by UserPrincipalName, UserId, UserDisplayName, AppDisplayName, Browser, OS, FullLocation
| mvexpand TimeGenerated, IPAddresses, Status
| extend TimeGenerated = todatetime(tostring(TimeGenerated)), IPAddress = tostring(IPAddresses), Status = tostring(Status)
| project-away IPAddresses
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by UserPrincipalName, UserId, UserDisplayName, Status, FailedLogonCount, IPAddress, IPAddressCount, AppDisplayName, Browser, OS, FullLocation
| where (IPAddressCount >= threshold_IPAddressCount and FailedLogonCount >= threshold_Failed) or FailedLogonCount >= threshold_FailedwithSingleIP
| project UserPrincipalName);
OfficeActivity
| where TimeGenerated > ago(time_window)
| where Operation =~ "MemberRoleChanged"
| mv-expand bagexpansion=array Members
| evaluate bag_unpack(Members)
| where Role == '2'
| where Members in (failed_signins)

Вы также можете сделать обнаружения SigninLogs специфичными для Teams, добавив фильтр только для входов на основе Teams:

| where AppDisplayName has 'Teams'

Для дополнительного разъяснения использования где у AppDisplayName есть Teams запрос KQL ниже демонстрирует успешный вход с одного IP-адреса и неудачный вход с другого IP-адреса, но ограничен только входами в Teams:

let timeFrame = 1d;
let logonDiff = 10m;
SigninLogs 
  | where TimeGenerated >= ago(timeFrame) 
  | where ResultType == "0" 
  | where AppDisplayName has "Teams"
  | project SuccessLogonTime = TimeGenerated, UserPrincipalName, SuccessIPAddress = IPAddress, AppDisplayName, SuccessIPBlock = strcat(split(IPAddress, ".")[0], ".", split(IPAddress, ".")[1])
  | join kind= inner (
      SigninLogs 
      | where TimeGenerated >= ago(timeFrame) 
      | where ResultType !in ("0", "50140") 
      | where ResultDescription !~ "Other"  
      | where AppDisplayName startswith "Microsoft Teams"
      | project FailedLogonTime = TimeGenerated, UserPrincipalName, FailedIPAddress = IPAddress, AppDisplayName, ResultType, ResultDescription
  ) on UserPrincipalName, AppDisplayName 
  | where SuccessLogonTime < FailedLogonTime and FailedLogonTime - SuccessLogonTime <= logonDiff and FailedIPAddress !startswith SuccessIPBlock
  | summarize FailedLogonTime = max(FailedLogonTime), SuccessLogonTime = max(SuccessLogonTime) by UserPrincipalName, SuccessIPAddress, AppDisplayName, FailedIPAddress, ResultType, ResultDescription 
  | extend timestamp = SuccessLogonTime, AccountCustomEntity = UserPrincipalName, IPCustomEntity = SuccessIPAddress

Важная информация и обновления

Благодарим за совместную работу над контентом Пита Брайана, Николаса Диколу и Мэтью Лоу. Пит Брайан и люди, с которыми он совместно работает, продолжают разрабатывать запросы обнаружения и поиска для Teams.

Оставайтесь на связи с этим репозиторием Git Hub для обновлений.

Следите за обновлениями для анализатора и приложения логики, использовавшихся в этой статье.

Вы также должны присоединиться к сообществу Azure Sentinel и участвовать в нем. Мы очень ждем отзывы об этой статье, поэтому воспользуйтесь формой обратной связи ниже. Спасибо и удачной охоты на угрозы.

Регистрация приложения в идентификаторе Microsoft Entra

Включение и отключение поиска в журнале аудита

Что собой представляет Azure Sentinel?