Detection rules › Kusto

Jamf Protect - Alerts

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
Source
github.com/Azure/Azure-Sentinel

'Creates an incident based on Jamf Protect Alert data in Microsoft Sentinel'

Rule body kusto

id: 6098daa0-f05e-44d5-b5a0-913e63ba3179
name: Jamf Protect - Alerts 
description: |
  'Creates an incident based on Jamf Protect Alert data in Microsoft Sentinel'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: JamfProtect
    dataTypes: 
      - jamfprotectalerts_CL
suppressionDuration: PT5H
suppressionEnabled: false
tactics:
relevantTechniques:
query: |
  jamfprotectalerts_CL
  | extend
      algorithm = "SHA256",
      Host_IPs = tostring(parse_json(DvcIpAddr)[0]),
      Tags = parse_json(tostring(parse_json(tostring(input.match)).tags)),
      Tactics = case(input.match.tags has "Execution", "Execution", input.match.tags has "Visibility", "Visibility", input.match.tags has "Persistence", "Persistence", input.match.tags has "LateralMovement", "LateralMovement", input.match.tags has "CredentialAccess", "CredentialAcccess", input.match.tags has "DefenseEvasion", "DefenseEvasion", input.match.tags has "PrivilegeEscalation", "PrivilegeEscalation", input.match.tags has "Impact", "Impact", input.match.tags has "CommandAndControl", "CommandandControl", input.match.tags has "Discovery", "Discovery", input.match.tags has "InitialAccess", "InitialAccess", ""),
      Techniques = pack_array(extract(@"[A-Za-z]\d{4}", 0, tostring(input.match.tags))),
      JamfPro = case(input.match.actions has "SmartGroup", "Workflow with Jamf Pro", input.match.actions has "Prevented", "No workflow, Prevented by Protect", "No workflow")
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
eventGroupingSettings:
  aggregationKind: AlertPerResult
alertDetailsOverride:
  alertDisplayNameFormat: "{{EventMessage}} detected on {{DvcHostname}}"
  alertDescriptionFormat: "{{EventResultMessage}} - Please investigate"
  alertTacticsColumnName: Tactics
  alertSeverityColumnName: EventSeverity
  alertDynamicProperties:
    - alertProperty: ProviderName
      value: EventVendor
    - alertProperty: ProductName
      value: EventProduct
    - alertProperty: Techniques
      value: Techniques
customDetails:
  Protect_Event_Type: EventType
  Protect_Analytic: EventMessage
  Related_File_hash: TargetBinarySHA256
  Related_Binaries: TargetBinaryFilePath
  TargetBinarySignMsg: TargetBinarySigningInfoMessage
  TargetbinarySign: TargetbinarySignerType
  TargetBinarySigner: TargetBinarySigningTeamID
  JamfPro_Status: JamfPro
  Protect_Tags: Tags
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: DvcHostname
      - identifier: OSFamily
        columnName: DvcOs
      - identifier: OSVersion
        columnName: DvcOsVersion
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: Host_IPs
  - entityType: Process
    fieldMappings:
      - identifier: CommandLine
        columnName: TargetProcessCurrentDirectory
      - identifier: ProcessId
        columnName: TargetProcessId
  - entityType: FileHash
    fieldMappings:
      - identifier: Algorithm
        columnName: algorithm
      - identifier: Value
        columnName: TargetBinarySHA256
version: 1.0.6
kind: NRT

Stages and Predicates

Stage 1: source

jamfprotectalerts_CL

Stage 2: extend

| extend
    algorithm = "SHA256",
    Host_IPs = tostring(parse_json(DvcIpAddr)[0]),
    Tags = parse_json(tostring(parse_json(tostring(input.match)).tags)),
    Tactics = case(input.match.tags has "Execution", "Execution", input.match.tags has "Visibility", "Visibility", input.match.tags has "Persistence", "Persistence", input.match.tags has "LateralMovement", "LateralMovement", input.match.tags has "CredentialAccess", "CredentialAcccess", input.match.tags has "DefenseEvasion", "DefenseEvasion", input.match.tags has "PrivilegeEscalation", "PrivilegeEscalation", input.match.tags has "Impact", "Impact", input.match.tags has "CommandAndControl", "CommandandControl", input.match.tags has "Discovery", "Discovery", input.match.tags has "InitialAccess", "InitialAccess", ""),
    Techniques = pack_array(extract(@"[A-Za-z]\d{4}", 0, tostring(input.match.tags))),
    JamfPro = case(input.match.actions has "SmartGroup", "Workflow with Jamf Pro", input.match.actions has "Prevented", "No workflow, Prevented by Protect", "No workflow")
JamfPro =
ifactions has "SmartGroup""Workflow with Jamf Pro"
elifactions has "Prevented""No workflow, Prevented by Protect"
else"No workflow"
Tactics =
iftags has "Execution""Execution"
eliftags has "Visibility""Visibility"
eliftags has "Persistence""Persistence"
eliftags has "LateralMovement""LateralMovement"
eliftags has "CredentialAccess""CredentialAcccess"
eliftags has "DefenseEvasion""DefenseEvasion"
eliftags has "PrivilegeEscalation""PrivilegeEscalation"
eliftags has "Impact""Impact"
eliftags has "CommandAndControl""CommandandControl"
eliftags has "Discovery""Discovery"
eliftags has "InitialAccess""InitialAccess"
else""

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
Host_IPsextend
JamfProextend
Tacticsextend
Tagsextend
Techniquesextend
algorithmextend