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

Exes with double file extension and access summary

Back
Idd12580c2-1474-4125-a8a3-553f50d91215
RulenameExes with double file extension and access summary
DescriptionProvides a summary of executable files with double file extensions in SharePoint

and the users and IP addresses that have accessed them.
TacticsDefenseEvasion
TechniquesT1036
Required data connectorsAzureActiveDirectory
KindScheduled
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Hunting Queries/double_file_ext_exes.yaml
Version2.0.1
Arm templated12580c2-1474-4125-a8a3-553f50d91215.json
Deploy To Azure
let known_ext = dynamic(["lnk", "log", "option", "config", "manifest", "partial"]);
let excluded_users = dynamic(["app@sharepoint"]);
EnrichedMicrosoft365AuditLogs
| where RecordType == "SharePointFileOperation" and isnotempty(ObjectId)
| where ObjectId has ".exe." 
    and not(ObjectId endswith ".lnk") 
    and not(ObjectId endswith ".log") 
    and not(ObjectId endswith ".option") 
    and not(ObjectId endswith ".config") 
    and not(ObjectId endswith ".manifest") 
    and not(ObjectId endswith ".partial")
| extend Extension = extract("[^.]*\\.[^.]*$", 0, ObjectId)
| extend SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)
| join kind=leftouter (
    EnrichedMicrosoft365AuditLogs
    | where RecordType == "SharePointFileOperation" and (Operation == "FileDownloaded" or Operation == "FileAccessed")
    | where not(ObjectId endswith ".lnk") 
        and not(ObjectId endswith ".log") 
        and not(ObjectId endswith ".option") 
        and not(ObjectId endswith ".config") 
        and not(ObjectId endswith ".manifest") 
        and not(ObjectId endswith ".partial")
) on ObjectId
| where UserId1 !in (excluded_users)
| extend userBag = bag_pack("UserId", UserId1, "ClientIp", ClientIp1)
| summarize make_set(UserId1, 10000), userBag = make_bag(userBag), UploadTime = max(TimeGenerated) by UserId, ObjectId, SourceFileName, Extension
| extend NumberOfUsers = array_length(bag_keys(userBag))
| project UploadTime, Uploader = UserId, FileLocation = ObjectId, FileName = SourceFileName, AccessedBy = userBag, Extension, NumberOfUsers
| extend UploaderName = tostring(split(Uploader, "@")[0]), UploaderUPNSuffix = tostring(split(Uploader, "@")[1])
description: |
  'Provides a summary of executable files with double file extensions in SharePoint 
   and the users and IP addresses that have accessed them.'  
entityMappings:
- fieldMappings:
  - columnName: UploaderName
    identifier: Name
  - columnName: UploaderUPNSuffix
    identifier: UPNSuffix
  entityType: Account
kind: Scheduled
requiredDataConnectors:
- connectorId: AzureActiveDirectory
  dataTypes:
  - EnrichedMicrosoft365AuditLogs
query: |
  let known_ext = dynamic(["lnk", "log", "option", "config", "manifest", "partial"]);
  let excluded_users = dynamic(["app@sharepoint"]);
  EnrichedMicrosoft365AuditLogs
  | where RecordType == "SharePointFileOperation" and isnotempty(ObjectId)
  | where ObjectId has ".exe." 
      and not(ObjectId endswith ".lnk") 
      and not(ObjectId endswith ".log") 
      and not(ObjectId endswith ".option") 
      and not(ObjectId endswith ".config") 
      and not(ObjectId endswith ".manifest") 
      and not(ObjectId endswith ".partial")
  | extend Extension = extract("[^.]*\\.[^.]*$", 0, ObjectId)
  | extend SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)
  | join kind=leftouter (
      EnrichedMicrosoft365AuditLogs
      | where RecordType == "SharePointFileOperation" and (Operation == "FileDownloaded" or Operation == "FileAccessed")
      | where not(ObjectId endswith ".lnk") 
          and not(ObjectId endswith ".log") 
          and not(ObjectId endswith ".option") 
          and not(ObjectId endswith ".config") 
          and not(ObjectId endswith ".manifest") 
          and not(ObjectId endswith ".partial")
  ) on ObjectId
  | where UserId1 !in (excluded_users)
  | extend userBag = bag_pack("UserId", UserId1, "ClientIp", ClientIp1)
  | summarize make_set(UserId1, 10000), userBag = make_bag(userBag), UploadTime = max(TimeGenerated) by UserId, ObjectId, SourceFileName, Extension
  | extend NumberOfUsers = array_length(bag_keys(userBag))
  | project UploadTime, Uploader = UserId, FileLocation = ObjectId, FileName = SourceFileName, AccessedBy = userBag, Extension, NumberOfUsers
  | extend UploaderName = tostring(split(Uploader, "@")[0]), UploaderUPNSuffix = tostring(split(Uploader, "@")[1])  
version: 2.0.1
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Hunting Queries/double_file_ext_exes.yaml
relevantTechniques:
- T1036
tactics:
- DefenseEvasion
id: d12580c2-1474-4125-a8a3-553f50d91215
name: Exes with double file extension and access summary
{
  "$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/d12580c2-1474-4125-a8a3-553f50d91215')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/d12580c2-1474-4125-a8a3-553f50d91215')]",
      "properties": {
        "alertRuleTemplateName": "d12580c2-1474-4125-a8a3-553f50d91215",
        "customDetails": null,
        "description": "'Provides a summary of executable files with double file extensions in SharePoint \n and the users and IP addresses that have accessed them.'\n",
        "displayName": "Exes with double file extension and access summary",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UploaderName",
                "identifier": "Name"
              },
              {
                "columnName": "UploaderUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Hunting Queries/double_file_ext_exes.yaml",
        "query": "let known_ext = dynamic([\"lnk\", \"log\", \"option\", \"config\", \"manifest\", \"partial\"]);\nlet excluded_users = dynamic([\"app@sharepoint\"]);\nEnrichedMicrosoft365AuditLogs\n| where RecordType == \"SharePointFileOperation\" and isnotempty(ObjectId)\n| where ObjectId has \".exe.\" \n    and not(ObjectId endswith \".lnk\") \n    and not(ObjectId endswith \".log\") \n    and not(ObjectId endswith \".option\") \n    and not(ObjectId endswith \".config\") \n    and not(ObjectId endswith \".manifest\") \n    and not(ObjectId endswith \".partial\")\n| extend Extension = extract(\"[^.]*\\\\.[^.]*$\", 0, ObjectId)\n| extend SourceFileName = tostring(parse_json(tostring(AdditionalProperties)).SourceFileName)\n| join kind=leftouter (\n    EnrichedMicrosoft365AuditLogs\n    | where RecordType == \"SharePointFileOperation\" and (Operation == \"FileDownloaded\" or Operation == \"FileAccessed\")\n    | where not(ObjectId endswith \".lnk\") \n        and not(ObjectId endswith \".log\") \n        and not(ObjectId endswith \".option\") \n        and not(ObjectId endswith \".config\") \n        and not(ObjectId endswith \".manifest\") \n        and not(ObjectId endswith \".partial\")\n) on ObjectId\n| where UserId1 !in (excluded_users)\n| extend userBag = bag_pack(\"UserId\", UserId1, \"ClientIp\", ClientIp1)\n| summarize make_set(UserId1, 10000), userBag = make_bag(userBag), UploadTime = max(TimeGenerated) by UserId, ObjectId, SourceFileName, Extension\n| extend NumberOfUsers = array_length(bag_keys(userBag))\n| project UploadTime, Uploader = UserId, FileLocation = ObjectId, FileName = SourceFileName, AccessedBy = userBag, Extension, NumberOfUsers\n| extend UploaderName = tostring(split(Uploader, \"@\")[0]), UploaderUPNSuffix = tostring(split(Uploader, \"@\")[1])\n",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "DefenseEvasion"
        ],
        "techniques": [
          "T1036"
        ],
        "templateVersion": "2.0.1"
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}