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

Discord CDN Risky File Download ASIM Web Session Schema

Back
Id01e8ffff-dc0c-43fe-aa22-d459c4204553
RulenameDiscord CDN Risky File Download (ASIM Web Session Schema)
DescriptionIdentifies callouts to Discord CDN addresses for risky file extensions. This detection will trigger when a callout for a risky file is made to a discord server that has only been seen once in your environment.

Unique discord servers are identified using the server ID that is included in the request URL (DiscordServerId in query). Discord CDN has been used in multiple campaigns to download additional payloads.

This analytic rule uses ASIM and supports any built-in or custom source that supports the ASIM WebSession schema (ASIM WebSession Schema)
SeverityMedium
TacticsCommandAndControl
TechniquesT1071.001
Required data connectorsSquidProxy
Zscaler
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Detections/ASimWebSession/DiscordCDNRiskyFileDownload_ASim.yaml
Version1.1.4
Arm template01e8ffff-dc0c-43fe-aa22-d459c4204553.json
Deploy To Azure
let discord=dynamic(["cdn.discordapp.com", "media.discordapp.com"]);
  _Im_WebSession(url_has_any=discord, eventresult='Success')
  | where Url has "attachments"
  | extend DiscordServerId = extract(@"\/attachments\/([0-9]+)\/", 1, Url)
  | summarize dcount(Url), make_set(SrcUsername), make_set(SrcIpAddr), make_set(Url), min(TimeGenerated), max(TimeGenerated), make_set(EventResult) by DiscordServerId
  | mv-expand set_SrcUsername to typeof(string), set_Url to typeof(string), set_EventResult to typeof(string), set_SrcIpAddr to typeof(string)
  | summarize by DiscordServerId, dcount_Url, set_SrcUsername, min_TimeGenerated, max_TimeGenerated, set_EventResult, set_SrcIpAddr, set_Url
  | project StartTime=min_TimeGenerated, EndTime=max_TimeGenerated, Result=set_EventResult, SourceUser=set_SrcUsername, SourceIP=set_SrcIpAddr, RequestURL=set_Url
  | where RequestURL has_any (".bin",".exe",".dll",".bin",".msi")
  | extend AccountName = tostring(split(SourceUser, "@")[0]), AccountUPNSuffix = tostring(split(SourceUser, "@")[1])
relevantTechniques:
- T1071.001
name: Discord CDN Risky File Download  (ASIM Web Session Schema)
requiredDataConnectors:
- dataTypes:
  - SquidProxy_CL
  connectorId: SquidProxy
- dataTypes:
  - CommonSecurityLog
  connectorId: Zscaler
entityMappings:
- fieldMappings:
  - identifier: FullName
    columnName: SourceUser
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: AccountUPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: SourceIP
  entityType: IP
- fieldMappings:
  - identifier: Url
    columnName: RequestURL
  entityType: URL
triggerThreshold: 0
id: 01e8ffff-dc0c-43fe-aa22-d459c4204553
tactics:
- CommandAndControl
version: 1.1.4
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/ASimWebSession/DiscordCDNRiskyFileDownload_ASim.yaml
queryPeriod: 1d
kind: Scheduled
tags:
- Discord
metadata:
  categories:
    domains:
    - Security - Threat Protection
  author:
    name: Microsoft Security Research
  support:
    tier: Community
  source:
    kind: Community
queryFrequency: 1d
severity: Medium
description: |
  'Identifies callouts to Discord CDN addresses for risky file extensions. This detection will trigger when a callout for a risky file is made to a discord server that has only been seen once in your environment. 
   Unique discord servers are identified using the server ID that is included in the request URL (DiscordServerId in query). Discord CDN has been used in multiple campaigns to download additional payloads.
   This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM WebSession schema (ASIM WebSession Schema)'  
query: |
  let discord=dynamic(["cdn.discordapp.com", "media.discordapp.com"]);
    _Im_WebSession(url_has_any=discord, eventresult='Success')
    | where Url has "attachments"
    | extend DiscordServerId = extract(@"\/attachments\/([0-9]+)\/", 1, Url)
    | summarize dcount(Url), make_set(SrcUsername), make_set(SrcIpAddr), make_set(Url), min(TimeGenerated), max(TimeGenerated), make_set(EventResult) by DiscordServerId
    | mv-expand set_SrcUsername to typeof(string), set_Url to typeof(string), set_EventResult to typeof(string), set_SrcIpAddr to typeof(string)
    | summarize by DiscordServerId, dcount_Url, set_SrcUsername, min_TimeGenerated, max_TimeGenerated, set_EventResult, set_SrcIpAddr, set_Url
    | project StartTime=min_TimeGenerated, EndTime=max_TimeGenerated, Result=set_EventResult, SourceUser=set_SrcUsername, SourceIP=set_SrcIpAddr, RequestURL=set_Url
    | where RequestURL has_any (".bin",".exe",".dll",".bin",".msi")
    | extend AccountName = tostring(split(SourceUser, "@")[0]), AccountUPNSuffix = tostring(split(SourceUser, "@")[1])  
triggerOperator: gt
{
  "$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/01e8ffff-dc0c-43fe-aa22-d459c4204553')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/01e8ffff-dc0c-43fe-aa22-d459c4204553')]",
      "properties": {
        "alertRuleTemplateName": "01e8ffff-dc0c-43fe-aa22-d459c4204553",
        "customDetails": null,
        "description": "'Identifies callouts to Discord CDN addresses for risky file extensions. This detection will trigger when a callout for a risky file is made to a discord server that has only been seen once in your environment. \n Unique discord servers are identified using the server ID that is included in the request URL (DiscordServerId in query). Discord CDN has been used in multiple campaigns to download additional payloads.\n This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM WebSession schema (ASIM WebSession Schema)'\n",
        "displayName": "Discord CDN Risky File Download  (ASIM Web Session Schema)",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "SourceUser",
                "identifier": "FullName"
              },
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "AccountUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceIP",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "RequestURL",
                "identifier": "Url"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/ASimWebSession/DiscordCDNRiskyFileDownload_ASim.yaml",
        "query": "let discord=dynamic([\"cdn.discordapp.com\", \"media.discordapp.com\"]);\n  _Im_WebSession(url_has_any=discord, eventresult='Success')\n  | where Url has \"attachments\"\n  | extend DiscordServerId = extract(@\"\\/attachments\\/([0-9]+)\\/\", 1, Url)\n  | summarize dcount(Url), make_set(SrcUsername), make_set(SrcIpAddr), make_set(Url), min(TimeGenerated), max(TimeGenerated), make_set(EventResult) by DiscordServerId\n  | mv-expand set_SrcUsername to typeof(string), set_Url to typeof(string), set_EventResult to typeof(string), set_SrcIpAddr to typeof(string)\n  | summarize by DiscordServerId, dcount_Url, set_SrcUsername, min_TimeGenerated, max_TimeGenerated, set_EventResult, set_SrcIpAddr, set_Url\n  | project StartTime=min_TimeGenerated, EndTime=max_TimeGenerated, Result=set_EventResult, SourceUser=set_SrcUsername, SourceIP=set_SrcIpAddr, RequestURL=set_Url\n  | where RequestURL has_any (\".bin\",\".exe\",\".dll\",\".bin\",\".msi\")\n  | extend AccountName = tostring(split(SourceUser, \"@\")[0]), AccountUPNSuffix = tostring(split(SourceUser, \"@\")[1])\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "subTechniques": [
          "T1071.001"
        ],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "tags": [
          "Discord"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.1.4",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}