↳ Source GitHubRègle analytiqueMedium

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

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'
Type de règle
Scheduled
Version
1.0.0
Statut déclaré
Available
Fréquence
1d
Période analysée
1d
Déclenchement
gt 0

Couverture MITRE déclarée

Requête KQL

Requête originale, sans modification.

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]), "")

Entités déclarées

AccountIPURLHost

Contenus associés

Liens établis à partir des identifiants déclarés et des manifests des solutions.

Traçabilité de la source

GitHub

Les valeurs affichées proviennent des fichiers du dépôt Azure/Azure-Sentinel. Elles décrivent le modèle publié, pas la configuration de votre workspace.

Identifiant source
b7fe8f27-7010-404b-aec5-6e5245cea580
Autres fichiers source 2Solutions/Web Session Essentials/Analytic Rules/DiscordCDNRiskyFileDownload.yamlsource ↗Solutions/Web Session Essentials/Data/Solution_Web Session Essentials.jsonsolution-membership ↗
GSTEP / SUIVI DU CATALOGUE

Ajouté au catalogue : 16 sept. 2026 · 05:49 UTC
Dernier changement observé : 16 sept. 2026 · 05:49 UTC

Dates de synchronisation GSTEP, distinctes des dates de publication du contenu source.