Detection rules › Panther

CrowdStrike MacOS plutil Novel Plist Modification (Anomaly Detection)

Status
Experimental
Severity
medium
Group by
device_id, plist_file
Tags
Anomaly Detection, macOS, Persistence, CrowdStrike, T1547.011
Reference
https://attack.mitre.org/techniques/T1547/011/
Source
github.com/panther-labs/panther-analysis

Detects when plutil performs modification operations (insert, replace, remove, create) on plist files it hasn't modified in the previous 30 days. Uses behavioral filtering to exclude read-only operations (convert, print, lint). This anomaly-based approach reduces noise from legitimate repeated operations while catching novel persistence attempts, even in /Applications/.

MITRE ATT&CK coverage

Rule body yaml

AnalysisType: scheduled_rule
Filename: crowdstrike_macos_plutil_newfiles.py
DisplayName: CrowdStrike MacOS plutil Novel Plist Modification (Anomaly Detection)
Enabled: false
Status: Experimental
Description: |
  Detects when plutil performs modification operations (insert, replace, remove, create) on plist
  files it hasn't modified in the previous 30 days. Uses behavioral filtering to exclude read-only
  operations (convert, print, lint). This anomaly-based approach reduces noise from legitimate
  repeated operations while catching novel persistence attempts, even in /Applications/.
Severity: Medium
DedupPeriodMinutes: 1440
Threshold: 1
Reference: https://attack.mitre.org/techniques/T1547/011/
Runbook: |
  1. Verify the plist modification was authorized. Query CrowdStrike for the full plutil command line on the affected device to determine the exact operation performed (insert, replace, remove, create) and identify the parent process that executed the command.
  2. Review the modification context including the user account, source process, and timing. Assess the risk level based on the plist location - LaunchAgents/LaunchDaemons indicate persistence attempts (high risk), while /Applications/ modifications could be legitimate software updates (medium risk). Check for suspicious parent processes such as bash, python, curl, or remote shell activity.
  3. If the modification is suspicious or unauthorized, quarantine the device and analyze the modified plist content for malicious payloads or references to external scripts. Review all processes currently running that may have been launched by the modified plist, revoke any persistence mechanisms, and hunt for related IOCs across other endpoints. Escalate for forensic analysis if compromise is confirmed.
Tags:
  - Anomaly Detection
  - macOS
  - Persistence
  - CrowdStrike
  - T1547.011
InlineFilters:
  - All: []
ScheduledQueries:
  - CrowdStrike MacOS plutil Novel Plist Modification
RuleID: Crowdstrike.Macos.Plutil.NewFiles
Tests:
  - Name: Anomaly - New LaunchAgent modified for first time (insert operation)
    ExpectedResult: true
    Log:
      {
        "device_id": "abc123def456789",
        "plist_file": "/Library/LaunchAgents/com.suspicious.agent.plist"
      }
  - Name: Anomaly - New LaunchAgent modified for first time (replace operation)
    ExpectedResult: true
    Log:
      {
        "device_id": "abc123def456789",
        "plist_file": "/Library/LaunchAgents/com.attacker.plist"
      }
  - Name: Anomaly - New LaunchDaemon modified for first time (remove operation)
    ExpectedResult: true
    Log:
      {
        "device_id": "xyz789ghi012345",
        "plist_file": "/Library/LaunchDaemons/com.evil.daemon.plist"
      }
  - Name: Anomaly - New plist created for first time (create operation)
    ExpectedResult: true
    Log:
      {
        "device_id": "xyz789ghi012345",
        "plist_file": "/Users/user/Library/LaunchAgents/com.new.persistence.plist"
      }
  - Name: Anomaly - User LaunchAgent never modified before on this device
    ExpectedResult: true
    Log:
      {
        "device_id": "abc123def456789",
        "plist_file": "/Users/john.doe/Library/LaunchAgents/com.malware.backdoor.plist"
      }
  - Name: Anomaly - System LaunchDaemon first modification in 30 days
    ExpectedResult: true
    Log:
      {
        "device_id": "xyz789ghi012345",
        "plist_file": "/System/Library/LaunchDaemons/com.evil.daemon.plist"
      }
  - Name: Anomaly - New application Info.plist modification (potential tampering)
    ExpectedResult: true
    Log:
      {
        "device_id": "mno345pqr678901",
        "plist_file": "/Applications/CustomApp.app/Contents/Info.plist"
      }
  - Name: Anomaly - First-time modification of Homebrew app plist
    ExpectedResult: true
    Log:
      {
        "device_id": "def456ghi789012",
        "plist_file": "/usr/local/Cellar/suspicious-tool/1.0/Info.plist"
      }
  - Name: Anomaly - User preferences plist modified for first time
    ExpectedResult: true
    Log:
      {
        "device_id": "ghi789jkl012345",
        "plist_file": "/Users/jane.smith/Library/Preferences/com.custom.config.plist"
      }
  - Name: Anomaly - Previously unseen plist file in non-standard location
    ExpectedResult: true
    Log:
      {
        "device_id": "stu901vwx234567",
        "plist_file": "/opt/custom/config.plist"
      }
  - Name: Invalid - Empty plist file path
    ExpectedResult: false
    Log:
      {
        "device_id": "abc123def456789",
        "plist_file": ""
      }
  - Name: Invalid - Whitespace only plist path
    ExpectedResult: false
    Log:
      {
        "device_id": "abc123def456789",
        "plist_file": "   "
      }
  - Name: Invalid - Missing plist_file field
    ExpectedResult: false
    Log:
      {
        "device_id": "abc123def456789"
      }
  - Name: Invalid - Unknown placeholder value from query
    ExpectedResult: false
    Log:
      {
        "device_id": "abc123def456789",
        "plist_file": "<UNKNOWN_FILE>"
      }
  - Name: Invalid - Null plist_file value
    ExpectedResult: false
    Log:
      {
        "device_id": "jkl012mno345678",
        "plist_file": null
      }
  - Name: Invalid - Empty result object
    ExpectedResult: false
    Log: {}

Detection logic

Condition

plist_file is_not_null
plist_file ne "<UNKNOWN_FILE>"

This rule also runs imperative logic the parser cannot express as a filter; the conditions above are the structured part it could extract.

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
plist_fileis_not_null
  • (no value, null check)
plist_filene
  • <UNKNOWN_FILE>

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.

Field
device_id
plist_file