Detection rules › Kusto

Users searching for VIP user activity

Severity
low
Time window
1d
Author
Microsoft Security Research
Source
github.com/Azure/Azure-Sentinel

This query monitors for users running Log Analytics queries that contain filters for specific, defined VIP user accounts or the VIPUser watchlist template. Use this detection to alert for users specifically searching for activity of sensitive users.

MITRE ATT&CK coverage

Rule body

id: f7f4a77e-f68f-4b56-9aaf-a0c9d87d7a8e
name: Users searching for VIP user activity
description: |
    This query monitors for users running Log Analytics queries that contain filters for specific, defined VIP user accounts or the VIPUser watchlist template.
    Use this detection to alert for users specifically searching for activity of sensitive users.
severity: Low
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Collection
  - Exfiltration
relevantTechniques:
  - T1530
  - T1213
  - T1020
query: |
  // Replace these with the username or emails of your VIP users you wish to monitor for.
  let vips = dynamic(['vip1@email.com','vip2@email.com']);
  // Add users who are allowed to conduct these searches - this could be specific SOC team members
  let allowed_users = dynamic([]);
  LAQueryLogs
  | where QueryText has_any (vips) or QueryText has_any ('_GetWatchlist("VIPUsers")', "_GetWatchlist('VIPUsers')")
  | where AADEmail !in (allowed_users)
  | project TimeGenerated, AADEmail, RequestClientApp, QueryText, ResponseRowCount, RequestTarget
  | extend timestamp = TimeGenerated, AccountName = tostring(split(AADEmail, "@")[0]), AccountUPNSuffix = tostring(split(AADEmail, "@")[1])
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountUPNSuffix
  - entityType: AzureResource
    fieldMappings:
      - identifier: ResourceId
        columnName: RequestTarget
version: 1.1.4
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Microsoft Security Research
    support:
        tier: Community
    categories:
        domains: [ "Security - Others" ]

Stages and Predicates

Parameters

let vips = dynamic(['vip1@email.com','vip2@email.com']);
let allowed_users = dynamic([]);

Stage 1: source

LAQueryLogs

Stage 2: where

| where QueryText has_any (vips) or QueryText has_any ('_GetWatchlist("VIPUsers")', "_GetWatchlist('VIPUsers')")

Stage 3: where

| where AADEmail !in (allowed_users)

Stage 4: project

| project TimeGenerated, AADEmail, RequestClientApp, QueryText, ResponseRowCount, RequestTarget

Stage 5: extend

| extend timestamp = TimeGenerated, AccountName = tostring(split(AADEmail, "@")[0]), AccountUPNSuffix = tostring(split(AADEmail, "@")[1])

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
AADEmaileq[]excludes:AADEmail field:"AADEmail" value:"[]"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
QueryTextmatch
  • _GetWatchlist("VIPUsers") transforms: term
  • _GetWatchlist('VIPUsers') transforms: term
  • vip1@email.com transforms: term
  • vip2@email.com transforms: term
field:"QueryText" kind:match

Output fields

These fields are emitted when the rule matches.

FieldSource
AADEmailproject
QueryTextproject
RequestClientAppproject
RequestTargetproject
ResponseRowCountproject
TimeGeneratedproject
AccountNameextend
AccountUPNSuffixextend
timestampextend