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

Office 365 - New Executable via Office FileUploaded Operation

Back
Id178c62b4-d5e5-40f5-8eab-7fccd0051e7a
RulenameOffice 365 - New Executable via Office FileUploaded Operation
DescriptionIdentifies when executable file types are uploaded to Office services such as SharePoint and OneDrive.

List currently includes exe, inf, gzip, cmd, bat file extensions.

Additionally, identifies when a given user is uploading these files to another user’s workspace.

This may be an indication of a staging location for malware or other malicious activity.
SeverityLow
TacticsCommandAndControl
LateralMovement
TechniquesT1105
T1570
Required data connectorsAzureActiveDirectory
KindScheduled
Query frequency1d
Query period8d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - Office_Uploaded_Executables.yaml
Version2.0.6
Arm template178c62b4-d5e5-40f5-8eab-7fccd0051e7a.json
Deploy To Azure
let threshold = 2;
let uploadOp = 'FileUploaded';
let execExt = dynamic(['exe', 'inf', 'gzip', 'cmd', 'bat']);
let starttime = 8d;
let endtime = 1d;
EnrichedMicrosoft365AuditLogs
| where TimeGenerated >= ago(endtime)
| where Operation == uploadOp
| extend SourceFileExtension = extract(@"\.([^\./]+)$", 1, tostring(parse_json(tostring(AdditionalProperties)).SourceFileName))  // Extract file extension
| where SourceFileExtension in (execExt)
| extend Site_Url = tostring(parse_json(tostring(AdditionalProperties)).SiteUrl)
| extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl)
| extend SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)
| project TimeGenerated, Id, Workload, RecordType, Operation, UserType, UserKey, UserId, ClientIp, UserAgent = tostring(parse_json(tostring(AdditionalProperties)).UserAgent), Site_Url, SourceRelativeUrl, SourceFileName
| join kind=leftanti (
    EnrichedMicrosoft365AuditLogs
    | where TimeGenerated between (ago(starttime) .. ago(endtime))
    | where Operation == uploadOp
    | extend SourceFileExtension = extract(@"\.([^\./]+)$", 1, tostring(parse_json(tostring(AdditionalProperties)).SourceFileName))  // Extract file extension
    | where SourceFileExtension in (execExt)
    | extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl)
    | summarize SourceRelativeUrl = make_set(SourceRelativeUrl, 100000), UserId = make_set(UserId, 100000), PrevSeenCount = count() by SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)
    // Uncomment the line below to enforce the threshold
    // | where PrevSeenCount > threshold
    | mvexpand SourceRelativeUrl, UserId
    | extend SourceRelativeUrl = tostring(SourceRelativeUrl), UserId = tostring(UserId)
) on SourceFileName, SourceRelativeUrl, UserId
| extend SiteUrlUserFolder = tolower(split(Site_Url, '/')[-2])
| extend UserIdUserFolderFormat = tolower(replace_regex(UserId, '@|\\.', '_'))
| extend UserIdDiffThanUserFolder = iff(Site_Url has '/personal/' and SiteUrlUserFolder != UserIdUserFolderFormat, true, false)
| summarize TimeGenerated = make_list(TimeGenerated, 100000), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), UserAgents = make_list(UserAgent, 100000), Ids = make_list(Id, 100000), SourceRelativeUrls = make_list(SourceRelativeUrl, 100000), FileNames = make_list(SourceFileName, 100000)
by Workload, RecordType, Operation, UserType, UserKey, UserId, ClientIp, Site_Url, SiteUrlUserFolder, UserIdUserFolderFormat, UserIdDiffThanUserFolder
| extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])
queryPeriod: 8d
version: 2.0.6
tactics:
- CommandAndControl
- LateralMovement
queryFrequency: 1d
id: 178c62b4-d5e5-40f5-8eab-7fccd0051e7a
triggerOperator: gt
requiredDataConnectors:
- dataTypes:
  - EnrichedMicrosoft365AuditLogs
  connectorId: AzureActiveDirectory
severity: Low
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: UserId
    identifier: FullName
  - columnName: AccountName
    identifier: Name
  - columnName: AccountUPNSuffix
    identifier: UPNSuffix
- entityType: IP
  fieldMappings:
  - columnName: ClientIp
    identifier: Address
- entityType: URL
  fieldMappings:
  - columnName: Site_Url
    identifier: Url
- entityType: File
  fieldMappings:
  - columnName: FileNames
    identifier: Name
triggerThreshold: 0
relevantTechniques:
- T1105
- T1570
query: |
  let threshold = 2;
  let uploadOp = 'FileUploaded';
  let execExt = dynamic(['exe', 'inf', 'gzip', 'cmd', 'bat']);
  let starttime = 8d;
  let endtime = 1d;
  EnrichedMicrosoft365AuditLogs
  | where TimeGenerated >= ago(endtime)
  | where Operation == uploadOp
  | extend SourceFileExtension = extract(@"\.([^\./]+)$", 1, tostring(parse_json(tostring(AdditionalProperties)).SourceFileName))  // Extract file extension
  | where SourceFileExtension in (execExt)
  | extend Site_Url = tostring(parse_json(tostring(AdditionalProperties)).SiteUrl)
  | extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl)
  | extend SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)
  | project TimeGenerated, Id, Workload, RecordType, Operation, UserType, UserKey, UserId, ClientIp, UserAgent = tostring(parse_json(tostring(AdditionalProperties)).UserAgent), Site_Url, SourceRelativeUrl, SourceFileName
  | join kind=leftanti (
      EnrichedMicrosoft365AuditLogs
      | where TimeGenerated between (ago(starttime) .. ago(endtime))
      | where Operation == uploadOp
      | extend SourceFileExtension = extract(@"\.([^\./]+)$", 1, tostring(parse_json(tostring(AdditionalProperties)).SourceFileName))  // Extract file extension
      | where SourceFileExtension in (execExt)
      | extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl)
      | summarize SourceRelativeUrl = make_set(SourceRelativeUrl, 100000), UserId = make_set(UserId, 100000), PrevSeenCount = count() by SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)
      // Uncomment the line below to enforce the threshold
      // | where PrevSeenCount > threshold
      | mvexpand SourceRelativeUrl, UserId
      | extend SourceRelativeUrl = tostring(SourceRelativeUrl), UserId = tostring(UserId)
  ) on SourceFileName, SourceRelativeUrl, UserId
  | extend SiteUrlUserFolder = tolower(split(Site_Url, '/')[-2])
  | extend UserIdUserFolderFormat = tolower(replace_regex(UserId, '@|\\.', '_'))
  | extend UserIdDiffThanUserFolder = iff(Site_Url has '/personal/' and SiteUrlUserFolder != UserIdUserFolderFormat, true, false)
  | summarize TimeGenerated = make_list(TimeGenerated, 100000), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), UserAgents = make_list(UserAgent, 100000), Ids = make_list(Id, 100000), SourceRelativeUrls = make_list(SourceRelativeUrl, 100000), FileNames = make_list(SourceFileName, 100000)
  by Workload, RecordType, Operation, UserType, UserKey, UserId, ClientIp, Site_Url, SiteUrlUserFolder, UserIdUserFolderFormat, UserIdDiffThanUserFolder
  | extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])  
kind: Scheduled
name: Office 365 - New Executable via Office FileUploaded Operation
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - Office_Uploaded_Executables.yaml
description: |
  Identifies when executable file types are uploaded to Office services such as SharePoint and OneDrive.
  List currently includes exe, inf, gzip, cmd, bat file extensions.
  Additionally, identifies when a given user is uploading these files to another user's workspace.
  This may be an indication of a staging location for malware or other malicious activity.  
status: Available
{
  "$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/178c62b4-d5e5-40f5-8eab-7fccd0051e7a')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/178c62b4-d5e5-40f5-8eab-7fccd0051e7a')]",
      "properties": {
        "alertRuleTemplateName": "178c62b4-d5e5-40f5-8eab-7fccd0051e7a",
        "customDetails": null,
        "description": "Identifies when executable file types are uploaded to Office services such as SharePoint and OneDrive.\nList currently includes exe, inf, gzip, cmd, bat file extensions.\nAdditionally, identifies when a given user is uploading these files to another user's workspace.\nThis may be an indication of a staging location for malware or other malicious activity.\n",
        "displayName": "Office 365 - New Executable via Office FileUploaded Operation",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserId",
                "identifier": "FullName"
              },
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "AccountUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "ClientIp",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "Site_Url",
                "identifier": "Url"
              }
            ]
          },
          {
            "entityType": "File",
            "fieldMappings": [
              {
                "columnName": "FileNames",
                "identifier": "Name"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - Office_Uploaded_Executables.yaml",
        "query": "let threshold = 2;\nlet uploadOp = 'FileUploaded';\nlet execExt = dynamic(['exe', 'inf', 'gzip', 'cmd', 'bat']);\nlet starttime = 8d;\nlet endtime = 1d;\nEnrichedMicrosoft365AuditLogs\n| where TimeGenerated >= ago(endtime)\n| where Operation == uploadOp\n| extend SourceFileExtension = extract(@\"\\.([^\\./]+)$\", 1, tostring(parse_json(tostring(AdditionalProperties)).SourceFileName))  // Extract file extension\n| where SourceFileExtension in (execExt)\n| extend Site_Url = tostring(parse_json(tostring(AdditionalProperties)).SiteUrl)\n| extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl)\n| extend SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)\n| project TimeGenerated, Id, Workload, RecordType, Operation, UserType, UserKey, UserId, ClientIp, UserAgent = tostring(parse_json(tostring(AdditionalProperties)).UserAgent), Site_Url, SourceRelativeUrl, SourceFileName\n| join kind=leftanti (\n    EnrichedMicrosoft365AuditLogs\n    | where TimeGenerated between (ago(starttime) .. ago(endtime))\n    | where Operation == uploadOp\n    | extend SourceFileExtension = extract(@\"\\.([^\\./]+)$\", 1, tostring(parse_json(tostring(AdditionalProperties)).SourceFileName))  // Extract file extension\n    | where SourceFileExtension in (execExt)\n    | extend SourceRelativeUrl = tostring(parse_json(tostring(AdditionalProperties)).SourceRelativeUrl)\n    | summarize SourceRelativeUrl = make_set(SourceRelativeUrl, 100000), UserId = make_set(UserId, 100000), PrevSeenCount = count() by SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)\n    // Uncomment the line below to enforce the threshold\n    // | where PrevSeenCount > threshold\n    | mvexpand SourceRelativeUrl, UserId\n    | extend SourceRelativeUrl = tostring(SourceRelativeUrl), UserId = tostring(UserId)\n) on SourceFileName, SourceRelativeUrl, UserId\n| extend SiteUrlUserFolder = tolower(split(Site_Url, '/')[-2])\n| extend UserIdUserFolderFormat = tolower(replace_regex(UserId, '@|\\\\.', '_'))\n| extend UserIdDiffThanUserFolder = iff(Site_Url has '/personal/' and SiteUrlUserFolder != UserIdUserFolderFormat, true, false)\n| summarize TimeGenerated = make_list(TimeGenerated, 100000), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), UserAgents = make_list(UserAgent, 100000), Ids = make_list(Id, 100000), SourceRelativeUrls = make_list(SourceRelativeUrl, 100000), FileNames = make_list(SourceFileName, 100000)\nby Workload, RecordType, Operation, UserType, UserKey, UserId, ClientIp, Site_Url, SiteUrlUserFolder, UserIdUserFolderFormat, UserIdDiffThanUserFolder\n| extend AccountName = tostring(split(UserId, \"@\")[0]), AccountUPNSuffix = tostring(split(UserId, \"@\")[1])\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P8D",
        "severity": "Low",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl",
          "LateralMovement"
        ],
        "techniques": [
          "T1105",
          "T1570"
        ],
        "templateVersion": "2.0.6",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}