Detection rules › Elastic

Payload Downloaded via Curl or Wget by Web Server

Source
github.com/elastic/protections-artifacts

This rule detects when a web server downloads a payload via curl or wget. Attackers may exploit RCE or file upload vulnerabilities to download malicious files to web servers to gain/maintain access and to establish a command and control channel.

MITRE ATT&CK coverage

Rule body

[rule]
description = """
This rule detects when a web server downloads a payload via curl or wget. Attackers may exploit RCE or file upload
vulnerabilities to download malicious files to web servers to gain/maintain access and to establish a command and
control channel.
"""
id = "aac41cc3-fc4a-4dea-b8d6-252ded1cb3fc"
license = "Elastic License v2"
name = "Payload Downloaded via Curl or Wget by Web Server"
os_list = ["linux"]
version = "1.0.8"

query = '''
process where event.type == "start" and event.action == "exec" and process.parent.interactive == false and (
  process.parent.name in (
    "nginx", "apache2", "httpd", "caddy", "mongrel_rails", "uwsgi", "daphne", "httpd.worker", "flask",
    "php-cgi", "php-fcgi", "php-cgi.cagefs", "lswsctrl", "varnishd", "uvicorn", "waitress-serve", "starman",
    "frankenphp", "zabbix_server", "asterisk", "sw-engine-fpm"
  ) or
  process.parent.name like ("php-fpm*", "gunicorn*", "*.cgi", "*.fcgi") or
  (
    process.parent.name like "ruby*" and
    process.parent.command_line like~ ("*puma*", "*rails*", "*passenger*") and
    not process.command_line like "*github.com/phusion/passenger/releases/download/release*"
  ) or
  (process.parent.name like "python*" and process.parent.command_line like~ (
    "*hypercorn*", "*flask*", "*uvicorn*", "*django*", "*app.py*", "*server.py*", "*wsgi.py*", "*asgi.py*"
  )) or
  (process.parent.name like "perl*" and process.parent.command_line like~ "*plackup*") or
  (process.parent.name == "node" and process.parent.command_line like~ (
    "*next start*", "*--port*", "*PORT=*", "*HOST=*", "*0.0.0.0*", "*/dist/*.js*", "*/build/*.js*", "*/server/*.js*",
    "*/app/*.js*", "*/apps/*/*.js*", "*/index.js*", "*/main.js*", "*/srv/*", "*/opt/*", "*/var/www/*", "*n8n*"
    ) and
    not (
      process.parent.args like (
        "/opt/cursor-agent/*", "/home/*/*", "/root/*", "/opt/vscode-server/*", "/usr/lib/node_modules/openclaw/dist/index.js",
        "/home/*/.npm-global/lib/node_modules/openclaw/dist/index.js", "openclaw-gateway"
      ) or
      process.parent.executable like "/*/.cursor-server/bin/linux-x64/*/node"
    )
  ) or
  (process.parent.name == "java" and process.parent.args like~ (
    /* Tomcat */
    "org.apache.catalina.startup.Bootstrap", "-Dcatalina.base=*",

    /* Jetty */
    "org.eclipse.jetty.start.Main", "-Djetty.home=*",

    /* WildFly / JBoss */
    "org.jboss.modules.Main", "-Djboss.home.dir=*",

    /* WebLogic */
    "weblogic.Server", "-Dweblogic.Name=*", "*weblogic-launcher.jar*",

    /* WebSphere traditional + Liberty */
    "com.ibm.ws.runtime.WsServer", "com.ibm.ws.kernel.boot.cmdline.Bootstrap",

    /* GlassFish */
    "com.sun.enterprise.glassfish.bootstrap.ASMain",

    /* Resin */
    "com.caucho.server.resin.Resin",

    /* Spring Boot */
    "org.springframework.boot.loader.*",

    /* Quarkus */
    "*quarkus-run.jar*", "io.quarkus.runner.GeneratedMain",

    /* Micronaut */
    "io.micronaut.runtime.Micronaut",

    /* Dropwizard */
    "io.dropwizard.cli.ServerCommand",

    /* Play */
    "play.core.server.ProdServerStart",

    /* Helidon */
    "io.helidon.microprofile.server.Main", "io.helidon.webserver*",

    /* Vert.x */
    "io.vertx.core.Launcher",

    /* Keycloak */
    "org.keycloak*",

    /* Apereo CAS */
    "org.apereo.cas*",

    /* Elasticsearch */
    "org.elasticsearch.bootstrap.Elasticsearch",

    /* Atlassian / Gerrit */
    "com.atlassian.jira.startup.Launcher", "*BitbucketServerLauncher*", "com.google.gerrit.pgm.Daemon",

    /* Solr */
    "*-Dsolr.solr.home=*",

    /* Jenkins */
    "*jenkins.war*"
    )
  )
) and
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "busybox") and
process.args in ("-c", "-cl", "-lc") and
process.command_line like ("*wget *", "*curl *") and
(
  process.command_line regex ".*[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(:[0-9]{1,5})?/.*" or
  process.command_line like ("*http*", "*ftp*")
) and
(
  (
    process.command_line regex~ """.*curl.* \-[a-zA-Z]*[oO]( .+|\-.*)?""" or
    process.command_line like~ ("*curl* --output*", "*curl* --remote-name*")
  ) or
  (
    (
      process.command_line regex~ """.*wget.* \-[a-zA-Z]*O.*""" or
      process.command_line like~ "*wget* --output-document*"
    ) and
  not process.command_line like """*--output-document "-"*"""
  ) or
  process.command_line like ("*|*sh*", "*|*python*", "*|*php*", "*|*perl*", "*|*ruby*", "*|*node*", "*|*lua*", "*|*busybox*") or
  (
    process.command_line like ("*curl *>> /*", "*curl *>>/*", "*curl *> /*", "*curl *>/*", "*wget *>> /*", "*wget *>>/*", "*wget *> /*", "*wget *>/*") and
    not process.command_line like ("*> /dev/null*", "*>/dev/null*", "*curl*/etc/cobra/*/uploads/whatsapp/*")
  )
) and
not (
  process.command_line like (
    "*-O /dev/null*", "*-o /dev/null*", "*wget -qcO --user-agent=*", "*curl * | python -m json.tool",
    "*http://:8008/dacx/fileoperation*", "*http://${host}:9000/api/system/liveness*"
  ) or
  (process.parent.name == "ruby" and process.command_line like "*/tmp/passenger-native-support-*") or
  (process.parent.name == "asterisk" and process.command_line like "*bapi.*.group/v2/call/outgoing*") or
  (process.parent.name == "node" and process.command_line like "*/tmp/.claude/shell-snapshots/*") or
  (process.parent.name == "apache2" and process.command_line like "*/var/www/html/cacti/dati/weathermap/*.jpg")
)
'''

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1190"
name = "Exploit Public-Facing Application"
reference = "https://attack.mitre.org/techniques/T1190/"


[threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"



[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1505"
name = "Server Software Component"
reference = "https://attack.mitre.org/techniques/T1505/"
[[threat.technique.subtechnique]]
id = "T1505.003"
name = "Web Shell"
reference = "https://attack.mitre.org/techniques/T1505/003/"



[threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1210"
name = "Exploitation of Remote Services"
reference = "https://attack.mitre.org/techniques/T1210/"


[threat.tactic]
id = "TA0008"
name = "Lateral Movement"
reference = "https://attack.mitre.org/tactics/TA0008/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1071"
name = "Application Layer Protocol"
reference = "https://attack.mitre.org/techniques/T1071/"


[threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"

[internal]
min_endpoint_version = "8.2.0"

Stages and Predicates

Stage 1: process

process where event.type == "start" and event.action == "exec" and process.parent.interactive == false and (
  process.parent.name in (
    "nginx", "apache2", "httpd", "caddy", "mongrel_rails", "uwsgi", "daphne", "httpd.worker", "flask",
    "php-cgi", "php-fcgi", "php-cgi.cagefs", "lswsctrl", "varnishd", "uvicorn", "waitress-serve", "starman",
    "frankenphp", "zabbix_server", "asterisk", "sw-engine-fpm"
  ) or
  process.parent.name like ("php-fpm*", "gunicorn*", "*.cgi", "*.fcgi") or
  (
    process.parent.name like "ruby*" and
    process.parent.command_line like~ ("*puma*", "*rails*", "*passenger*") and
    not process.command_line like "*github.com/phusion/passenger/releases/download/release*"
  ) or
  (process.parent.name like "python*" and process.parent.command_line like~ (
    "*hypercorn*", "*flask*", "*uvicorn*", "*django*", "*app.py*", "*server.py*", "*wsgi.py*", "*asgi.py*"
  )) or
  (process.parent.name like "perl*" and process.parent.command_line like~ "*plackup*") or
  (process.parent.name == "node" and process.parent.command_line like~ (
    "*next start*", "*--port*", "*PORT=*", "*HOST=*", "*0.0.0.0*", "*/dist/*.js*", "*/build/*.js*", "*/server/*.js*",
    "*/app/*.js*", "*/apps/*/*.js*", "*/index.js*", "*/main.js*", "*/srv/*", "*/opt/*", "*/var/www/*", "*n8n*"
    ) and
    not (
      process.parent.args like (
        "/opt/cursor-agent/*", "/home/*/*", "/root/*", "/opt/vscode-server/*", "/usr/lib/node_modules/openclaw/dist/index.js",
        "/home/*/.npm-global/lib/node_modules/openclaw/dist/index.js", "openclaw-gateway"
      ) or
      process.parent.executable like "/*/.cursor-server/bin/linux-x64/*/node"
    )
  ) or
  (process.parent.name == "java" and process.parent.args like~ (
    "org.apache.catalina.startup.Bootstrap", "-Dcatalina.base=*",
    "org.eclipse.jetty.start.Main", "-Djetty.home=*",
    "org.jboss.modules.Main", "-Djboss.home.dir=*",
    "weblogic.Server", "-Dweblogic.Name=*", "*weblogic-launcher.jar*",
    "com.ibm.ws.runtime.WsServer", "com.ibm.ws.kernel.boot.cmdline.Bootstrap",
    "com.sun.enterprise.glassfish.bootstrap.ASMain",
    "com.caucho.server.resin.Resin",
    "org.springframework.boot.loader.*",
    "*quarkus-run.jar*", "io.quarkus.runner.GeneratedMain",
    "io.micronaut.runtime.Micronaut",
    "io.dropwizard.cli.ServerCommand",
    "play.core.server.ProdServerStart",
    "io.helidon.microprofile.server.Main", "io.helidon.webserver*",
    "io.vertx.core.Launcher",
    "org.keycloak*",
    "org.apereo.cas*",
    "org.elasticsearch.bootstrap.Elasticsearch",
    "com.atlassian.jira.startup.Launcher", "*BitbucketServerLauncher*", "com.google.gerrit.pgm.Daemon",
    "*-Dsolr.solr.home=*",
    "*jenkins.war*"
    )
  )
) and
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "busybox") and
process.args in ("-c", "-cl", "-lc") and
process.command_line like ("*wget *", "*curl *") and
(
  process.command_line regex ".*[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(:[0-9]{1,5})?/.*" or
  process.command_line like ("*http*", "*ftp*")
) and
(
  (
    process.command_line regex~ """.*curl.* \-[a-zA-Z]*[oO]( .+|\-.*)?""" or
    process.command_line like~ ("*curl* --output*", "*curl* --remote-name*")
  ) or
  (
    (
      process.command_line regex~ """.*wget.* \-[a-zA-Z]*O.*""" or
      process.command_line like~ "*wget* --output-document*"
    ) and
  not process.command_line like """*--output-document "-"*"""
  ) or
  process.command_line like ("*|*sh*", "*|*python*", "*|*php*", "*|*perl*", "*|*ruby*", "*|*node*", "*|*lua*", "*|*busybox*") or
  (
    process.command_line like ("*curl *>> /*", "*curl *>>/*", "*curl *> /*", "*curl *>/*", "*wget *>> /*", "*wget *>>/*", "*wget *> /*", "*wget *>/*") and
    not process.command_line like ("*> /dev/null*", "*>/dev/null*", "*curl*/etc/cobra/*/uploads/whatsapp/*")
  )
) and
not (
  process.command_line like (
    "*-O /dev/null*", "*-o /dev/null*", "*wget -qcO --user-agent=*", "*curl * | python -m json.tool",
    "*http://:8008/dacx/fileoperation*", "*http://${host}:9000/api/system/liveness*"
  ) or
  (process.parent.name == "ruby" and process.command_line like "*/tmp/passenger-native-support-*") or
  (process.parent.name == "asterisk" and process.command_line like "*bapi.*.group/v2/call/outgoing*") or
  (process.parent.name == "node" and process.command_line like "*/tmp/.claude/shell-snapshots/*") or
  (process.parent.name == "apache2" and process.command_line like "*/var/www/html/cacti/dati/weathermap/*.jpg")
)

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.command_linematch/tmp/.claude/shell-snapshots/excludes:process.command_line field:"process.command_line" value:"/tmp/.claude/shell-snapshots/"
process.parent.nameeqnodeexcludes:process.parent.name field:"process.parent.name" value:"node"
process.command_linematch/tmp/passenger-native-support-excludes:process.command_line field:"process.command_line" value:"/tmp/passenger-native-support-"
process.parent.nameeqrubyexcludes:process.parent.name field:"process.parent.name" value:"ruby"
process.command_linewildcard*/var/www/html/cacti/dati/weathermap/*.jpgexcludes:process.command_line field:"process.command_line" value:"*/var/www/html/cacti/dati/weathermap/*.jpg"
process.parent.nameeqapache2excludes:process.parent.name field:"process.parent.name" value:"apache2"
process.command_linewildcard*bapi.*.group/v2/call/outgoing*excludes:process.command_line field:"process.command_line" value:"*bapi.*.group/v2/call/outgoing*"
process.parent.nameeqasteriskexcludes:process.parent.name field:"process.parent.name" value:"asterisk"
process.command_linewildcard*-O /dev/null*, *-o /dev/null*, *wget -qcO --user-agent=*, *curl * | python -m json.tool, *http://:8008/dacx/fileoperation*, *http://${host}:9000/api/system/liveness*excludes:process.command_line

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec
field:"EventType" kind:eq value:"exec"
event.typeeq
  • start
field:"event.type" kind:eq value:"start"
process.argsin
  • -c
  • -cl
  • -lc
field:"process.args" kind:in
process.command_lineregex_match
  • .*[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}(:[0-9]{1,5})?/.*
  • .*curl.* \-[a-zA-Z]*[oO]( .+|\-.*)?
  • .*wget.* \-[a-zA-Z]*O.*
field:"CommandLine" kind:regex_match
process.command_linewildcard
  • *curl *
  • *curl *> /*
  • *curl *>/*
  • *curl *>> /*
  • *curl *>>/*
  • *curl* --output*
  • *curl* --remote-name*
  • *ftp*
  • *http*
  • *wget *
  • *wget *> /*
  • *wget *>/*
  • *wget *>> /*
  • *wget *>>/*
  • *wget* --output-document*
  • *|*busybox*
  • *|*lua*
  • *|*node*
  • *|*perl*
  • *|*php*
  • *|*python*
  • *|*ruby*
  • *|*sh*
field:"CommandLine" kind:wildcard
process.namein
  • bash
  • busybox
  • csh
  • dash
  • fish
  • ksh
  • sh
  • tcsh
  • zsh
field:"process_name" kind:in
process.parent.argswildcard
  • *-Dsolr.solr.home=*
  • *BitbucketServerLauncher*
  • *jenkins.war*
  • *quarkus-run.jar*
  • *weblogic-launcher.jar*
  • -Dcatalina.base=*
  • -Djboss.home.dir=*
  • -Djetty.home=*
  • -Dweblogic.Name=*
  • com.atlassian.jira.startup.Launcher
  • com.caucho.server.resin.Resin
  • com.google.gerrit.pgm.Daemon
  • com.ibm.ws.kernel.boot.cmdline.Bootstrap
  • com.ibm.ws.runtime.WsServer
  • com.sun.enterprise.glassfish.bootstrap.ASMain
  • io.dropwizard.cli.ServerCommand
  • io.helidon.microprofile.server.Main
  • io.helidon.webserver*
  • io.micronaut.runtime.Micronaut
  • io.quarkus.runner.GeneratedMain
  • io.vertx.core.Launcher
  • org.apache.catalina.startup.Bootstrap
  • org.apereo.cas*
  • org.eclipse.jetty.start.Main
  • org.elasticsearch.bootstrap.Elasticsearch
  • org.jboss.modules.Main
  • org.keycloak*
  • org.springframework.boot.loader.*
  • play.core.server.ProdServerStart
  • weblogic.Server
field:"process.parent.args" kind:wildcard
process.parent.command_linewildcard
  • *--port*
  • */app/*.js*
  • */apps/*/*.js*
  • */build/*.js*
  • */dist/*.js*
  • */index.js*
  • */main.js*
  • */opt/*
  • */server/*.js*
  • */srv/*
  • */var/www/*
  • *0.0.0.0*
  • *HOST=*
  • *PORT=*
  • *app.py*
  • *asgi.py*
  • *django*
  • *flask*
  • *hypercorn*
  • *n8n*
  • *next start*
  • *passenger*
  • *plackup*
  • *puma*
  • *rails*
  • *server.py*
  • *uvicorn*
  • *wsgi.py*
field:"ParentCommandLine" kind:wildcard
process.parent.interactiveeq
  • false transforms: boolean
field:"process.parent.interactive" kind:eq value:"false"
process.parent.nameeq
  • java
  • node
field:"parent_process_name" kind:eq
process.parent.namein
  • apache2
  • asterisk
  • caddy
  • daphne
  • flask
  • frankenphp
  • httpd
  • httpd.worker
  • lswsctrl
  • mongrel_rails
  • nginx
  • php-cgi
  • php-cgi.cagefs
  • php-fcgi
  • starman
  • sw-engine-fpm
  • uvicorn
  • uwsgi
  • varnishd
  • waitress-serve
  • zabbix_server
field:"parent_process_name" kind:in
process.parent.namewildcard
  • *.cgi
  • *.fcgi
  • gunicorn*
  • perl*
  • php-fpm*
  • python*
  • ruby*
field:"parent_process_name" kind:wildcard