Detection rules › Kusto

GSA - Detect Source IP Scanning Multiple Open Ports

Status
available
Severity
medium
Time window
30s
Group by
DestinationFqdn, SourceIp
Source
github.com/Azure/Azure-Sentinel

Identifies a source IP scanning multiple open ports on Global Secure Access Firewall. This can indicate malicious scanning of ports by an attacker, trying to reveal open ports in the organization that can be compromised for initial access. Configurable Parameters: - Port scan time - the time range to look for multiple ports scanned. Default is set to 30 seconds. - Minimum different ports threshold - alert only if more than this number of ports scanned. Default is set to 100.

MITRE ATT&CK coverage

TacticTechniques
DiscoveryT1046 Network Service Discovery

Rule body kusto

id: 82cfa6b9-5f7e-4b8b-8b2f-a63f21b7a7d1
name: GSA - Detect Source IP Scanning Multiple Open Ports
description: |
  Identifies a source IP scanning multiple open ports on Global Secure Access Firewall. This can indicate malicious scanning of ports by an attacker, trying to reveal open ports in the organization that can be compromised for initial access.
    Configurable Parameters:
    - Port scan time - the time range to look for multiple ports scanned. Default is set to 30 seconds.
    - Minimum different ports threshold - alert only if more than this number of ports scanned. Default is set to 100.
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - NetworkAccessTrafficLogs
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 1
tactics:
  - Discovery
relevantTechniques:
  - T1046
query: |
  let port_scan_time = 30s;
  let min_ports_threshold = 100;
  NetworkAccessTraffic
  | where TimeGenerated > ago(1d)
  | where Action == 'Allowed'
  | summarize PortsScanned = dcount(DestinationPort) by SourceIp, DestinationFqdn, bin(TimeGenerated, port_scan_time)
  | where PortsScanned > min_ports_threshold
  | project SourceIp, PortsScanned, TimeGenerated,DestinationFqdn
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SourceIp
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: DestinationFqdn
version: 1.0.2
kind: Scheduled

Stages and Predicates

Parameters

let port_scan_time = 30s;
let min_ports_threshold = 100;

Stage 1: source

NetworkAccessTraffic

Stage 2: where

| where TimeGenerated > ago(1d)

Stage 3: where

| where Action == 'Allowed'

Stage 4: summarize

| summarize PortsScanned = dcount(DestinationPort) by SourceIp, DestinationFqdn, bin(TimeGenerated, port_scan_time)
Threshold
gt 100

Stage 5: where

| where PortsScanned > min_ports_threshold

Stage 6: project

| project SourceIp, PortsScanned, TimeGenerated,DestinationFqdn

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
Actioneq
  • Allowed transforms: cased
PortsScannedgt
  • 100 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
DestinationFqdnproject
PortsScannedproject
SourceIpproject
TimeGeneratedproject