Detection rules › Elastic
Potential ClickFix Attack via Base64 Decoded Payload
Detects a ClickFix-style attack where a base64 encoded payload is decoded and piped to a shell interpreter for execution, resulting in a curl download. This technique is commonly used in social engineering attacks where victims are tricked into copying and pasting malicious commands from fake error dialogs or verification prompts.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Execution |
Telemetry coverage
Rule body
[rule]
description = """
Detects a ClickFix-style attack where a base64 encoded payload is decoded and piped to a shell interpreter for
execution, resulting in a curl download. This technique is commonly used in social engineering attacks where victims are
tricked into copying and pasting malicious commands from fake error dialogs or verification prompts.
"""
id = "9dfe40e2-3f4c-47d6-af48-f3459b53d49e"
license = "Elastic License v2"
name = "Potential ClickFix Attack via Base64 Decoded Payload"
os_list = ["macos"]
reference = ["https://blog.sekoia.io/clickfix-tactic-the-phantom-meet/"]
version = "1.0.5"
query = '''
sequence by process.Ext.effective_parent.entity_id with maxspan=10s
[process where event.type == "start" and event.action == "exec" and process.name == "base64" and process.args in ("-d", "-D", "--decode") and
process.Ext.effective_parent.name like~ ("Terminal", "iTerm2", "iTerm", "ghostty",
"alacritty", "wezterm-gui", "Hyper", "kitty",
"WarpTerminal", "stable", "rio", "tabby") and
not process.parent.command_line like ("*/.claude/shell-snapshots/snapshot-bash*", "*__CURSOR_SANDBOX_ENV_RESTORE*")]
[process where event.type == "start" and event.action == "exec" and process.name in ("bash", "sh", "zsh", "Terminal") and process.args_count <= 1]
[process where event.type == "start" and event.action == "exec" and process.name in ("curl", "nscurl") and process.parent.name in ("bash", "sh", "zsh", "Terminal") and
process.parent.command_line in ("bash", "sh", "zsh", "Terminal", "/sbin/launchd") and
not process.command_line like "/usr/bin/curl --version"]
'''
min_endpoint_version = "8.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 2
[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"
[[threat.technique.subtechnique]]
id = "T1566.002"
name = "Spearphishing Link"
reference = "https://attack.mitre.org/techniques/T1566/002/"
[threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1204"
name = "User Execution"
reference = "https://attack.mitre.org/techniques/T1204/"
[[threat.technique.subtechnique]]
id = "T1204.001"
name = "Malicious Link"
reference = "https://attack.mitre.org/techniques/T1204/001/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[internal]
min_endpoint_version = "8.16.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 10s, correlated by process.Ext.effective_parent.entity_id.
Stage 1: process
[process where event.type == "start" and event.action == "exec" and process.name == "base64" and process.args in ("-d", "-D", "--decode") and
process.Ext.effective_parent.name like~ ("Terminal", "iTerm2", "iTerm", "ghostty",
"alacritty", "wezterm-gui", "Hyper", "kitty",
"WarpTerminal", "stable", "rio", "tabby") and
not process.parent.command_line like ("*/.claude/shell-snapshots/snapshot-bash*", "*__CURSOR_SANDBOX_ENV_RESTORE*")]
Stage 2: process
[process where event.type == "start" and event.action == "exec" and process.name in ("bash", "sh", "zsh", "Terminal") and process.args_count <= 1]
Stage 3: process
[process where event.type == "start" and event.action == "exec" and process.name in ("curl", "nscurl") and process.parent.name in ("bash", "sh", "zsh", "Terminal") and
process.parent.command_line in ("bash", "sh", "zsh", "Terminal", "/sbin/launchd") and
not process.command_line like "/usr/bin/curl --version"]
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.parent.command_line | match | /.claude/shell-snapshots/snapshot-bash, __CURSOR_SANDBOX_ENV_RESTORE | excludes:process.parent.command_line field:"process.parent.command_line" value:"/.claude/shell-snapshots/snapshot-bash" field:"process.parent.command_line" value:"__CURSOR_SANDBOX_ENV_RESTORE" |
process.command_line | eq | /usr/bin/curl --version | excludes:process.command_line field:"process.command_line" value:"/usr/bin/curl --version" |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.Ext.effective_parent.name | wildcard |
| field:"process.Ext.effective_parent.name" kind:wildcard |
process.args | in |
| field:"process.args" kind:in |
process.args_count | le |
| field:"process.args_count" kind:le value:"1" |
process.name | eq |
| field:"process_name" kind:eq value:"base64" |
process.name | in |
| field:"process_name" kind:in |
process.parent.command_line | in |
| field:"ParentCommandLine" kind:in |
process.parent.name | in |
| field:"parent_process_name" kind:in |