Detection rules › Kusto

Possible Phishing with CSL and Network Sessions

Status
available
Severity
medium
Time window
1d
Group by
AccountObjectId, DestinationIP, DeviceAction, DeviceName, DeviceProduct, DstIpAddr, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessAccountUpn, InitiatingProcessFileName, RecipientEmailAddress, RecipientObjectId, RemoteUrl, RequestClientApplication, RequestURL, SourceIP, TimeGenerated, UrlClickedByUserSid
Source
github.com/Azure/Azure-Sentinel

'This query looks for malicious URL clicks in phishing email recognized by MDO in correlation with CommonSecurityLogs(CSL) & NetworkSession events. If your workspace doesnt have one of the many data sources required for ASIM it may give informational error which can be safely ignored.'

MITRE ATT&CK coverage

TacticTechniques
Initial AccessT1566 Phishing
Command & ControlT1102 Web Service

Rule body kusto

id: 6c3a1258-bcdd-4fcd-b753-1a9bc826ce12
name: Possible Phishing with CSL and Network Sessions
description: |
    'This query looks for malicious URL clicks in phishing email recognized by MDO in correlation with CommonSecurityLogs(CSL) & NetworkSession events. 
    If your workspace doesnt have one of the many data sources required for ASIM it may give informational error which can be safely ignored.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
  dataTypes:
  - AlertEvidence
  - EmailEvents
  - IdentityInfo
  - DeviceEvents
  - DeviceNetworkEvents
- connectorId: Zscaler
  dataTypes:
  - CommonSecurityLog
- connectorId: Fortinet
  dataTypes:
  - CommonSecurityLog
- connectorId: CheckPoint
  dataTypes:
  - CommonSecurityLog
- connectorId: PaloAltoNetworks
  dataTypes:
  - CommonSecurityLog
- connectorId: AWSS3
  datatypes:
  - AWSVPCFlow
- connectorId: WindowsForwardedEvents
  dataTypes:
  - WindowsEvent
- connectorId: SecurityEvents
  dataTypes:
  - SecurityEvent
- connectorId: WindowsSecurityEvents
  dataTypes:
  - SecurityEvent
- connectorId: MicrosoftSysmonForLinux
  dataTypes:
  - Syslog
- connectorId: AzureNSG
  dataTypes:
  - AzureDiagnostics
- connectorId: AzureMonitor(VMInsights)
  dataTypes:
  - VMConnection
- connectorId: AIVectraStream
  dataTypes:
  - VectraStream_CL
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- CommandAndControl
relevantTechniques:
  - T1566
  - T1102
tags:
  - Schema: ASimNetworkSessions
    SchemaVersion: 0.2.5
query: |
    //SuspiciousUrlClicked
    AlertEvidence
    | where ServiceSource =~ "Microsoft Defender for Office 365"
    | where EntityType =~ "Url"
    | project AlertId, RemoteUrl
    | join kind=inner (
    AlertEvidence
    | where ServiceSource =~ "Microsoft Defender for Office 365"
    | where EntityType =~ "MailMessage"
    | project AlertId, NetworkMessageId
    )
    on AlertId
    | distinct RemoteUrl, NetworkMessageId
    | join EmailEvents on NetworkMessageId
    | distinct RemoteUrl, NetworkMessageId, RecipientEmailAddress, RecipientObjectId
    | join kind = inner IdentityInfo on $left.RecipientObjectId  == $right.AccountObjectId
    | distinct RemoteUrl, NetworkMessageId, RecipientEmailAddress , RecipientObjectId, AccountSID
    | join kind = inner  
    (DeviceEvents
    | where ActionType =~ "BrowserLaunchedToOpenUrl"| where isnotempty(RemoteUrl)
    | project  UrlClickedByUserSid = RemoteUrl,
    InitiatingProcessAccountSid, DeviceName, DeviceId, InitiatingProcessFileName,
    InitiatingProcessAccountUpn, InitiatingProcessAccountName, InitiatingProcessAccountDomain
    )
    on $left.AccountSID == $right.InitiatingProcessAccountSid and $left.RemoteUrl == $right.UrlClickedByUserSid
    | distinct  RemoteUrl, NetworkMessageId, RecipientEmailAddress, RecipientObjectId,
     AccountSID, UrlClickedByUserSid, DeviceName, DeviceId, InitiatingProcessFileName,
     InitiatingProcessAccountUpn, InitiatingProcessAccountName, InitiatingProcessAccountDomain
    |  join kind=inner
    (
    //Suspicious url clicked found in common security logs
    CommonSecurityLog
    | project TimeGenerated, DeviceVendor, DeviceProduct, DeviceAction, DestinationDnsDomain, DestinationIP, RequestURL, SourceIP, SourceHostName, RequestClientApplication
    ) on $left.RemoteUrl== $right.RequestURL
    |  join kind=inner
    (
    //Find the relevant network sessions
    _Im_NetworkSession
    | where isnotempty(DstIpAddr)
    | where not(ipv4_is_private(DstIpAddr))
    | project TimeGenerated, SrcIpAddr, SrcPortNumber, DstIpAddr, DstPortNumber, DstBytes, SrcBytes
    ) on  $left.DestinationIP == $right.DstIpAddr //The relevant network session being projected 
    | summarize count() by TimeGenerated, RecipientEmailAddress, UrlClickedByUserSid, InitiatingProcessAccountUpn, InitiatingProcessAccountName, InitiatingProcessAccountDomain,
    DeviceName, InitiatingProcessFileName, DeviceProduct, DeviceAction, SourceIP, DestinationIP, RequestClientApplication
    | extend HostName = tostring(split(DeviceName, ".")[0]), DomainIndex = toint(indexof(DeviceName, '.'))
    | extend HostNameDomain = iff(DomainIndex != -1, substring(DeviceName, DomainIndex + 1), DeviceName)
    | extend RecipientEmailName = tostring(split(RecipientEmailAddress,'@',0)[0]), RecipientEmailUPNSuffix = tostring(split(RecipientEmailAddress,'@',1)[0])
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName 
        columnName: InitiatingProcessAccountUpn
      - identifier: Name
        columnName: InitiatingProcessAccountName
      - identifier: UPNSuffix
        columnName: InitiatingProcessAccountDomain
  - entityType: Account
    fieldMappings:
      - identifier: FullName 
        columnName: RecipientEmailAddress
      - identifier: Name
        columnName: RecipientEmailName
      - identifier: UPNSuffix
        columnName: RecipientEmailUPNSuffix
  - entityType: Host
    fieldMappings:
      - identifier: FullName 
        columnName: DeviceName
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: HostNameDomain
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SourceIP
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: DestinationIP
version: 1.1.2
kind: Scheduled

Stages and Predicates

Stage 1: source

AlertEvidence

Stage 2: where

| where ServiceSource =~ "Microsoft Defender for Office 365"

Stage 3: where

| where EntityType =~ "Url"

Stage 4: project

| project AlertId, RemoteUrl

Stage 5: join

| join kind=inner (
AlertEvidence
| where ServiceSource =~ "Microsoft Defender for Office 365"
| where EntityType =~ "MailMessage"
| project AlertId, NetworkMessageId
)
on AlertId

Stage 6: distinct

| distinct RemoteUrl, NetworkMessageId

Stage 7: join

| join EmailEvents on NetworkMessageId

Stage 8: distinct

| distinct RemoteUrl, NetworkMessageId, RecipientEmailAddress, RecipientObjectId

Stage 9: join

| join kind = inner IdentityInfo on $left.RecipientObjectId  == $right.AccountObjectId

Stage 10: distinct

| distinct RemoteUrl, NetworkMessageId, RecipientEmailAddress , RecipientObjectId, AccountSID

Stage 11: join

| join kind = inner  
(DeviceEvents
| where ActionType =~ "BrowserLaunchedToOpenUrl"| where isnotempty(RemoteUrl)
| project  UrlClickedByUserSid = RemoteUrl,
InitiatingProcessAccountSid, DeviceName, DeviceId, InitiatingProcessFileName,
InitiatingProcessAccountUpn, InitiatingProcessAccountName, InitiatingProcessAccountDomain
)
on $left.AccountSID == $right.InitiatingProcessAccountSid and $left.RemoteUrl == $right.UrlClickedByUserSid

Stage 12: distinct

| distinct  RemoteUrl, NetworkMessageId, RecipientEmailAddress, RecipientObjectId,
 AccountSID, UrlClickedByUserSid, DeviceName, DeviceId, InitiatingProcessFileName,
 InitiatingProcessAccountUpn, InitiatingProcessAccountName, InitiatingProcessAccountDomain

Stage 13: join

| join kind=inner
(
CommonSecurityLog
| project TimeGenerated, DeviceVendor, DeviceProduct, DeviceAction, DestinationDnsDomain, DestinationIP, RequestURL, SourceIP, SourceHostName, RequestClientApplication
) on $left.RemoteUrl== $right.RequestURL

Stage 14: join

| join kind=inner
(
_Im_NetworkSession
| where isnotempty(DstIpAddr)
| where not(ipv4_is_private(DstIpAddr))
| project TimeGenerated, SrcIpAddr, SrcPortNumber, DstIpAddr, DstPortNumber, DstBytes, SrcBytes
) on  $left.DestinationIP == $right.DstIpAddr

Stage 15: summarize

| summarize count() by TimeGenerated, RecipientEmailAddress, UrlClickedByUserSid, InitiatingProcessAccountUpn, InitiatingProcessAccountName, InitiatingProcessAccountDomain,
DeviceName, InitiatingProcessFileName, DeviceProduct, DeviceAction, SourceIP, DestinationIP, RequestClientApplication

Stage 16: extend (3 consecutive steps)

| extend HostName = tostring(split(DeviceName, ".")[0]), DomainIndex = toint(indexof(DeviceName, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(DeviceName, DomainIndex + 1), DeviceName)
| extend RecipientEmailName = tostring(split(RecipientEmailAddress,'@',0)[0]), RecipientEmailUPNSuffix = tostring(split(RecipientEmailAddress,'@',1)[0])

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
DstIpAddrcidr_match10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, 127.0.0.0/8

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
ActionTypeeq
  • BrowserLaunchedToOpenUrl
DstIpAddris_not_null
  • (no value, null check)
EntityTypeeq
  • MailMessage
  • Url
RemoteUrlis_not_null
  • (no value, null check)
ServiceSourceeq
  • Microsoft Defender for Office 365

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
DestinationIPsummarize
DeviceActionsummarize
DeviceNamesummarize
DeviceProductsummarize
InitiatingProcessAccountDomainsummarize
InitiatingProcessAccountNamesummarize
InitiatingProcessAccountUpnsummarize
InitiatingProcessFileNamesummarize
RecipientEmailAddresssummarize
RequestClientApplicationsummarize
SourceIPsummarize
TimeGeneratedsummarize
UrlClickedByUserSidsummarize
DomainIndexextend
HostNameextend
HostNameDomainextend
RecipientEmailNameextend
RecipientEmailUPNSuffixextend