Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

GSA Enriched Office 365 - Accessed files shared by temporary external user

Back
Id4d38f80f-6b7d-4a1f-aeaf-e38df637e6ac
RulenameGSA Enriched Office 365 - Accessed files shared by temporary external user
DescriptionThis 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.
SeverityLow
TacticsInitialAccess
TechniquesT1566
Required data connectorsAzureActiveDirectory
Office365
KindScheduled
Query frequency1h
Query period1h
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - External User added to Team and immediately uploads file.yaml
Version2.1.3
Arm template4d38f80f-6b7d-4a1f-aeaf-e38df637e6ac.json
Deploy To Azure
let fileAccessThreshold = 10;
// OfficeActivity Query
let OfficeEvents = 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 > fileAccessThreshold
        ) on OfficeObjectId
    ) on MemberAdded
    | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;
// EnrichedMicrosoft365AuditLogs Query
let EnrichedEvents = EnrichedMicrosoft365AuditLogs
    | where Workload =~ "MicrosoftTeams"
    | where Operation =~ "MemberAdded"
    | extend MemberAdded = tostring(parse_json(tostring(AdditionalProperties)).Members[0].UPN)
    | where MemberAdded contains "#EXT#"
    | project TimeAdded = TimeGenerated, Operation, MemberAdded, UserWhoAdded = UserId, TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)
    | join kind=inner (
        EnrichedMicrosoft365AuditLogs
        | where Workload =~ "MicrosoftTeams"
        | where Operation =~ "MemberRemoved"
        | extend MemberAdded = tostring(parse_json(tostring(AdditionalProperties)).Members[0].UPN)
        | where MemberAdded contains "#EXT#"
        | project TimeDeleted = TimeGenerated, Operation, MemberAdded, UserWhoDeleted = UserId, TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)
    ) on MemberAdded, TeamName
    | where TimeDeleted > TimeAdded
    | join kind=inner (
        EnrichedMicrosoft365AuditLogs
        | where RecordType == "SharePointFileOperation"
        | where Operation == "FileUploaded"
        | extend MemberAdded = UserId, SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl), TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)
        | where SourceRelativeUrl has "Microsoft Teams Chat Files"
        | join kind=inner (
            EnrichedMicrosoft365AuditLogs
            | where RecordType == "SharePointFileOperation"
            | where Operation == "FileAccessed"
            | extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl), TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)
            | where SourceRelativeUrl has "Microsoft Teams Chat Files"
            | summarize FileAccessCount = count() by ObjectId, TeamName
            | where FileAccessCount > fileAccessThreshold
        ) on ObjectId, TeamName
    ) on MemberAdded, TeamName
    | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;
// Combine Office and Enriched Events and Deduplicate
let CombinedEvents = OfficeEvents
    | union EnrichedEvents
    | summarize arg_min(TimeAdded, *) by MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;
// Project Final Output
CombinedEvents
    | 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])
    | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName, MemberAddedAccountName, MemberAddedAccountUPNSuffix, UserWhoAddedAccountName, UserWhoAddedAccountUPNSuffix, UserWhoDeletedAccountName, UserWhoDeletedAccountUPNSuffix
query: |
  let fileAccessThreshold = 10;
  // OfficeActivity Query
  let OfficeEvents = 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 > fileAccessThreshold
          ) on OfficeObjectId
      ) on MemberAdded
      | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;
  // EnrichedMicrosoft365AuditLogs Query
  let EnrichedEvents = EnrichedMicrosoft365AuditLogs
      | where Workload =~ "MicrosoftTeams"
      | where Operation =~ "MemberAdded"
      | extend MemberAdded = tostring(parse_json(tostring(AdditionalProperties)).Members[0].UPN)
      | where MemberAdded contains "#EXT#"
      | project TimeAdded = TimeGenerated, Operation, MemberAdded, UserWhoAdded = UserId, TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)
      | join kind=inner (
          EnrichedMicrosoft365AuditLogs
          | where Workload =~ "MicrosoftTeams"
          | where Operation =~ "MemberRemoved"
          | extend MemberAdded = tostring(parse_json(tostring(AdditionalProperties)).Members[0].UPN)
          | where MemberAdded contains "#EXT#"
          | project TimeDeleted = TimeGenerated, Operation, MemberAdded, UserWhoDeleted = UserId, TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)
      ) on MemberAdded, TeamName
      | where TimeDeleted > TimeAdded
      | join kind=inner (
          EnrichedMicrosoft365AuditLogs
          | where RecordType == "SharePointFileOperation"
          | where Operation == "FileUploaded"
          | extend MemberAdded = UserId, SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl), TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)
          | where SourceRelativeUrl has "Microsoft Teams Chat Files"
          | join kind=inner (
              EnrichedMicrosoft365AuditLogs
              | where RecordType == "SharePointFileOperation"
              | where Operation == "FileAccessed"
              | extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl), TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)
              | where SourceRelativeUrl has "Microsoft Teams Chat Files"
              | summarize FileAccessCount = count() by ObjectId, TeamName
              | where FileAccessCount > fileAccessThreshold
          ) on ObjectId, TeamName
      ) on MemberAdded, TeamName
      | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;
  // Combine Office and Enriched Events and Deduplicate
  let CombinedEvents = OfficeEvents
      | union EnrichedEvents
      | summarize arg_min(TimeAdded, *) by MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;
  // Project Final Output
  CombinedEvents
      | 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])
      | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName, MemberAddedAccountName, MemberAddedAccountUPNSuffix, UserWhoAddedAccountName, UserWhoAddedAccountUPNSuffix, UserWhoDeletedAccountName, UserWhoDeletedAccountUPNSuffix  
relevantTechniques:
- T1566
name: GSA Enriched Office 365 - Accessed files shared by temporary external user
severity: Low
triggerThreshold: 0
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.'
status: Available
triggerOperator: gt
tactics:
- InitialAccess
entityMappings:
- fieldMappings:
  - columnName: MemberAdded
    identifier: FullName
  - columnName: MemberAddedAccountName
    identifier: Name
  - columnName: MemberAddedAccountUPNSuffix
    identifier: UPNSuffix
  entityType: Account
- fieldMappings:
  - columnName: UserWhoAdded
    identifier: FullName
  - columnName: UserWhoAddedAccountName
    identifier: Name
  - columnName: UserWhoAddedAccountUPNSuffix
    identifier: UPNSuffix
  entityType: Account
- fieldMappings:
  - columnName: UserWhoDeleted
    identifier: FullName
  - columnName: UserWhoDeletedAccountName
    identifier: Name
  - columnName: UserWhoDeletedAccountUPNSuffix
    identifier: UPNSuffix
  entityType: Account
- fieldMappings:
  - columnName: ClientIP
    identifier: Address
  entityType: IP
requiredDataConnectors:
- connectorId: AzureActiveDirectory
  dataTypes:
  - EnrichedMicrosoft365AuditLogs
- connectorId: Office365
  dataTypes:
  - OfficeActivity (Teams)
id: 4d38f80f-6b7d-4a1f-aeaf-e38df637e6ac
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - External User added to Team and immediately uploads file.yaml
queryPeriod: 1h
queryFrequency: 1h
version: 2.1.3
kind: Scheduled
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2024-01-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/4d38f80f-6b7d-4a1f-aeaf-e38df637e6ac')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/4d38f80f-6b7d-4a1f-aeaf-e38df637e6ac')]",
      "properties": {
        "alertRuleTemplateName": "4d38f80f-6b7d-4a1f-aeaf-e38df637e6ac",
        "customDetails": null,
        "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.'\n",
        "displayName": "GSA Enriched Office 365 - Accessed files shared by temporary external user",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "MemberAdded",
                "identifier": "FullName"
              },
              {
                "columnName": "MemberAddedAccountName",
                "identifier": "Name"
              },
              {
                "columnName": "MemberAddedAccountUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserWhoAdded",
                "identifier": "FullName"
              },
              {
                "columnName": "UserWhoAddedAccountName",
                "identifier": "Name"
              },
              {
                "columnName": "UserWhoAddedAccountUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserWhoDeleted",
                "identifier": "FullName"
              },
              {
                "columnName": "UserWhoDeletedAccountName",
                "identifier": "Name"
              },
              {
                "columnName": "UserWhoDeletedAccountUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "ClientIP",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - External User added to Team and immediately uploads file.yaml",
        "query": "let fileAccessThreshold = 10;\n// OfficeActivity Query\nlet OfficeEvents = OfficeActivity\n    | where OfficeWorkload =~ \"MicrosoftTeams\"\n    | where Operation =~ \"MemberAdded\"\n    | extend MemberAdded = tostring(parse_json(Members)[0].UPN)\n    | where MemberAdded contains \"#EXT#\"\n    | project TimeAdded = TimeGenerated, Operation, MemberAdded, UserWhoAdded = UserId, TeamName\n    | join kind=inner (\n        OfficeActivity\n        | where OfficeWorkload =~ \"MicrosoftTeams\"\n        | where Operation =~ \"MemberRemoved\"\n        | extend MemberAdded = tostring(parse_json(Members)[0].UPN)\n        | where MemberAdded contains \"#EXT#\"\n        | project TimeDeleted = TimeGenerated, Operation, MemberAdded, UserWhoDeleted = UserId, TeamName\n    ) on MemberAdded\n    | where TimeDeleted > TimeAdded\n    | join kind=inner (\n        OfficeActivity\n        | where RecordType == \"SharePointFileOperation\"\n        | where SourceRelativeUrl has \"Microsoft Teams Chat Files\"\n        | where Operation == \"FileUploaded\"\n        | extend MemberAdded = UserId\n        | join kind=inner (\n            OfficeActivity\n            | where RecordType == \"SharePointFileOperation\"\n            | where Operation == \"FileAccessed\"\n            | where SourceRelativeUrl has \"Microsoft Teams Chat Files\"\n            | summarize FileAccessCount = count() by OfficeObjectId\n            | where FileAccessCount > fileAccessThreshold\n        ) on OfficeObjectId\n    ) on MemberAdded\n    | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;\n// EnrichedMicrosoft365AuditLogs Query\nlet EnrichedEvents = EnrichedMicrosoft365AuditLogs\n    | where Workload =~ \"MicrosoftTeams\"\n    | where Operation =~ \"MemberAdded\"\n    | extend MemberAdded = tostring(parse_json(tostring(AdditionalProperties)).Members[0].UPN)\n    | where MemberAdded contains \"#EXT#\"\n    | project TimeAdded = TimeGenerated, Operation, MemberAdded, UserWhoAdded = UserId, TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)\n    | join kind=inner (\n        EnrichedMicrosoft365AuditLogs\n        | where Workload =~ \"MicrosoftTeams\"\n        | where Operation =~ \"MemberRemoved\"\n        | extend MemberAdded = tostring(parse_json(tostring(AdditionalProperties)).Members[0].UPN)\n        | where MemberAdded contains \"#EXT#\"\n        | project TimeDeleted = TimeGenerated, Operation, MemberAdded, UserWhoDeleted = UserId, TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)\n    ) on MemberAdded, TeamName\n    | where TimeDeleted > TimeAdded\n    | join kind=inner (\n        EnrichedMicrosoft365AuditLogs\n        | where RecordType == \"SharePointFileOperation\"\n        | where Operation == \"FileUploaded\"\n        | extend MemberAdded = UserId, SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl), TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)\n        | where SourceRelativeUrl has \"Microsoft Teams Chat Files\"\n        | join kind=inner (\n            EnrichedMicrosoft365AuditLogs\n            | where RecordType == \"SharePointFileOperation\"\n            | where Operation == \"FileAccessed\"\n            | extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl), TeamName = tostring(parse_json(tostring(AdditionalProperties)).TeamName)\n            | where SourceRelativeUrl has \"Microsoft Teams Chat Files\"\n            | summarize FileAccessCount = count() by ObjectId, TeamName\n            | where FileAccessCount > fileAccessThreshold\n        ) on ObjectId, TeamName\n    ) on MemberAdded, TeamName\n    | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;\n// Combine Office and Enriched Events and Deduplicate\nlet CombinedEvents = OfficeEvents\n    | union EnrichedEvents\n    | summarize arg_min(TimeAdded, *) by MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName;\n// Project Final Output\nCombinedEvents\n    | extend MemberAddedAccountName = tostring(split(MemberAdded, \"@\")[0]), MemberAddedAccountUPNSuffix = tostring(split(MemberAdded, \"@\")[1])\n    | extend UserWhoAddedAccountName = tostring(split(UserWhoAdded, \"@\")[0]), UserWhoAddedAccountUPNSuffix = tostring(split(UserWhoAdded, \"@\")[1])\n    | extend UserWhoDeletedAccountName = tostring(split(UserWhoDeleted, \"@\")[0]), UserWhoDeletedAccountUPNSuffix = tostring(split(UserWhoDeleted, \"@\")[1])\n    | project TimeAdded, TimeDeleted, MemberAdded, UserWhoAdded, UserWhoDeleted, TeamName, MemberAddedAccountName, MemberAddedAccountUPNSuffix, UserWhoAddedAccountName, UserWhoAddedAccountUPNSuffix, UserWhoDeletedAccountName, UserWhoDeletedAccountUPNSuffix\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "PT1H",
        "severity": "Low",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "InitialAccess"
        ],
        "techniques": [
          "T1566"
        ],
        "templateVersion": "2.1.3",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}