Port Scan
| Id | b2c5907b-1040-4692-9802-9946031017e8 |
| Rulename | Port Scan |
| Description | Identifies a source IP scanning multiple open ports on Azure 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 |
| Tactics | Discovery Reconnaissance |
| Techniques | T1046 T1595.001 |
| Required data connectors | AzureFirewall |
| Kind | Scheduled |
| Query frequency | 1d |
| Query period | 1d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Azure Firewall/Analytic Rules/Azure Firewall - Port Scan.yaml |
| Version | 1.1.3 |
| Arm template | b2c5907b-1040-4692-9802-9946031017e8.json |
let MinimumDifferentPortsThreshold = 100;
let BinTime = 30s;
// Exclude known benign scanner IPs in your environment to reduce noise
let KnownScannerIPs = dynamic([]);
union isfuzzy=true(
AZFWApplicationRule
| where SourceIp !in (KnownScannerIPs)
| summarize AlertTimedCountPortsInBinTime = dcount(DestinationPort) by SourceIp, bin(TimeGenerated, BinTime), Fqdn
| where AlertTimedCountPortsInBinTime > MinimumDifferentPortsThreshold),
(AZFWNetworkRule
| where SourceIp !in (KnownScannerIPs)
| extend Fqdn = DestinationIp
| summarize AlertTimedCountPortsInBinTime = dcount(DestinationPort) by SourceIp, bin(TimeGenerated, BinTime), Fqdn
| where AlertTimedCountPortsInBinTime > MinimumDifferentPortsThreshold),
(AzureDiagnostics
| where OperationName == "AzureFirewallApplicationRuleLog" or OperationName == "AzureFirewallNetworkRuleLog"
| parse msg_s with * "from " SourceIp ":" SourcePort:int " to " Fqdn ":" DestinationPort:int *
| where isnotempty(Fqdn) and isnotempty(SourceIp)
| where SourceIp !in (KnownScannerIPs)
| summarize AlertTimedCountPortsInBinTime = dcount(DestinationPort) by SourceIp, bin(TimeGenerated, BinTime), Fqdn
| where AlertTimedCountPortsInBinTime > MinimumDifferentPortsThreshold)
relevantTechniques:
- T1046
- T1595.001
entityMappings:
- entityType: IP
fieldMappings:
- columnName: SourceIp
identifier: Address
- entityType: URL
fieldMappings:
- columnName: Fqdn
identifier: Url
version: 1.1.3
id: b2c5907b-1040-4692-9802-9946031017e8
severity: Medium
kind: Scheduled
queryFrequency: 1d
description: |
'Identifies a source IP scanning multiple open ports on Azure 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.'
requiredDataConnectors:
- connectorId: AzureFirewall
dataTypes:
- AzureDiagnostics
- AZFWApplicationRule
- AZFWNetworkRule
triggerOperator: gt
name: Port Scan
tactics:
- Discovery
- Reconnaissance
alertDetailsOverride:
alertDescriptionFormat: Source IP {{SourceIp}} has scanned {{AlertTimedCountPortsInBinTime}} different ports within a short time frame, which may indicate reconnaissance activity.
alertDisplayNameFormat: Port Scan Detected from {{SourceIp}}
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Azure Firewall/Analytic Rules/Azure Firewall - Port Scan.yaml
triggerThreshold: 0
queryPeriod: 1d
query: |
let MinimumDifferentPortsThreshold = 100;
let BinTime = 30s;
// Exclude known benign scanner IPs in your environment to reduce noise
let KnownScannerIPs = dynamic([]);
union isfuzzy=true(
AZFWApplicationRule
| where SourceIp !in (KnownScannerIPs)
| summarize AlertTimedCountPortsInBinTime = dcount(DestinationPort) by SourceIp, bin(TimeGenerated, BinTime), Fqdn
| where AlertTimedCountPortsInBinTime > MinimumDifferentPortsThreshold),
(AZFWNetworkRule
| where SourceIp !in (KnownScannerIPs)
| extend Fqdn = DestinationIp
| summarize AlertTimedCountPortsInBinTime = dcount(DestinationPort) by SourceIp, bin(TimeGenerated, BinTime), Fqdn
| where AlertTimedCountPortsInBinTime > MinimumDifferentPortsThreshold),
(AzureDiagnostics
| where OperationName == "AzureFirewallApplicationRuleLog" or OperationName == "AzureFirewallNetworkRuleLog"
| parse msg_s with * "from " SourceIp ":" SourcePort:int " to " Fqdn ":" DestinationPort:int *
| where isnotempty(Fqdn) and isnotempty(SourceIp)
| where SourceIp !in (KnownScannerIPs)
| summarize AlertTimedCountPortsInBinTime = dcount(DestinationPort) by SourceIp, bin(TimeGenerated, BinTime), Fqdn
| where AlertTimedCountPortsInBinTime > MinimumDifferentPortsThreshold)
status: Available