↳ GitHub sourceAnalytics ruleLow

Accessed files shared by temporary external user

Description

'This detection identifies when an external user is added to a Team or Teams chat and shares a file which is accessed by many users (>10) and the users is removed within short period of time. This might be an indicator of suspicious activity.'
Rule type
Scheduled
Version
2.1.1
Declared status
Available
Query frequency
1h
Query period
1h
Trigger
gt 0

Declared MITRE coverage

Declared sources

Metadata from the source file. No dependencies inferred from KQL.

Connectors

Data types

KQL query

Original query, unchanged.

let fileAccessThrehold = 10;
OfficeActivity
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberAdded"
| extend MemberAdded = tostring(parse_json(Members)[0].UPN)
| where MemberAdded contains ("#EXT#")
| project TimeAdded=TimeGenerated, Operation, MemberAdded, UserWhoAdded = UserId, TeamName
| join kind = inner (
  OfficeActivity
  | where OfficeWorkload =~ "MicrosoftTeams"
  | where Operation =~ "MemberRemoved"
  | extend MemberAdded = tostring(parse_json(Members)[0].UPN)
  | where MemberAdded contains ("#EXT#")
  | project TimeDeleted=TimeGenerated, Operation, MemberAdded, UserWhoDeleted = UserId, TeamName
  ) on MemberAdded
| where TimeDeleted > TimeAdded
| join kind=inner (
  OfficeActivity
  | where RecordType == "SharePointFileOperation"
  | where SourceRelativeUrl has "Microsoft Teams Chat Files"
  | where Operation == "FileUploaded"
  | extend MemberAdded = UserId
  | join kind = inner (
      OfficeActivity
      | where RecordType == "SharePointFileOperation"
      | where Operation  == "FileAccessed"
      | where SourceRelativeUrl has "Microsoft Teams Chat Files"
      | summarize FileAccessCount = count() by OfficeObjectId
      | where FileAccessCount > fileAccessThrehold
      ) on $left.OfficeObjectId == $right.OfficeObjectId
  )on MemberAdded
| project-away MemberAdded1, MemberAdded2, OfficeObjectId1, Operation1, Operation2, TeamName1, TeamName2
| extend MemberAddedAccountName = tostring(split(MemberAdded, "@")[0]), MemberAddedAccountUPNSuffix = tostring(split(MemberAdded, "@")[1])
| extend UserWhoAddedAccountName = tostring(split(UserWhoAdded, "@")[0]), UserWhoAddedAccountUPNSuffix = tostring(split(UserWhoAdded, "@")[1])
| extend UserWhoDeletedAccountName = tostring(split(UserWhoDeleted, "@")[0]), UserWhoDeletedAccountUPNSuffix = tostring(split(UserWhoDeleted, "@")[1])

Declared entities

AccountIP

Related content

Links established from declared identifiers and solution manifests.

Source provenance

GitHub

Displayed values come from files in Azure/Azure-Sentinel. They describe the published template, not your workspace configuration.

Source identifier
bff058b2-500e-4ae5-bb49-a5b1423cbd5b
Additional source files 3Solutions/Microsoft 365/Analytic Rules/External User added to Team and immediately uploads file.yamlsource ↗Detections/OfficeActivity/External User added to Team and immediately uploads file.yamlmigration-note ↗Solutions/Microsoft 365/Data/Solution_Office365.jsonsolution-membership ↗
GSTEP / CATALOG TRACKING

Added to catalog : 16 Sept 2026 · 05:49 UTC
Last change observed : 16 Sept 2026 · 05:49 UTC

GSTEP sync dates, separate from the source content’s publication dates.