Detection rules › Kusto

CYFIRMA - Attack Surface - Open Ports High Rule

This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.

Status
available
Severity
high
Time window
5m
Source
github.com/Azure/Azure-Sentinel

"This rule is triggered when CYFIRMA identifies open and publicly accessible ports on internet-facing assets. Exposed services may include SSH, RDP, HTTP, or other potentially sensitive ports, increasing the risk of unauthorized access, exploitation, or reconnaissance by threat actors. Monitoring open ports is critical to reducing the external attack surface and preventing misuse through brute force, service vulnerabilities, or protocol exploitation."

MITRE ATT&CK coverage

TacticTechniques
Initial AccessT1566 Phishing
PersistenceT1505 Server Software Component
Command & ControlT1071 Application Layer Protocol

Rule body kusto

id: 87e7eb3f-bb8e-46e5-8807-d3fc63d0f676
name: CYFIRMA - Attack Surface - Open Ports High Rule
description: |
  "This rule is triggered when CYFIRMA identifies open and publicly accessible ports on internet-facing assets. Exposed services may include SSH, RDP, HTTP, or other potentially sensitive ports, increasing the risk of unauthorized access, exploitation, or reconnaissance by threat actors. Monitoring open ports is critical to reducing the external attack surface and preventing misuse through brute force, service vulnerabilities, or protocol exploitation."
version: 1.0.1
kind: Scheduled
severity: High
requiredDataConnectors:
  - connectorId: CyfirmaAttackSurfaceAlertsConnector
    dataTypes:
      - CyfirmaASOpenPortsAlerts_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - InitialAccess
  - CommandAndControl
  - Discovery
  - DefenseEvasion
  - Persistence
relevantTechniques:
  - T1566
  - T1071
  - T1505
query: |
  // High Severity - Open Ports Exposure Detected
  let timeFrame = 5m;
  CyfirmaASOpenPortsAlerts_CL
  | where severity == 'Critical' and TimeGenerated between (ago(timeFrame) .. now())
  | extend Description=description, FirstSeen=first_seen, LastSeen=last_seen, RiskScore=risk_score, Domain=sub_domain, TopDomain=top_domain, NetworkIP=ip, AlertUID=alert_uid, UID=uid, WebServer=web_server, WebServerVersion=web_server_version, OpenPorts=open_ports, ProviderName="CYFIRMA", ProductName="DeCYFIR/DeTCT"
  | project
      TimeGenerated,
      Description,
      Domain,
      TopDomain,
      RiskScore,
      FirstSeen,
      LastSeen,
      NetworkIP,
      AlertUID,
      UID,
      WebServer,
      WebServerVersion,
      OpenPorts,
      ProductName,
      ProviderName
entityMappings:
  - entityType: DNS
    fieldMappings:
      - identifier: DomainName
        columnName: Domain
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: TopDomain
      - identifier: DnsDomain
        columnName: Domain
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: NetworkIP
customDetails:
  TimeGenerated: TimeGenerated
  RiskScore: RiskScore
  FirstSeen: FirstSeen
  LastSeen: LastSeen
  AlertUID: AlertUID
  UID: UID
  WebServer: WebServer
  WebServerVersion: WebServerVersion
  OpenPorts: OpenPorts
  Description: Description
alertDetailsOverride:
  alertDisplayNameFormat: "CYFIRMA - High Severity Open Ports Exposure Detected on Assets - Domain: {{Domain}}, IP: {{NetworkIP}}"
  alertDescriptionFormat: "CYFIRMA - High Severity Open Ports Exposure Detected on Assets - {{Description}}"
  alertDynamicProperties:
    - alertProperty: ProductName
      value: ProductName
    - alertProperty: ProviderName
      value: ProviderName
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
eventGroupingSettings:
  aggregationKind: AlertPerResult

Stages and Predicates

Parameters

let timeFrame = 5m;

Stage 1: source

CyfirmaASOpenPortsAlerts_CL

Stage 2: where

| where severity == 'Critical' and TimeGenerated between (ago(timeFrame) .. now())

Stage 3: extend

| extend Description=description, FirstSeen=first_seen, LastSeen=last_seen, RiskScore=risk_score, Domain=sub_domain, TopDomain=top_domain, NetworkIP=ip, AlertUID=alert_uid, UID=uid, WebServer=web_server, WebServerVersion=web_server_version, OpenPorts=open_ports, ProviderName="CYFIRMA", ProductName="DeCYFIR/DeTCT"

Stage 4: project

| project
    TimeGenerated,
    Description,
    Domain,
    TopDomain,
    RiskScore,
    FirstSeen,
    LastSeen,
    NetworkIP,
    AlertUID,
    UID,
    WebServer,
    WebServerVersion,
    OpenPorts,
    ProductName,
    ProviderName

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
severityeq
  • Critical 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
AlertUIDproject
Descriptionproject
Domainproject
FirstSeenproject
LastSeenproject
NetworkIPproject
OpenPortsproject
ProductNameproject
ProviderNameproject
RiskScoreproject
TimeGeneratedproject
TopDomainproject
UIDproject
WebServerproject
WebServerVersionproject