Detection rules › Elastic
Potential Data Exfiltration via Curl
Detects the use of curl to upload an archived file to an internet server. Threat actors often will collect data on a system and compress it in an archive file before exfiltrating the file back to their C2 server for review. Many threat actors have been seen utilizing curl to upload this archive file with the collected data to do this. Use of curl in this way while not inherently malicious should be considered highly abnormal and suspicious activity.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Telemetry coverage
Rule body
[rule]
description = """
Detects the use of curl to upload an archived file to an internet server. Threat actors often will collect data on a
system and compress it in an archive file before exfiltrating the file back to their C2 server for review. Many threat
actors have been seen utilizing curl to upload this archive file with the collected data to do this. Use of curl in this
way while not inherently malicious should be considered highly abnormal and suspicious activity.
"""
id = "192ec591-1d00-4c16-a717-8a7481038d23"
license = "Elastic License v2"
name = "Potential Data Exfiltration via Curl"
os_list = ["macos"]
reference = [
"https://everything.curl.dev/usingcurl/uploads",
"https://objective-see.org/blog/blog_0x71.html#-sentinelsneak",
"https://objective-see.org/blog/blog_0x66.html",
]
version = "1.0.40"
query = '''
sequence by process.entity_id with maxspan=15s
[process where event.type == "start" and event.action == "exec" and process.name == "curl" and
process.args like~ ("-F", "-T", "-d", "--data*") and
process.args like~ ("*@*.zip", "*@*.gz", "*@*.tgz", "b64=@*") and
process.args like~ "http*" and
(process.parent.name like~ ("osascript", "python*", "node", "ruby", "bash", "sh", "zsh", "perl") or (process.parent.code_signature.trusted == false or process.parent.code_signature.exists == false)) and
not process.args like ("Authorization*", "PRIVATE-TOKEN*") and
not process.parent.command_line like "/bin/bash --init-file /Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/workbench/contrib/terminal/common/scripts/shellIntegration-bash.sh" and
not process.Ext.effective_parent.executable like ("/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon",
"/Applications/Support.app/Contents/MacOS/Support")]
[network where event.type == "start" and not destination.domain : ("*.cloud.es.io", "*.elastic-cloud.com")]
'''
min_endpoint_version = "8.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1048"
name = "Exfiltration Over Alternative Protocol"
reference = "https://attack.mitre.org/techniques/T1048/"
[threat.tactic]
id = "TA0010"
name = "Exfiltration"
reference = "https://attack.mitre.org/tactics/TA0010/"
[internal]
min_endpoint_version = "8.16.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 15s, correlated by process.entity_id.
Stage 1: process
[process where event.type == "start" and event.action == "exec" and process.name == "curl" and
process.args like~ ("-F", "-T", "-d", "--data*") and
process.args like~ ("*@*.zip", "*@*.gz", "*@*.tgz", "b64=@*") and
process.args like~ "http*" and
(process.parent.name like~ ("osascript", "python*", "node", "ruby", "bash", "sh", "zsh", "perl") or (process.parent.code_signature.trusted == false or process.parent.code_signature.exists == false)) and
not process.args like ("Authorization*", "PRIVATE-TOKEN*") and
not process.parent.command_line like "/bin/bash --init-file /Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/workbench/contrib/terminal/common/scripts/shellIntegration-bash.sh" and
not process.Ext.effective_parent.executable like ("/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon",
"/Applications/Support.app/Contents/MacOS/Support")]
Stage 2: network
[network where event.type == "start" and not destination.domain : ("*.cloud.es.io", "*.elastic-cloud.com")]
Exclusions
The rule actively suppresses these predicates.
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.args | wildcard |
| field:"process.args" kind:wildcard |
process.name | eq |
| field:"process_name" kind:eq value:"curl" |
process.parent.code_signature.exists | eq |
| field:"process.parent.code_signature.exists" kind:eq value:"false" |
process.parent.code_signature.trusted | eq |
| field:"process.parent.code_signature.trusted" kind:eq value:"false" |
process.parent.name | wildcard |
| field:"parent_process_name" kind:wildcard |