Detection rules › Elastic
Suspicious Executable Download via Ruby
Detects when Ruby makes a network connection followed immediately by the rename or modification of a macOS binary. This initial diagnostic rule is meant to allow for an analysis of this activity and tune this rule to detect potential malicious initial access via Ruby scripts or packages.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| macOS | ESF event write (NOTIFY): Fires after a process writes data to a file. |
Rule body
[rule]
description = """
Detects when Ruby makes a network connection followed immediately by the rename or modification of a macOS binary. This
initial diagnostic rule is meant to allow for an analysis of this activity and tune this rule to detect potential
malicious initial access via Ruby scripts or packages.
"""
id = "42e3338b-c9a0-45bc-9ebf-dfbf1c45289d"
license = "Elastic License v2"
name = "Suspicious Executable Download via Ruby"
os_list = ["macos"]
reference = ["https://www.mandiant.com/resources/blog/north-korea-supply-chain"]
version = "1.0.15"
query = '''
sequence by process.entity_id with maxspan=1m
[network where event.type == "start" and process.name == "ruby"]
[file where event.action == "modification" and process.name == "ruby" and
file.Ext.header_bytes like~ ("cffaedfe*", "cafebabe*") and
file.path like~ ("/Users/Shared/*", "/tmp/*", "/private/tmp/*", "/var/tmp/*", "/private/var/tmp/*", "/usr/local/bin/*") and
not file.extension in ("dylib", "so", "bundle")]
'''
min_endpoint_version = "8.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1105"
name = "Ingress Tool Transfer"
reference = "https://attack.mitre.org/techniques/T1105/"
[threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
[internal]
min_endpoint_version = "8.16.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 1m, correlated by process.entity_id.
Stage 1: network
[network where event.type == "start" and process.name == "ruby"]
Stage 2: file
[file where event.action == "modification" and process.name == "ruby" and
file.Ext.header_bytes like~ ("cffaedfe*", "cafebabe*") and
file.path like~ ("/Users/Shared/*", "/tmp/*", "/private/tmp/*", "/var/tmp/*", "/private/var/tmp/*", "/usr/local/bin/*") and
not file.extension in ("dylib", "so", "bundle")]
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
file.extension | in | bundle, dylib, so | excludes:file.extension field:"file.extension" value:"bundle" field:"file.extension" value:"dylib" field:"file.extension" value:"so" |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"modification" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
file.Ext.header_bytes | wildcard |
| field:"file.Ext.header_bytes" kind:wildcard |
file.path | wildcard |
| field:"TargetFilename" kind:wildcard |
process.name | eq |
| field:"process_name" kind:eq value:"ruby" |