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

The download of potentially risky files from the Discord Content Delivery Network CDN ASIM Web Session

Back
Idb7fe8f27-7010-404b-aec5-6e5245cea580
RulenameThe download of potentially risky files from the Discord Content Delivery Network (CDN) (ASIM Web Session)
DescriptionThis detection mechanism identifies instances where requests are made to Discord CDN addresses for file extensions that are considered risky.

It triggers when a callout is made to a Discord server that has only been encountered once in your environment. The uniqueness of Discord servers is determined based on the server ID present in the request URL (DiscordServerId in the query).

Discord CDN has been utilized in numerous campaigns to download additional payloads, highlighting the importance of monitoring such activities.

The query includes a sample set of popular web script extensions (scriptExtensions), which should be customized to align with the specific requirements of your environment
SeverityMedium
TacticsCommandAndControl
TechniquesT1071.001
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/DiscordCDNRiskyFileDownload.yaml
Version1.0.0
Arm templateb7fe8f27-7010-404b-aec5-6e5245cea580.json
Deploy To Azure
let lookback = 1d;
let connectionThreshold = 1;
let RiskyFileExtensions = materialize(externaldata(Extensions: string)
    [@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/RiskyFileExtensionsInUrl.csv"]
    with(format="csv", ignoreFirstRecord=True));
let CustomRiskyFileExtensions = (_ASIM_GetWatchlistRaw("Web_RiskyFileExtensions") // Create new Watchlist and add your custom indicators(Optional)
    | extend
        Extensions = tostring(WatchlistItem["Extensions"])
    | project Extensions
    | where isnotempty(Extensions));
let CombinedRiskyFileExtensions = union RiskyFileExtensions, CustomRiskyFileExtensions;
let knownRiskyFileExtensions=toscalar(CombinedRiskyFileExtensions
    | where isnotempty(Extensions)
    | summarize make_set(Extensions, 1000));
let discord=dynamic(["cdn.discordapp.com", "media.discordapp.com"]);
let WebData = _Im_WebSession(starttime=ago(lookback), url_has_any=discord, eventresult='Success')
    | where isnotempty(Url)
    | project Url, SrcUsername, SrcIpAddr, TimeGenerated, SrcHostname
    | where Url has "attachments"
    | extend DiscordServerId = extract(@"\/attachments\/([0-9]+)\/", 1, Url);
WebData
| summarize
    dcount(Url),
    min(TimeGenerated),
    max(TimeGenerated)
    by DiscordServerId
| join kind=inner (WebData) on DiscordServerId
| where dcount_Url <= connectionThreshold and Url has_any (knownRiskyFileExtensions)
| summarize EventCount = count()
    by
    EventStartTime=min_TimeGenerated,
    EventEndTime=max_TimeGenerated,
    SrcUsername,
    SrcHostname,
    SrcIpAddr,
    Url
| extend
    Name = iif(SrcUsername contains "@", tostring(split(SrcUsername, '@', 0)[0]), SrcUsername),
    UPNSuffix = iif(SrcUsername contains "@", tostring(split(SrcUsername, '@', 1)[0]), "")
id: b7fe8f27-7010-404b-aec5-6e5245cea580
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
severity: Medium
customDetails:
  EventStartTime: EventStartTime
  EventEndTime: EventEndTime
alertDetailsOverride:
  alertDescriptionFormat: " Client requested for URL '{{Url}}' that contains a files hosted on a recognized Discord Content Delivery Network (CDN) which are considered to be potentially risky. It is essential to investigate further to determine the nature of the files being requested and the intent of the users involved"
  alertDisplayNameFormat: User '{{SrcUsername}}' with the IP address '{{SrcIpAddr}}' has been detected downloading potentially risky files from the Discord CDN
relevantTechniques:
- T1071.001
requiredDataConnectors: []
tags:
- SchemaVersion: 0.2.6
  Schema: WebSession
entityMappings:
- fieldMappings:
  - identifier: Name
    columnName: Name
  - identifier: UPNSuffix
    columnName: UPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: SrcIpAddr
  entityType: IP
- fieldMappings:
  - identifier: Url
    columnName: Url
  entityType: URL
- fieldMappings:
  - identifier: HostName
    columnName: SrcHostname
  entityType: Host
version: 1.0.0
query: |
  let lookback = 1d;
  let connectionThreshold = 1;
  let RiskyFileExtensions = materialize(externaldata(Extensions: string)
      [@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/RiskyFileExtensionsInUrl.csv"]
      with(format="csv", ignoreFirstRecord=True));
  let CustomRiskyFileExtensions = (_ASIM_GetWatchlistRaw("Web_RiskyFileExtensions") // Create new Watchlist and add your custom indicators(Optional)
      | extend
          Extensions = tostring(WatchlistItem["Extensions"])
      | project Extensions
      | where isnotempty(Extensions));
  let CombinedRiskyFileExtensions = union RiskyFileExtensions, CustomRiskyFileExtensions;
  let knownRiskyFileExtensions=toscalar(CombinedRiskyFileExtensions
      | where isnotempty(Extensions)
      | summarize make_set(Extensions, 1000));
  let discord=dynamic(["cdn.discordapp.com", "media.discordapp.com"]);
  let WebData = _Im_WebSession(starttime=ago(lookback), url_has_any=discord, eventresult='Success')
      | where isnotempty(Url)
      | project Url, SrcUsername, SrcIpAddr, TimeGenerated, SrcHostname
      | where Url has "attachments"
      | extend DiscordServerId = extract(@"\/attachments\/([0-9]+)\/", 1, Url);
  WebData
  | summarize
      dcount(Url),
      min(TimeGenerated),
      max(TimeGenerated)
      by DiscordServerId
  | join kind=inner (WebData) on DiscordServerId
  | where dcount_Url <= connectionThreshold and Url has_any (knownRiskyFileExtensions)
  | summarize EventCount = count()
      by
      EventStartTime=min_TimeGenerated,
      EventEndTime=max_TimeGenerated,
      SrcUsername,
      SrcHostname,
      SrcIpAddr,
      Url
  | extend
      Name = iif(SrcUsername contains "@", tostring(split(SrcUsername, '@', 0)[0]), SrcUsername),
      UPNSuffix = iif(SrcUsername contains "@", tostring(split(SrcUsername, '@', 1)[0]), "")  
queryPeriod: 1d
triggerOperator: gt
tactics:
- CommandAndControl
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/DiscordCDNRiskyFileDownload.yaml
status: Available
description: |
  'This detection mechanism identifies instances where requests are made to Discord CDN addresses for file extensions that are considered risky.
    It triggers when a callout is made to a Discord server that has only been encountered once in your environment. The uniqueness of Discord servers is determined based on the server ID present in the request URL (DiscordServerId in the query).
    Discord CDN has been utilized in numerous campaigns to download additional payloads, highlighting the importance of monitoring such activities.
    The query includes a sample set of popular web script extensions (scriptExtensions), which should be customized to align with the specific requirements of your environment'  
name: The download of potentially risky files from the Discord Content Delivery Network (CDN) (ASIM Web Session)
kind: Scheduled
queryFrequency: 1d
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2023-02-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/b7fe8f27-7010-404b-aec5-6e5245cea580')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/b7fe8f27-7010-404b-aec5-6e5245cea580')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": " Client requested for URL '{{Url}}' that contains a files hosted on a recognized Discord Content Delivery Network (CDN) which are considered to be potentially risky. It is essential to investigate further to determine the nature of the files being requested and the intent of the users involved",
          "alertDisplayNameFormat": "User '{{SrcUsername}}' with the IP address '{{SrcIpAddr}}' has been detected downloading potentially risky files from the Discord CDN"
        },
        "alertRuleTemplateName": "b7fe8f27-7010-404b-aec5-6e5245cea580",
        "customDetails": {
          "EventEndTime": "EventEndTime",
          "EventStartTime": "EventStartTime"
        },
        "description": "'This detection mechanism identifies instances where requests are made to Discord CDN addresses for file extensions that are considered risky.\n  It triggers when a callout is made to a Discord server that has only been encountered once in your environment. The uniqueness of Discord servers is determined based on the server ID present in the request URL (DiscordServerId in the query).\n  Discord CDN has been utilized in numerous campaigns to download additional payloads, highlighting the importance of monitoring such activities.\n  The query includes a sample set of popular web script extensions (scriptExtensions), which should be customized to align with the specific requirements of your environment'\n",
        "displayName": "The download of potentially risky files from the Discord Content Delivery Network (CDN) (ASIM Web Session)",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SrcIpAddr",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "Url",
                "identifier": "Url"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "SrcHostname",
                "identifier": "HostName"
              }
            ]
          }
        ],
        "eventGroupingSettings": {
          "aggregationKind": "AlertPerResult"
        },
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/DiscordCDNRiskyFileDownload.yaml",
        "query": "let lookback = 1d;\nlet connectionThreshold = 1;\nlet RiskyFileExtensions = materialize(externaldata(Extensions: string)\n    [@\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/RiskyFileExtensionsInUrl.csv\"]\n    with(format=\"csv\", ignoreFirstRecord=True));\nlet CustomRiskyFileExtensions = (_ASIM_GetWatchlistRaw(\"Web_RiskyFileExtensions\") // Create new Watchlist and add your custom indicators(Optional)\n    | extend\n        Extensions = tostring(WatchlistItem[\"Extensions\"])\n    | project Extensions\n    | where isnotempty(Extensions));\nlet CombinedRiskyFileExtensions = union RiskyFileExtensions, CustomRiskyFileExtensions;\nlet knownRiskyFileExtensions=toscalar(CombinedRiskyFileExtensions\n    | where isnotempty(Extensions)\n    | summarize make_set(Extensions, 1000));\nlet discord=dynamic([\"cdn.discordapp.com\", \"media.discordapp.com\"]);\nlet WebData = _Im_WebSession(starttime=ago(lookback), url_has_any=discord, eventresult='Success')\n    | where isnotempty(Url)\n    | project Url, SrcUsername, SrcIpAddr, TimeGenerated, SrcHostname\n    | where Url has \"attachments\"\n    | extend DiscordServerId = extract(@\"\\/attachments\\/([0-9]+)\\/\", 1, Url);\nWebData\n| summarize\n    dcount(Url),\n    min(TimeGenerated),\n    max(TimeGenerated)\n    by DiscordServerId\n| join kind=inner (WebData) on DiscordServerId\n| where dcount_Url <= connectionThreshold and Url has_any (knownRiskyFileExtensions)\n| summarize EventCount = count()\n    by\n    EventStartTime=min_TimeGenerated,\n    EventEndTime=max_TimeGenerated,\n    SrcUsername,\n    SrcHostname,\n    SrcIpAddr,\n    Url\n| extend\n    Name = iif(SrcUsername contains \"@\", tostring(split(SrcUsername, '@', 0)[0]), SrcUsername),\n    UPNSuffix = iif(SrcUsername contains \"@\", tostring(split(SrcUsername, '@', 1)[0]), \"\")\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "status": "Available",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "tags": [
          {
            "Schema": "WebSession",
            "SchemaVersion": "0.2.6"
          }
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.0.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}