Detection rules › Kusto

PLC Stop Command (Microsoft Defender for IoT)

Status
available
Severity
medium
Time window
1h
Source
github.com/Azure/Azure-Sentinel

'This alert leverages Defender for IoT to detect PLC stop commands which could indicate improper configuration or malicious activity on the network such as a threat manipulating PLC programming to affect the function of the network.'

MITRE ATT&CK coverage

Rule body

id: a7d3f642-15d8-4e83-99ee-83ca3352525d
name: PLC Stop Command (Microsoft Defender for IoT)
description: |
  'This alert leverages Defender for IoT to detect PLC stop commands which could indicate improper configuration or malicious activity on the network such as a threat manipulating PLC programming to affect the function of the network.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: IoT
    dataTypes:
      - SecurityAlert (ASC for IoT)
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T0858
query: |
  let alertList = dynamic(["Controller Reset", "An S7 Stop PLC Command was Sent", "Controller Stop", "Excessive Restart Rate of an Outstation", "GE SRTP Stop PLC Command was Sent", "Outstation Restarted", "Outstation Restarts Frequently", "Profinet Device Factory Reset", "Slave Device Unrecoverable Failure", "Suspicion of Hardware Problems in Outstation"]);
  SecurityAlert
  | where ProviderName == "IoTSecurity"
  | where AlertName has_any (alertList) 
  | extend ExtendedProperties = parse_json(ExtendedProperties)
  | where tostring(ExtendedProperties.isNew) == "True"
  | extend DeviceId = tostring(ExtendedProperties.DeviceId), 
           SourceDeviceAddress = tostring(ExtendedProperties.SourceDeviceAddress), 
           DestDeviceAddress = tostring(ExtendedProperties.DestinationDeviceAddress), 
           RemediationSteps = tostring(parse_json(RemediationSteps)[0]), 
           Protocol = tostring(ExtendedProperties.Protocol), 
           AlertManagementUri = tostring(ExtendedProperties.AlertManagementUri)
  | project
    TimeGenerated,
    DeviceId,
    ProductName,
    ProductComponentName,
    AlertSeverity,
    AlertName,
    Description,
    Protocol,
    SourceDeviceAddress,
    DestDeviceAddress,
    RemediationSteps,
    Tactics,
    Entities,
    VendorOriginalId,
    AlertLink,
    AlertManagementUri,
    Techniques
entityMappings:
sentinelEntitiesMappings:
  - columnName: Entities
eventGroupingSettings:
  aggregationKind: AlertPerResult
customDetails:
  Sensor: DeviceId
  Protocol: Protocol
  VendorOriginalId: VendorOriginalId
  AlertManagementUri: AlertManagementUri
alertDetailsOverride:
  alertDisplayNameFormat: (MDIoT) {{AlertName}}
  alertDescriptionFormat: (MDIoT) {{Description}}
  alertTacticsColumnName: Tactics
  alertSeverityColumnName: AlertSeverity
  alertDynamicProperties: 
    - alertProperty: ProductName
      value: ProductName
    - alertProperty: RemediationSteps
      value: RemediationSteps
    - alertProperty: Techniques
      value: Techniques
    - alertProperty: ProductComponentName
      value: ProductComponentName
    - alertProperty: AlertLink
      value: AlertLink
version: 1.0.3
kind: Scheduled

Stages and Predicates

Let binding: alertList used in Stage 3

let alertList = dynamic(["Controller Reset", "An S7 Stop PLC Command was Sent", "Controller Stop", "Excessive Restart Rate of an Outstation", "GE SRTP Stop PLC Command was Sent", "Outstation Restarted", "Outstation Restarts Frequently", "Profinet Device Factory Reset", "Slave Device Unrecoverable Failure", "Suspicion of Hardware Problems in Outstation"]);

Stage 1: source

SecurityAlert

Stage 2: where

| where ProviderName == "IoTSecurity"

Stage 3: where

| where AlertName has_any (alertList)

Stage 4: extend

| extend ExtendedProperties = parse_json(ExtendedProperties)

Stage 5: where

| where tostring(ExtendedProperties.isNew) == "True"

Stage 6: extend

| extend DeviceId = tostring(ExtendedProperties.DeviceId), 
         SourceDeviceAddress = tostring(ExtendedProperties.SourceDeviceAddress), 
         DestDeviceAddress = tostring(ExtendedProperties.DestinationDeviceAddress), 
         RemediationSteps = tostring(parse_json(RemediationSteps)[0]), 
         Protocol = tostring(ExtendedProperties.Protocol), 
         AlertManagementUri = tostring(ExtendedProperties.AlertManagementUri)

Stage 7: project

| project
  TimeGenerated,
  DeviceId,
  ProductName,
  ProductComponentName,
  AlertSeverity,
  AlertName,
  Description,
  Protocol,
  SourceDeviceAddress,
  DestDeviceAddress,
  RemediationSteps,
  Tactics,
  Entities,
  VendorOriginalId,
  AlertLink,
  AlertManagementUri,
  Techniques

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
AlertNamematch
  • An S7 Stop PLC Command was Sent transforms: term
  • Controller Reset transforms: term
  • Controller Stop transforms: term
  • Excessive Restart Rate of an Outstation transforms: term
  • GE SRTP Stop PLC Command was Sent transforms: term
  • Outstation Restarted transforms: term
  • Outstation Restarts Frequently transforms: term
  • Profinet Device Factory Reset transforms: term
  • Slave Device Unrecoverable Failure transforms: term
  • Suspicion of Hardware Problems in Outstation transforms: term
field:"AlertName" kind:match
ProviderNameeq
  • IoTSecurity
field:"ProviderName" kind:eq value:"IoTSecurity"
isNeweq
  • True transforms: tostring
field:"isNew" kind:eq value:"True"

Output fields

These fields are emitted when the rule matches.

FieldSource
AlertLinkproject
AlertManagementUriproject
AlertNameproject
AlertSeverityproject
Descriptionproject
DestDeviceAddressproject
DeviceIdproject
Entitiesproject
ProductComponentNameproject
ProductNameproject
Protocolproject
RemediationStepsproject
SourceDeviceAddressproject
Tacticsproject
Techniquesproject
TimeGeneratedproject
VendorOriginalIdproject