Persistence via Login or Logout Hook

Identifies use of the Defaults command to install a login or logoff hook in MacOS. An adversary may abuse this capability to establish persistence in an environment by inserting code to be executed at login or logout.

Elastic rule (View on GitHub)

 1[metadata]
 2creation_date = "2020/12/07"
 3integration = ["endpoint"]
 4maturity = "production"
 5min_stack_comments = "New fields added: required_fields, related_integrations, setup"
 6min_stack_version = "8.3.0"
 7updated_date = "2023/06/22"
 8
 9[rule]
10author = ["Elastic"]
11description = """
12Identifies use of the Defaults command to install a login or logoff hook in MacOS. An adversary may abuse this
13capability to establish persistence in an environment by inserting code to be executed at login or logout.
14"""
15from = "now-9m"
16index = ["auditbeat-*", "logs-endpoint.events.*"]
17language = "eql"
18license = "Elastic License v2"
19name = "Persistence via Login or Logout Hook"
20note = """## Setup
21
22If enabling an EQL rule on a non-elastic-agent index (such as beats) for versions <8.2, events will not define `event.ingested` and default fallback for EQL rules was not added until 8.2, so you will need to add a custom pipeline to populate `event.ingested` to @timestamp for this rule to work.
23"""
24references = [
25    "https://www.virusbulletin.com/uploads/pdf/conference_slides/2014/Wardle-VB2014.pdf",
26    "https://www.manpagez.com/man/1/defaults/",
27]
28risk_score = 47
29rule_id = "5d0265bf-dea9-41a9-92ad-48a8dcd05080"
30severity = "medium"
31tags = ["Domain: Endpoint", "OS: macOS", "Use Case: Threat Detection", "Tactic: Persistence", "Data Source: Elastic Defend"]
32timestamp_override = "event.ingested"
33type = "eql"
34
35query = '''
36process where host.os.type == "macos" and event.type == "start" and
37 process.name == "defaults" and process.args == "write" and process.args : ("LoginHook", "LogoutHook") and
38 not process.args :
39       (
40         "Support/JAMF/ManagementFrameworkScripts/logouthook.sh",
41         "Support/JAMF/ManagementFrameworkScripts/loginhook.sh",
42         "/Library/Application Support/JAMF/ManagementFrameworkScripts/logouthook.sh",
43         "/Library/Application Support/JAMF/ManagementFrameworkScripts/loginhook.sh"
44       )
45'''
46
47
48[[rule.threat]]
49framework = "MITRE ATT&CK"
50[[rule.threat.technique]]
51id = "T1037"
52name = "Boot or Logon Initialization Scripts"
53reference = "https://attack.mitre.org/techniques/T1037/"
54
55
56[rule.threat.tactic]
57id = "TA0003"
58name = "Persistence"
59reference = "https://attack.mitre.org/tactics/TA0003/"

Setup

If enabling an EQL rule on a non-elastic-agent index (such as beats) for versions <8.2, events will not define event.ingested and default fallback for EQL rules was not added until 8.2, so you will need to add a custom pipeline to populate event.ingested to @timestamp for this rule to work.

References

Related rules

to-top