Detection rules › Elastic
Launchctl Submit Execution of Downloaded File
Identifies the execution of a recently downloaded file via launchctl submit. Adversaries may download payloads with curl or wget and register them as transient launchd jobs in order to execute them in the background.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Execution |
Telemetry coverage
Rule body
[rule]
description = """
Identifies the execution of a recently downloaded file via launchctl submit. Adversaries may download payloads with curl
or wget and register them as transient launchd jobs in order to execute them in the background.
"""
id = "6b950b18-a6b4-465c-876b-e9536b282471"
license = "Elastic License v2"
name = "Launchctl Submit Execution of Downloaded File"
os_list = ["macos"]
version = "1.0.1"
query = '''
sequence with maxspan=1m
[process where event.type == "start" and event.action == "exec" and
process.name in ("curl", "nscurl", "wget") and process.command_line like "*http*"] as event0
[file where event.action != "deletion" and process.name in ("curl", "nscurl", "wget") and
process.entity_id == event0.process.entity_id] as event1
[process where event.type == "start" and event.action == "exec" and
process.name == "launchctl" and process.args == "submit" and process.args == "-l" and
stringcontains~(process.command_line, event1.file.name)]
'''
min_endpoint_version = "8.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 2
[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 2
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1569"
name = "System Services"
reference = "https://attack.mitre.org/techniques/T1569/"
[[threat.technique.subtechnique]]
id = "T1569.001"
name = "Launchctl"
reference = "https://attack.mitre.org/techniques/T1569/001/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[internal]
min_endpoint_version = "8.16.0"
Stages and Predicates
Stage 1: process
[process where event.type == "start" and event.action == "exec" and
process.name in ("curl", "nscurl", "wget") and process.command_line like "*http*"] as event0
Stage 2: file
[file where event.action != "deletion" and process.name in ("curl", "nscurl", "wget") and
process.entity_id == event0.process.entity_id] as event1
Stage 3: process
[process where event.type == "start" and event.action == "exec" and
process.name == "launchctl" and process.args == "submit" and process.args == "-l" and
stringcontains~(process.command_line, event1.file.name)]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.action | ne |
| field:"EventType" kind:ne value:"deletion" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | eq |
| field:"process.args" kind:eq |
process.command_line | contains |
| field:"CommandLine" kind:contains value:"event1.file.name" |
process.command_line | wildcard |
| field:"CommandLine" kind:wildcard value:"*http*" |
process.entity_id | eq |
| field:"process_guid" kind:eq value:"event0.process.entity_id" |
process.name | eq |
| field:"process_name" kind:eq value:"launchctl" |
process.name | in |
| field:"process_name" kind:in |