Detection rules › Kusto

GreyNoise TI map IP entity to Network Session Events (ASIM Network Session schema)

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

'This rule identifies a match Network Sessions for which the source or destination IP address is a known GreyNoise IoC. This analytic rule uses ASIM and supports any built-in or custom source that supports the ASIM NetworkSession schema'

MITRE ATT&CK coverage

TacticTechniques
Command & ControlT1071 Application Layer Protocol

Rule body kusto

id: 536e8e5c-ce0e-575e-bcc9-aba8e7bf9316
name: GreyNoise TI map IP entity to Network Session Events (ASIM Network Session schema)
version: 1.0.3
kind: Scheduled
description: |
  'This rule identifies a match Network Sessions for which the source or destination IP address is a known GreyNoise IoC.
  This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: AWSS3
    dataTypes:
      - AWSVPCFlow
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceNetworkEvents
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsForwardedEvents
    dataTypes:
      - WindowsEvent
  - connectorId: Zscaler
    dataTypes:
      - CommonSecurityLog
  - connectorId: MicrosoftSysmonForLinux
    dataTypes:
      - Syslog
  - connectorId: PaloAltoNetworks
    dataTypes:
      - CommonSecurityLog
  - connectorId: AzureMonitor(VMInsights)
    dataTypes:
      - VMConnection
  - connectorId: AzureFirewall
    dataTypes:
      - AzureDiagnostics
  - connectorId: AzureNSG
    dataTypes:
      - AzureDiagnostics
  - connectorId: CiscoASA
    dataTypes:
      - CommonSecurityLog
  - connectorId: CiscoAsaAma
    dataTypes:
      - CommonSecurityLog
  - connectorId: Corelight
    dataTypes:
      - Corelight_CL
  - connectorId: AIVectraStream
    dataTypes:
      - VectraStream
  - connectorId: CheckPoint
    dataTypes:
      - CommonSecurityLog
  - connectorId: Fortinet
    dataTypes:
      - CommonSecurityLog
  - connectorId: MicrosoftDefenderThreatIntelligence
    dataTypes:
      - ThreatIntelligenceIndicator
  - connectorId: CiscoMeraki
    dataTypes:
      - Syslog
      - CiscoMerakiNativePoller
  - connectorId: GreyNoise2SentinelAPI
    dataTypes:
      - ThreatIntelligenceIndicator

queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CommandAndControl
relevantTechniques:
  - T1071
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  let IP_TI = materialize (
  ThreatIntelligenceIndicator
  | where TimeGenerated >= ago(ioc_lookBack)
  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
  | where Active == true and ExpirationDateTime > now()
  | where SourceSystem == 'GreyNoise'
    | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,"NO_IP")
    | where TI_ipEntity != "NO_IP"
  );
  IP_TI
    // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
  | join kind=innerunique 
  (
    _Im_NetworkSession (starttime=ago(dt_lookBack))
    | where isnotempty(SrcIpAddr)
    | summarize imNWS_mintime=min(TimeGenerated), imNWS_maxtime=max(TimeGenerated) by SrcIpAddr, DstIpAddr, Dvc, EventProduct, EventVendor  
    | lookup (IP_TI | project TI_ipEntity, Active) on $left.SrcIpAddr == $right.TI_ipEntity
    | project-rename SrcMatch = Active
    | lookup (IP_TI | project TI_ipEntity, Active) on $left.DstIpAddr == $right.TI_ipEntity
    | project-rename DstMatch = Active
    | where SrcMatch or DstMatch
    | extend 
        IoCIP = iff(SrcMatch, SrcIpAddr, DstIpAddr),
        IoCDirection = iff(SrcMatch, "Source", "Destination")
  )on $left.TI_ipEntity == $right.IoCIP
  | where imNWS_mintime < ExpirationDateTime
  | project imNWS_mintime, imNWS_maxtime, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SrcIpAddr, DstIpAddr, IoCDirection, IoCIP, Dvc, EventVendor, EventProduct
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IoCIP

customDetails:
  EventStartTime: imNWS_mintime
  EventEndTime: imNWS_maxtime
  IoCDescription: Description
  ActivityGroupNames: ActivityGroupNames
  IndicatorId: IndicatorId
  ThreatType: ThreatType
  IoCExpirationTime: ExpirationDateTime
  IoCConfidenceScore: ConfidenceScore
  IoCIPDirection: IoCDirection

alertDetailsOverride:
  alertDisplayNameFormat: A network session {{IoCDirection}} address {{IoCIP}} matched an IoC. 
  alertDescriptionFormat: The {{IoCDirection}} address {{IoCIP}} of a network session  matched a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence blead for more information on the indicator.

tags:
  - Schema: ASIMNetworkSession
    SchemaVersion: 0.2.4

Stages and Predicates

Parameters

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

The stages below define let IP_TI (the rule's main pipeline source).

Stage 1: source

ThreatIntelligenceIndicator

Stage 2: where

| where TimeGenerated >= ago(ioc_lookBack)

Stage 3: summarize

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

Stage 4: where

| where Active == true and ExpirationDateTime > now()

Stage 5: where

| where SourceSystem == 'GreyNoise'

Stage 6: extend

| extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,"NO_IP")

Stage 7: where

| where TI_ipEntity != "NO_IP"

The stages below run on IP_TI (the outer pipeline).

Stage 8: join

IP_TI
| join kind=innerunique 
(
  _Im_NetworkSession (starttime=ago(dt_lookBack))
  | where isnotempty(SrcIpAddr)
  | summarize imNWS_mintime=min(TimeGenerated), imNWS_maxtime=max(TimeGenerated) by SrcIpAddr, DstIpAddr, Dvc, EventProduct, EventVendor  
  | lookup (IP_TI | project TI_ipEntity, Active) on $left.SrcIpAddr == $right.TI_ipEntity
  | project-rename SrcMatch = Active
  | lookup (IP_TI | project TI_ipEntity, Active) on $left.DstIpAddr == $right.TI_ipEntity
  | project-rename DstMatch = Active
  | where SrcMatch or DstMatch
  | extend 
      IoCIP = iff(SrcMatch, SrcIpAddr, DstIpAddr),
      IoCDirection = iff(SrcMatch, "Source", "Destination")
)on $left.TI_ipEntity == $right.IoCIP

Stage 9: where

| where imNWS_mintime < ExpirationDateTime

Stage 10: project

| project imNWS_mintime, imNWS_maxtime, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SrcIpAddr, DstIpAddr, IoCDirection, IoCIP, Dvc, EventVendor, EventProduct

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
Activeeq
  • true transforms: cased
SourceSystemeq
  • GreyNoise transforms: cased
SrcIpAddris_not_null
  • (no value, null check)
TI_ipEntityne
  • NO_IP transforms: cased
imNWS_mintimelt
  • ExpirationDateTime transforms: cased

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
ActivityGroupNamesproject
ConfidenceScoreproject
Descriptionproject
DstIpAddrproject
Dvcproject
EventProductproject
EventVendorproject
ExpirationDateTimeproject
IndicatorIdproject
IoCDirectionproject
IoCIPproject
SrcIpAddrproject
ThreatTypeproject
imNWS_maxtimeproject
imNWS_mintimeproject