Detection rules › Elastic

Ingress Tool Transfer via CURL

Source
github.com/elastic/protections-artifacts

Identifies downloads of remote content using Windows CURL executable. This tactic may be indicative of malicious activity where malware is downloading second stage payloads using built-in Windows programs.

MITRE ATT&CK coverage

TacticTechniques
Command & Control

Rule body

[rule]
description = """
Identifies downloads of remote content using Windows CURL executable. This tactic may be indicative of malicious
activity where malware is downloading second stage payloads using built-in Windows programs.
"""
id = "336ada1c-69f8-46e8-bdd2-790c85429696"
license = "Elastic License v2"
name = "Ingress Tool Transfer via CURL"
os_list = ["windows"]
version = "1.0.34"

query = '''
process where event.action == "start" and

 /* renamed curl or curl running from normal users writable folders are very noisy */
 process.executable : ("?:\\Windows\\System32\\curl.exe", "?:\\Windows\\SysWOW64\\curl.exe") and

 (
  (process.args_count == 2 and process.command_line : "*http*" and process.parent.name : "cmd.exe" and
   process.parent.command_line : "*  /c curl*") or

  (process.args : ("-o", "--output") and
   (
    (process.parent.name : ("powershell.exe", "mshta.exe", "wscript.exe", "cscript.exe", "rundll32.exe", "regsvr32.exe") and
     process.parent.args_count >= 2) or

     (process.parent.name : "cmd.exe" and process.parent.command_line : ("*curl*", "*^*^*^*")) or

     descendant of [process where process.name : ("winword.exe", "excel.exe", "powerpnt.exe", "wscript.exe")] or

     process.parent.executable : ("?:\\Users\\Public\\*", "?:\\Users\\*\\AppData\\*", "?:\\ProgramData\\*")
   ))
  ) and
  /* lot of legit curl execution via custom bat scripts or interactively via cmd or powershell */
  not (process.parent.name : "cmd.exe" and process.parent.args :( "*.bat*", "\\\\*.jpg", "curl -L -o \\\\*", "config_%c%a%b_%d%e%f.xml")) and
  not (process.parent.name : ("cmd.exe", "powershell.exe") and process.parent.args_count == 1) and
  not process.parent.executable : "?:\\Users\\*\\AppData\\Local\\Temp\\nsc*.tmp\\*.exe" and
  not process.command_line : ("*curl -o \\\\.\\nul -v -I -L -s --connect-timeout*", "*http://127.0.0.1:*", "*http://localhost:*") and
  not process.args : ("https://mirror.init7.net/ctan/systems*", "http://localhost:*",
                      "https://*.ctan.org*", "texlive/curl", "http*.local/*",
                      "http://control.firstvoucher.com/api/build/*zip",
                      "https://blackhole.blob.core.windows.net/*",
                      "https://*.cw-onlineupdate.de/*",
                      "https://gitea.*.prod/*",
                      "https://dl.google.com/*") and

  /* avoid breaking privileged install */
  not user.id : "S-1-5-18" and
  not (process.parent.name : "cmd.exe" and process.parent.command_line like~ "*oi-vscode-server*run.app*") and
  not (process.parent.name : "cmd.exe" and process.parent.command_line like~ "*nexuspayables.com*showImage.php*") and
  not (process.parent.command_line like~ "*VoicemodInstaller*" and process.parent.name like~ "VoicemodInstaller*")
'''

min_endpoint_version = "7.15.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0

[[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 = "7.15.0"

Stages and Predicates

Stage 1: process

process where event.action == "start" and
 process.executable : ("?:\\Windows\\System32\\curl.exe", "?:\\Windows\\SysWOW64\\curl.exe") and
 (
  (process.args_count == 2 and process.command_line : "*http*" and process.parent.name : "cmd.exe" and
   process.parent.command_line : "*  /c curl*") or
  (process.args : ("-o", "--output") and
   (
    (process.parent.name : ("powershell.exe", "mshta.exe", "wscript.exe", "cscript.exe", "rundll32.exe", "regsvr32.exe") and
     process.parent.args_count >= 2) or
     (process.parent.name : "cmd.exe" and process.parent.command_line : ("*curl*", "*^*^*^*")) or
     descendant of [process where process.name : ("winword.exe", "excel.exe", "powerpnt.exe", "wscript.exe")] or
     process.parent.executable : ("?:\\Users\\Public\\*", "?:\\Users\\*\\AppData\\*", "?:\\ProgramData\\*")
   ))
  ) and
  not (process.parent.name : "cmd.exe" and process.parent.args :( "*.bat*", "\\\\*.jpg", "curl -L -o \\\\*", "config_%c%a%b_%d%e%f.xml")) and
  not (process.parent.name : ("cmd.exe", "powershell.exe") and process.parent.args_count == 1) and
  not process.parent.executable : "?:\\Users\\*\\AppData\\Local\\Temp\\nsc*.tmp\\*.exe" and
  not process.command_line : ("*curl -o \\\\.\\nul -v -I -L -s --connect-timeout*", "*http://127.0.0.1:*", "*http://localhost:*") and
  not process.args : ("https://mirror.init7.net/ctan/systems*", "http://localhost:*",
                      "https://*.ctan.org*", "texlive/curl", "http*.local/*",
                      "http://control.firstvoucher.com/api/build/*zip",
                      "https://blackhole.blob.core.windows.net/*",
                      "https://*.cw-onlineupdate.de/*",
                      "https://gitea.*.prod/*",
                      "https://dl.google.com/*") and
  not user.id : "S-1-5-18" and
  not (process.parent.name : "cmd.exe" and process.parent.command_line like~ "*oi-vscode-server*run.app*") and
  not (process.parent.name : "cmd.exe" and process.parent.command_line like~ "*nexuspayables.com*showImage.php*") and
  not (process.parent.command_line like~ "*VoicemodInstaller*" and process.parent.name like~ "VoicemodInstaller*")

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.parent.argswildcard*.bat*, \\*.jpg, curl -L -o \\*, config_%c%a%b_%d%e%f.xmlexcludes:process.parent.args
process.parent.nameeqcmd.exeexcludes:process.parent.name field:"process.parent.name" value:"cmd.exe"
process.parent.args_counteq1excludes:process.parent.args_count field:"process.parent.args_count" value:"1"
process.parent.nameeqcmd.exe, powershell.exeexcludes:process.parent.name field:"process.parent.name" value:"cmd.exe" field:"process.parent.name" value:"powershell.exe"
process.parent.command_linematchVoicemodInstallerexcludes:process.parent.command_line field:"process.parent.command_line" value:"VoicemodInstaller"
process.parent.namestarts_withVoicemodInstallerexcludes:process.parent.name field:"process.parent.name" value:"VoicemodInstaller"
process.parent.command_linewildcard*nexuspayables.com*showImage.php*excludes:process.parent.command_line field:"process.parent.command_line" value:"*nexuspayables.com*showImage.php*"
process.parent.command_linewildcard*oi-vscode-server*run.app*excludes:process.parent.command_line field:"process.parent.command_line" value:"*oi-vscode-server*run.app*"
process.argswildcardhttps://mirror.init7.net/ctan/systems*, http://localhost:*, https://*.ctan.org*, texlive/curl, http*.local/*, http://control.firstvoucher.com/api/build/*zip, https://blackhole.blob.core.windows.net/*, https://*.cw-onlineupdate.de/*, https://gitea.*.prod/*, https://dl.google.com/*excludes:process.args
process.command_linematchcurl -o \\.\nul -v -I -L -s --connect-timeout, http://127.0.0.1:, http://localhost:excludes:process.command_line field:"process.command_line" value:"curl -o \\.\nul -v -I -L -s --connect-timeout" field:"process.command_line" value:"http://127.0.0.1:" field:"process.command_line" value:"http://localhost:"
process.parent.executablewildcard?:\Users\*\AppData\Local\Temp\nsc*.tmp\*.exeexcludes:process.parent.executable field:"process.parent.executable" value:"?:\Users\*\AppData\Local\Temp\nsc*.tmp\*.exe"
user.ideqS-1-5-18excludes:user.id field:"user.id" value:"S-1-5-18"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • start corpus 391 (elastic 391)
field:"EventType" kind:eq value:"start"
process.argswildcard
  • --output corpus 2 (elastic 2)
  • -o corpus 7 (elastic 7)
field:"process.args" kind:wildcard
process.args_counteq
  • 2 transforms: number corpus 37 (elastic 37)
field:"process.args_count" kind:eq value:"2"
process.command_linewildcard
  • *http* corpus 52 (sigma 34, elastic 15, chronicle 2, splunk 1)
field:"CommandLine" kind:wildcard value:"*http*"
process.executablewildcard
  • ?:\Windows\SysWOW64\curl.exe corpus 2 (elastic 2)
  • ?:\Windows\System32\curl.exe corpus 2 (elastic 2)
field:"Image" kind:wildcard
process.parent.args_countge
  • 2 transforms: number corpus 4 (elastic 4)
field:"process.parent.args_count" kind:ge value:"2"
process.parent.command_linewildcard
  • * /c curl*
  • *^*^*^*
  • *curl*
field:"ParentCommandLine" kind:wildcard
process.parent.executablewildcard
  • ?:\ProgramData\* corpus 2 (elastic 2)
  • ?:\Users\*\AppData\* corpus 4 (elastic 4)
  • ?:\Users\Public\*
field:"ParentImage" kind:wildcard
process.parent.namewildcard
  • cmd.exe corpus 36 (elastic 31, splunk 4, kusto 1)
  • cscript.exe corpus 16 (elastic 15, splunk 1)
  • mshta.exe corpus 24 (elastic 22, splunk 2)
  • powershell.exe corpus 39 (elastic 36, kusto 2, splunk 1)
  • regsvr32.exe corpus 13 (elastic 13)
  • rundll32.exe corpus 20 (elastic 20)
  • wscript.exe corpus 24 (elastic 23, splunk 1)
field:"parent_process_name" kind:wildcard