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