↳ Source GitHubRègle analytiqueHigh
Power Apps - Multiple users access a malicious link after launching new app
Description
Identifies a chain of events, where a new Power App is created, followed by mulitple users launching the app within the detection window and clicking on the same malicious URL.
- Type de règle
- Scheduled
- Version
- 3.2.0
- Statut déclaré
- Available
- Fréquence
- 1h
- Période analysée
- 14d
- Déclenchement
- gt 0
Couverture MITRE déclarée
Sources déclarées
Métadonnées du fichier source. Aucune dépendance déduite du KQL.
Connecteurs
Types de données
Requête KQL
Requête originale, sans modification.
// Define a threshold (distinct_user_launch_threshold) for
// the minimum number of users who launched an app
// to be in scope of this detection
let distinct_user_launch_threshold = 2;
// Define a threshold for the minumum number of users
// who clicked the same malicious link after launching the app
// to be in scope of this detection
let distinct_user_url_click_threshold = 2;
let query_frequency = 1h;
let query_lookback = 14d;
let new_app_creation_activity = materialize(
PowerPlatformAdminActivity
| where TimeGenerated >= ago (query_lookback)
| where EventOriginalType == "CreatePowerApp"
| extend Properties = tostring(PropertyCollection)
| extend SrcIpAddr = extract(@'"enduser.ip_address","Value":"([^"]+)"', 1, Properties)
| extend SrcIpAddr = iif(SrcIpAddr startswith '::ffff:', replace_string(SrcIpAddr, '::ffff:', ''), SrcIpAddr)
| extend AppId = extract(@'"powerplatform.analytics.resource.power_app.id","Value":"([^"]+)"', 1, Properties)
| extend AppId = tolower(replace_string(AppId, '/providers/Microsoft.PowerApps/apps/', ''))
| extend
AppName = extract(@'"powerplatform.analytics.resource.power_app.display_name","Value":"([^"]+)"', 1, Properties),
EnvironmentId = extract(@'"powerplatform.analytics.resource.environment.id","Value":"([^"]+)"', 1, Properties)
| project-rename
AppCreatedTime = TimeGenerated,
AppCreator = ActorName,
AppCreatorIpAddr = SrcIpAddr
);
let distinct_apps = new_app_creation_activity
| distinct AppName;
let new_app_launch_activity = materialize(
new_app_creation_activity
| join kind=inner (
PowerPlatformAdminActivity
| where TimeGenerated >= ago (query_lookback)
| where EventOriginalType == "LaunchPowerApp"
| where PropertyCollection has_any (distinct_apps)
| extend Properties = tostring(PropertyCollection)
| extend AppName = extract(@'"powerplatform.analytics.resource.power_app.display_name","Value":"([^"]+)"', 1, Properties)
| summarize FirstAppLaunchTime = min(TimeGenerated) by ActorName, AppName)
on AppName
| where FirstAppLaunchTime > AppCreatedTime
);
let new_app_launch_users = new_app_launch_activity
| summarize LaunchCount = dcount(ActorName) by AppName
| where LaunchCount > distinct_user_launch_threshold
| join kind=inner new_app_launch_activity on AppName
| summarize
by
ActorName,
FirstAppLaunchTime,
AppName,
AppId,
EnvironmentId,
AppCreator,
AppCreatorIpAddr;
let detected_urls = union isfuzzy=true
(
SecurityAlert
| where TimeGenerated >= ago (query_lookback)
| where Entities has_cs '"Type":"url"'
| mv-expand todynamic(Entities)
| where tostring(Entities.Type) == "url"
| project Url = tostring(Entities.Url), Source = "SecurityAlert"
),
(
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(query_lookback)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where isnotempty(isnotempty(Url))
| project Url, Source = "ThreatIntelligence"
)
| summarize by Url, Source;
let url_click_events = materialize(
union isfuzzy=true
(
UrlClickEvents
| where TimeGenerated >= ago(query_frequency)
| where isnotempty(ThreatTypes)
| join kind=inner (new_app_launch_users) on $left.AccountUpn == $right.ActorName
| where TimeGenerated between (FirstAppLaunchTime .. (FirstAppLaunchTime + 1h))
| summarize by ActorName, Url, Source = "MicrosoftDefender"
),
(
_Im_WebSession
| where TimeGenerated >= ago(query_frequency)
| join kind=inner (new_app_launch_users) on $left.SrcUsername == $right.ActorName
| join kind=inner (detected_urls) on Url
| where TimeGenerated between (FirstAppLaunchTime .. (FirstAppLaunchTime + 1h))
| summarize by ActorName, Url, Source
)
);
let distinct_url_click_events_count = toscalar(
url_click_events
| summarize DistinctUserCount = dcount(ActorName) by Url
| where DistinctUserCount > distinct_user_url_click_threshold
| summarize sum(DistinctUserCount)
);
url_click_events
| summarize DistinctUserCount = dcount(ActorName) by Url
| where DistinctUserCount >= distinct_user_url_click_threshold
| join kind=inner url_click_events on Url
| join kind=inner (new_app_launch_users) on ActorName
| extend
PowerAppsEntityId = 27593,
DataverseId = 32780,
AccountName = tostring(split(ActorName, '@')[0]),
UPNSuffix = tostring(split(ActorName, '@')[1])
| project
FirstAppLaunchTime,
AppCreator,
AppName,
AppId,
ImpactedUser = ActorName,
AccountName,
UPNSuffix,
EnvironmentId,
Url,
Source,
PowerAppsEntityId
Entités déclarées
Contenus associés
Liens établis à partir des identifiants déclarés et des manifests des solutions.
Traçabilité de la source
GitHubLes 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.
- Commit
7ca9800↗- Identifiant source
4bd7e93a-0646-4e02-8dcb-aa16d16618f4
GSTEP / SUIVI DU CATALOGUE
Ajouté au catalogue : 16 sept. 2026 · 05:49 UTC
Dernier changement observé : 16 sept. 2026 · 05:49 UTC