Detection rules › Kusto

TI map IP entity to LastPass data

Status
available
Severity
medium
Time window
14d
Group by
IP_Address_s, IndicatorId, TI_ipEntity
Source
github.com/Azure/Azure-Sentinel

'Identifies a match in LastPass table from any IP IOC from TI'

MITRE ATT&CK coverage

TacticTechniques
ImpactT1485 Data Destruction

Rule body kusto

id: 2a723664-22c2-4d3e-bbec-5843b90166f3
name: TI map IP entity to LastPass data
description: |
  'Identifies a match in LastPass table from any IP IOC from TI'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: LastPass
    dataTypes:
      - LastPassNativePoller_CL
  - connectorId: ThreatIntelligence
    dataTypes:
      - ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics:
  - Impact
relevantTechniques:
 - T1485
query: |
    let dt_lookBack = 1h;
    let ioc_lookBack = 14d;
    ThreatIntelligenceIndicator
    | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
    | where Active == true
    // Picking up only IOC's that contain the entities we want
    | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
    // As there is potentially more than 1 indicator type for matching IP, taking Network IP first, then others if that is empty.
    // Taking the first non-empty value based on potential IOC match availability
    | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
    | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
    | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
    | join (
        LastPassNativePoller_CL | where todatetime(Time_s) >= ago(dt_lookBack)
        | where Action_s != "Reporting"
        // renaming time column so it is clear the log this came from
        | extend LastPass_TimeGenerated = todatetime(Time_s)
    )
    on $left.TI_ipEntity == $right.IP_Address_s
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
    | project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, LastPass_TimeGenerated, 
    TI_ipEntity, IP_Address_s, Username_s, Action_s, Data_s, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: Username_s
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IP_Address_s
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: Url
version: 1.0.1
kind: Scheduled

Stages and Predicates

Parameters

let dt_lookBack = 1h;
let ioc_lookBack = 14d;

Stage 1: source

ThreatIntelligenceIndicator

Stage 2: where

| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()

Stage 3: where

| where Active == true

Stage 4: where

| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)

Stage 5: extend (3 consecutive steps)

| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
TI_ipEntity =
ifisnotempty(NetworkIP)NetworkIP
elseNetworkDestinationIP

Stage 6: join

| join (
    LastPassNativePoller_CL | where todatetime(Time_s) >= ago(dt_lookBack)
    | where Action_s != "Reporting"
    | extend LastPass_TimeGenerated = todatetime(Time_s)
)
on $left.TI_ipEntity == $right.IP_Address_s

Stage 7: summarize

| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId

Stage 8: project

| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, LastPass_TimeGenerated, 
TI_ipEntity, IP_Address_s, Username_s, Action_s, Data_s, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
Action_sne
  • Reporting transforms: cased
Activeeq
  • true transforms: cased
EmailSourceIpAddressis_not_null
  • (no value, null check)
NetworkDestinationIPis_not_null
  • (no value, null check)
NetworkIPis_not_null
  • (no value, null check)
NetworkSourceIPis_not_null
  • (no value, null check)

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
Action_sproject
ActivityGroupNamesproject
ConfidenceScoreproject
Data_sproject
Descriptionproject
EmailSourceIpAddressproject
ExpirationDateTimeproject
IP_Address_sproject
IndicatorIdproject
LastPass_TimeGeneratedproject
LatestIndicatorTimeproject
NetworkDestinationIPproject
NetworkIPproject
NetworkSourceIPproject
TI_ipEntityproject
ThreatTypeproject
Urlproject
Username_sproject