Detection rules › Kusto

HoneyLabs TI Map IP Entity to Network Session (ASIM)

Severity
medium
Time window
14d
Group by
Id, NS_ipEntity, TI_ipEntity
Source
github.com/Azure/Azure-Sentinel

Identifies network sessions whose source IP addresses HoneyLabs honeypot telemetry has observed running exploit or loader commands. Uses the ASIM NetworkSession parser, so it works across any normalised network source (firewalls, VPN, cloud NSG flow logs) without requiring CEF. Only the structured source IP is matched; destination IPs are intentionally excluded. Indicator Confidence reflects how much evidence HoneyLabs holds (90 = 100+ observed attacks, 60 = a single sighting); raise the threshold in the query to trade coverage for precision.

MITRE ATT&CK coverage

Telemetry coverage

Rule body

id: 5d3a1c77-2b40-4e6c-9f2d-71c0a8e4b912
name: HoneyLabs TI Map IP Entity to Network Session (ASIM)
version: 1.0.0
kind: Scheduled
description: |
  'Identifies network sessions whose source IP addresses HoneyLabs honeypot telemetry has observed running exploit or loader commands. Uses the ASIM NetworkSession parser, so it works across any normalised network source (firewalls, VPN, cloud NSG flow logs) without requiring CEF. Only the structured source IP is matched; destination IPs are intentionally excluded. Indicator Confidence reflects how much evidence HoneyLabs holds (90 = 100+ observed attacks, 60 = a single sighting); raise the threshold in the query to trade coverage for precision.'
severity: Medium
requiredDataConnectors: []
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
  - CommandAndControl
relevantTechniques:
  - T1190
  - T1071
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  let HoneyLabs_IPs = ThreatIntelIndicators
    | where TimeGenerated >= ago(ioc_lookBack)
    | where IsActive == true and ValidUntil > now()
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
    | where SourceSystem startswith 'HoneyLabs'
    | where ObservableKey == 'ipv4-addr:value'
    | extend TI_ipEntity = tostring(ObservableValue),
             HoneyLabsConfidence = Confidence,
             IndicatorDescription = tostring(Data.description),
             HoneyLabsReport = strcat('https://honeylabs.net/lookup/', tostring(ObservableValue));
  HoneyLabs_IPs
  | join kind=innerunique (
      _Im_NetworkSession(starttime=ago(dt_lookBack))
      | where isnotempty(SrcIpAddr)
      | extend NS_ipEntity = SrcIpAddr
      | extend NetworkSession_TimeGenerated = TimeGenerated
  ) on $left.TI_ipEntity == $right.NS_ipEntity
  | where NetworkSession_TimeGenerated < ValidUntil
  | summarize NetworkSession_TimeGenerated = arg_max(NetworkSession_TimeGenerated, *) by Id, NS_ipEntity
  | project NetworkSession_TimeGenerated, IndicatorDescription, Id, ValidUntil, HoneyLabsConfidence,
    HoneyLabsReport, TI_ipEntity, NS_ipEntity, SrcIpAddr, DstIpAddr, DstPortNumber, Dvc, EventResult
  | extend timestamp = NetworkSession_TimeGenerated
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: NS_ipEntity

Stages and Predicates

Parameters

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

let HoneyLabs_IPs is inlined into the numbered stages below.

Stages 1 to 7 define let HoneyLabs_IPs (the rule's main pipeline source); stages 8 to 12 run on it.

Stage 1: source

ThreatIntelIndicators

Stage 2: where

| where TimeGenerated >= ago(ioc_lookBack)

Stage 3: where

| where IsActive == true and ValidUntil > now()

Stage 4: summarize

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

Stage 5: where

| where SourceSystem startswith 'HoneyLabs'

Stage 6: where

| where ObservableKey == 'ipv4-addr:value'

Stage 7: extend

| extend TI_ipEntity = tostring(ObservableValue),
           HoneyLabsConfidence = Confidence,
           IndicatorDescription = tostring(Data.description),
           HoneyLabsReport = strcat('https://honeylabs.net/lookup/', tostring(ObservableValue))

Stage 8: join

HoneyLabs_IPs
| join kind=innerunique (
    _Im_NetworkSession(starttime=ago(dt_lookBack))
    | where isnotempty(SrcIpAddr)
    | extend NS_ipEntity = SrcIpAddr
    | extend NetworkSession_TimeGenerated = TimeGenerated
) on $left.TI_ipEntity == $right.NS_ipEntity

Stage 9: where

| where NetworkSession_TimeGenerated < ValidUntil

Stage 10: summarize

| summarize NetworkSession_TimeGenerated = arg_max(NetworkSession_TimeGenerated, *) by Id, NS_ipEntity

Stage 11: project

| project NetworkSession_TimeGenerated, IndicatorDescription, Id, ValidUntil, HoneyLabsConfidence,
  HoneyLabsReport, TI_ipEntity, NS_ipEntity, SrcIpAddr, DstIpAddr, DstPortNumber, Dvc, EventResult

Stage 12: extend

| extend timestamp = NetworkSession_TimeGenerated

Indicators

These rows show field, operator, and value matches.

Output fields

These fields are emitted when the rule matches.

FieldSource
DstIpAddrproject
DstPortNumberproject
Dvcproject
EventResultproject
HoneyLabsConfidenceproject
HoneyLabsReportproject
Idproject
IndicatorDescriptionproject
NS_ipEntityproject
NetworkSession_TimeGeneratedproject
SrcIpAddrproject
TI_ipEntityproject
ValidUntilproject
timestampextend