Skip to content

[New Rules] macOS Unified Logs Login Window and XProtect Detections#5874

Open
DefSecSentinel wants to merge 16 commits intomainfrom
colson/loginwindow-xprotect-unified-log-detections
Open

[New Rules] macOS Unified Logs Login Window and XProtect Detections#5874
DefSecSentinel wants to merge 16 commits intomainfrom
colson/loginwindow-xprotect-unified-log-detections

Conversation

@DefSecSentinel
Copy link
Contributor

Summary

  • Adds 2 new alerting rules leveraging macOS Unified Logs telemetry for login item persistence detection and XProtect malware scan correlation
  • Both rules operate at default log level — no debug or private data enablement required
  • Companion to #5867 (Apple Events) and #5870 (TCC)

New Alerting Rules

Rule Subsystem Severity MITRE Pattern
Login Item Persistence Execution via Unified Logs com.apple.loginwindow.logging low T1547.015 performAutolaunch
XProtect Malware Scan Match Detected com.apple.XProtectFramework.PluginAPI high T1036 XProtect scan match

Design Notes

  • Login Window rule: Very low event volume, high signal. Detects when login items execute at user login — a common macOS persistence mechanism. BBR rule for correlation with other indicators.
  • XProtect rule: Rare but extremely high-confidence. Fires when Apple's built-in YARA-based malware scanner detects a known signature. Severity set to high (risk_score 73) given the confidence level.
  • Both subsystems produce telemetry at default log level, making these rules deployable without any endpoint configuration beyond the base integration setup.
  • Also adds message: keyword to non-ecs-schema.json for logs-unified_logs.log-* (same fix as companion PRs).

Relates to: https://github.com/elastic/ia-trade-team/issues/847

Test plan

  • Validate TOML structure passes detection_rules validate-rule
  • Add a login item on test host and verify rule 12 fires on next login
  • Trigger XProtect scan with EICAR or known test signature and verify rule 13 fires
  • Confirm acceptable false positive rate against baseline macOS activity

🤖 Generated with Claude Code

Adds 2 new alerting rules leveraging macOS Unified Logs telemetry for
login item persistence and XProtect malware detection.

New rules:
- Login Item Persistence Execution via Unified Logs (T1547.015)
  com.apple.loginwindow.logging subsystem, performAutolaunch pattern
- XProtect Malware Scan Match Detected (T1036)
  com.apple.XProtectFramework.PluginAPI subsystem, high severity

Also adds message field as keyword in non-ECS schema for the
logs-unified_logs.log-* index pattern to support EQL validation.

Relates to: elastic/ia-trade-team#847

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (eql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (eql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

@github-actions
Copy link
Contributor

Rule: New - Guidelines

These guidelines serve as a reminder set of considerations when proposing a new rule.

Documentation and Context

  • Detailed description of the rule.
  • List any new fields required in ECS/data sources.
  • Link related issues or PRs.
  • Include references.

Rule Metadata Checks

  • creation_date matches the date of creation PR initially merged.
  • min_stack_version should support the widest stack versions.
  • name and description should be descriptive and not include typos.
  • query should be inclusive, not overly exclusive, considering performance for diverse environments. Non ecs fields should be added to non-ecs-schema.json if not available in an integration.
  • min_stack_comments and min_stack_version should be included if the rule is only compatible starting from a specific stack version.
  • index pattern should be neither too specific nor too vague, ensuring it accurately matches the relevant data stream (e.g., use logs-endpoint.process-* for process data).
  • integration should align with the index. If the integration is newly introduced, ensure the manifest, schemas, and new_rule.yaml template are updated.
  • setup should include the necessary steps to configure the integration.
  • note should include any additional information (e.g. Triage and analysis investigation guides, timeline templates).
  • tags should be relevant to the threat and align/added to the EXPECTED_RULE_TAGS in the definitions.py file.
  • threat, techniques, and subtechniques should map to ATT&CK always if possible.

New BBR Rules

  • building_block_type should be included if the rule is a building block and the rule should be located in the rules_building_block folder.
  • bypass_bbr_timing should be included if adding custom lookback timing to the rule.

Testing and Validation

  • Provide evidence of testing and detecting the expected threat.
  • Check for existence of coverage to prevent duplication.

@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (eql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (eql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta


query = '''
any where event.dataset == "unified_logs.log" and host.os.type == "macos" and
message like "*performAutolaunch*"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think message field is supported in EQL :

Image

maybe convert it to KQL

Switch from EQL to KQL since message is match_only_text. Use
unified_log.subsystem keyword field for efficient filtering. Update
index pattern and event.dataset to match actual integration naming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

The ingest pipeline normalizes event.dataset to "unifiedlogs.log"
regardless of the data stream name. Update all rules and index
patterns accordingly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

[metadata]
creation_date = "2026/03/23"
integration = ["unified_logs"]
maturity = "development"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
maturity = "development"
maturity = "production"

"system.process.cpu.total.norm.pct": "double",
"system.cpu.total.norm.pct": "double"
},
"logs-unified_logs.log-*": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be removed and instead add the integration manifest update

@DefSecSentinel DefSecSentinel marked this pull request as draft March 23, 2026 20:49
- Pull unifiedlogs integration manifest and schema via CLI
- Fix integration tag: unified_logs -> unifiedlogs (matches EPR package)
- Fix index pattern: logs-unifiedlogs.log-* -> logs-unifiedlogs.unifiedlogs-*
- Fix event.dataset: unifiedlogs.log -> unifiedlogs.unifiedlogs
- All rules pass local validation with updated schemas

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

data_stream.dataset is "unifiedlogs.unifiedlogs" but event.dataset
is set to "unifiedlogs.log" by the integration. Rules query on
event.dataset so must use the correct value.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (kuery)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

KQL cannot query the message field (match_only_text type with no
keyword sub-field). ES|QL's LIKE operator works correctly on text
fields. Converted both rules to ES|QL with METADATA and KEEP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

user.name, process.name, process.executable don't exist in
the unifiedlogs index. Removed from KEEP to prevent query errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

event.dataset is unifiedlogs.log which maps to package=unifiedlogs,
integration=log. Schema needs a 'log' dataset key.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 23, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

The performAutolaunch pattern doesn't exist in the actual unified
logs on current macOS versions. The real login item execution
pattern is LoginItemsLauncher, which fires during user login
when login items are launched. Updated rule query and description.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 24, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

@DefSecSentinel
Copy link
Contributor Author

Testing & Validation Update

Login Window and XProtect detection rules validated against live unified log data on the trade lab cluster (logs-unifiedlogs.unifiedlogs-*).

Changes Made During Testing

  • Converted rules from KQL to ES|QLmessage is a text field that doesn't support KQL term matching
  • Updated loginwindow rule pattern from performAutolaunch to LoginItemsLauncherperformAutolaunch does not appear in unified logs on current macOS versions; the actual login item execution pattern is LoginItemsLauncher
  • Fixed event.dataset, index pattern, and integration tag to match actual data stream naming
  • Added integration manifest and schema via CLI
  • Removed non-existent fields from ES|QL KEEP clause

Emulation Commands (run on macOS host with Unified Logs integration)

Login Item Persistence Execution:

# 1. Add a test login item
osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/Calculator.app", hidden:false}'

# 2. Log out and log back in (Apple Menu > Log Out)
# The LoginItemsLauncher events fire during the login window phase

# 3. Cleanup
osascript -e 'tell application "System Events" to delete login item "Calculator"'

XProtect Malware Scan Match: Cannot be reliably emulated — requires an actual malware signature match from XProtect. Rule pattern validated structurally.

Integration Prerequisites

  • Unified Logs integration installed on macOS agent policy
  • Debug and Info toggles enabled in integration settings
  • Predicate configured to capture loginwindow and XProtect subsystems:
    subsystem=="com.apple.loginwindow.logging" OR subsystem=="com.apple.XProtectFramework.PluginAPI"
    
  • Note: The original predicate filtered on eventMessage CONTAINS "performAutolaunch" which was too narrow. Broaden to capture all loginwindow events: subsystem=="com.apple.loginwindow.logging"

Validation Results

Rule Emulation Query Match Status
Login Item Persistence Execution Add login item + logout/login LoginItemsLauncher in com.apple.loginwindow.logging ✅ Confirmed
XProtect Malware Scan Match N/A (requires real malware signature) com.apple.XProtectFramework.PluginAPI ⚠️ Structural validation only

@DefSecSentinel DefSecSentinel marked this pull request as ready for review March 24, 2026 14:34
Unified Logs integration is now GA. Rules are validated and
ready for production use.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 24, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tradebot-elastic
Copy link

tradebot-elastic commented Mar 24, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

@tradebot-elastic
Copy link

tradebot-elastic commented Mar 24, 2026

⛔️ Test failed

Results
  • ❌ XProtect Malware Scan Match Detected (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta
  • ❌ Login Item Persistence Execution via Unified Logs (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport: auto dev rule meant to be non-prod / non-shipping integration: Unified_Logs OS: macOS patch Rule: New Proposal for new rule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants