Curl or Wget Egress Network Connection via LoLBin

This rule detects the execution of curl or wget binaries through a GTFOBin (living-off-the-land) technique in Linux environments. Attackers may exploit these utilities to download and execute malicious files from the internet while attempting to evade detection. The rule specifically targets binaries that are capable of executing shell commands directly from the proxied binary, rather than just spawning a shell.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2025/11/20"
  3integration = ["endpoint"]
  4maturity = "production"
  5updated_date = "2025/11/24"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10This rule detects the execution of curl or wget binaries through a GTFOBin (living-off-the-land) technique in Linux
 11environments. Attackers may exploit these utilities to download and execute malicious files from the internet while
 12attempting to evade detection. The rule specifically targets binaries that are capable of executing shell commands
 13directly from the proxied binary, rather than just spawning a shell.
 14"""
 15from = "now-9m"
 16index = ["logs-endpoint.events.process*", "logs-endpoint.events.network*"]
 17language = "eql"
 18license = "Elastic License v2"
 19name = "Curl or Wget Egress Network Connection via LoLBin"
 20note = """ ## Triage and analysis
 21
 22> **Disclaimer**:
 23> 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.
 24
 25### Investigating Curl or Wget Egress Network Connection via LoLBin
 26
 27This detects outbound connections from curl or wget when they are launched via living-off-the-land binaries that can execute shell commands, signaling proxy execution to mask activity. It matters because attackers abuse trusted utilities to fetch payloads, stage command-and-control, or exfiltrate while evading simple controls. Example: an attacker uses awk or busybox to run curl to an external host, downloads a script into /tmp, pipes it to sh, or saves a binary and runs it under the proxy’s context.
 28
 29### Possible investigation steps
 30
 31- Pull the full process tree around the event and review the parent LoLBin’s command line for signs of proxy execution such as pipelines to a shell, write-to-file flags (-o/-O), exfil options (--data/--upload-file), or TLS bypass (-k), noting working directory and effective user for context.
 32- Identify any paths or filenames used by the transfer and inspect the filesystem for newly created or modified artifacts in temp locations, recording hashes, timestamps, permission changes (e.g., chmod +x), and any immediate execution or persistence actions.
 33- Correlate the outbound destination with threat intelligence and internal allowlists, examine DNS/SNI/certificate details, and flag unusual ports or use of proxies/TOR that suggest evasion.
 34- Validate whether the parent LoLBin and its execution path align with legitimate software or maintenance workflows on the host, and broaden the search for similar executions across hosts within the same timeframe.
 35- Hunt for follow-on activity including new listeners, reverse shells, additional outbound beacons, or other GTFOBins invoking curl/wget, and tie findings back to the same domains/IPs or dropped filesystem artifacts.
 36
 37### False positive analysis
 38
 39- During legitimate dependency installation or build workflows, pip/npm/gem/bundler/yarn may run post-install hooks that invoke curl/wget to fetch supplemental files from public mirrors, with the package manager as the parent process.
 40- Operations or maintenance tasks may use watch/busybox/run-parts/awk to proxy execution of curl/wget for external availability checks or bootstrap downloads in init scripts, producing short-lived egress that matches the LoLBin-parent pattern.
 41
 42### Response and remediation
 43
 44- Immediately isolate the affected Linux host or apply an outbound block, terminate active curl/wget and their invoking LoLBins (e.g., awk, busybox, run-parts), and add temporary firewall/DNS rules to deny the contacted domain/IP and port.
 45- Enumerate and delete files fetched via curl/wget (-o/-O) in /tmp, /var/tmp, /dev/shm, and user home (including scripts piped to sh), remove any persistence added (new cron entries, systemd units, rc.local edits), and record hashes/paths for evidence.
 46- Rotate credentials or tokens exposed via -u/--header or ~/.netrc, purge malicious proxy settings and config files (http_proxy/https_proxy environment, ~/.wgetrc, ~/.curlrc), and revoke SSH keys or cookies discovered alongside the downloads.
 47- Restore the system by reimaging or reinstalling if tampering is suspected, re-enable egress only after validation, verify application functionality, and re-enroll the endpoint with EDR while limiting curl/wget usage to approved service accounts.
 48- Escalate to incident response if curl/wget is piped to a shell (e.g., curl https://... | sh), a downloaded binary is made executable and run (chmod +x followed by execution), the destination matches known malicious infrastructure, or torify/torsocks/proxy chaining is used.
 49- Harden by mounting /tmp, /var/tmp, and /dev/shm with noexec/nosuid/nodev, enforcing AppArmor/SELinux to restrict curl/wget network access and file writes, constraining GTFOBins from spawning shells, and requiring egress via a proxy allowlist with TLS validation (disallow --insecure/-k).
 50"""
 51references = ["https://gtfobins.github.io/#+shell"]
 52risk_score = 47
 53rule_id = "d1ee711a-a3ba-4d73-b5ab-84cab5b37fb3"
 54setup = """## Setup
 55
 56This rule requires data coming in from Elastic Defend.
 57
 58### Elastic Defend Integration Setup
 59Elastic 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.
 60
 61#### Prerequisite Requirements:
 62- Fleet is required for Elastic Defend.
 63- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
 64
 65#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
 66- Go to the Kibana home page and click "Add integrations".
 67- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
 68- Click "Add Elastic Defend".
 69- Configure the integration name and optionally add a description.
 70- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
 71- 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).
 72- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
 73- 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.
 74For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
 75- Click "Save and Continue".
 76- 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.
 77For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
 78"""
 79severity = "medium"
 80tags = [
 81    "Domain: Endpoint",
 82    "OS: Linux",
 83    "Use Case: Threat Detection",
 84    "Tactic: Defense Evasion",
 85    "Tactic: Execution",
 86    "Tactic: Command and Control",
 87    "Tactic: Exfiltration",
 88    "Data Source: Elastic Defend",
 89    "Resources: Investigation Guide",
 90]
 91type = "eql"
 92query = '''
 93sequence with maxspan=3s
 94  [process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.name in (
 95     "aa-exec", "aoss", "awk", "run-parts", "bundle", "bundler", "busctl", "busybox", "byebug", "c89", "c99", "cabal",
 96     "capsh", "cdist", "certbot", "check_by_ssh", "choom", "cobc", "cowsay", "cowthink", "cpio", "cpulimit", "csvtool",
 97     "dc", "distcc", "easy_install", "emacs", "enscript", "expect", "find", "flock", "gawk", "gcc", "gdb", "gem",
 98     "genie", "ghc", "ghci", "gimp", "grc", "gtester", "ionice", "irb", "jjs", "jrunscript", "knife", "latex",
 99     "latexmk", "lftp", "logsave", "ltrace", "mail", "mawk", "msgfilter", "multitime", "mysql", "nawk", "neofetch",
100     "nice", "nohup", "npm", "nroff", "nsenter", "octave", "openvpn", "pandoc", "pdb", "pdflatex", "pdftex", "perf",
101     "pexec", "pip", "rake", "rc", "rlwrap", "rpmdb", "rpmquery", "rpmverify", "rsync", "rtorrent", "runscript",
102     "rview", "rvim", "script", "scrot", "sed", "service", "setarch", "setlock", "sg", "socat", "softlimit", "split",
103     "sqlite3", "sqlmap", "sshpass", "start-stop-daemon", "stdbuf", "tar", "taskset",
104     "tasksh", "tex", "time", "tmate", "torify", "torsocks", "tshark", "valgrind", "vi", "view",
105     "vim", "vimdiff", "watch", "xdg-user-dir", "xdotool", "xelatex", "xetex", "yarn", "zip", "zypper"
106   ) and not (
107     process.executable == "/tmp/newroot/unshare" or
108     process.parent.args in (
109       "/etc/.agent/server_agent.sh", "/nessus/update2.sh", "/etc/cron.daily/spamassassin", "/etc/cron.daily/rkhunter",
110       "buildkit-runc", "/usr/sbin/spamassassin-maint"
111     ) or
112     process.parent.executable like (
113       "/usr/local/bin/fail2ban_cluster.sh", "/script/downloadArtifacts.sh", "/etc/cron.daily/rkhunter",
114       "/usr/bin/bbb-conf", "/usr/sbin/sos", "/usr/bin/make", "/var/lib/amagent/*", "/etc/cron.daily/spamassassin",
115       "/usr/lib/cron/run-crons", "/usr/sbin/spamassassin-maint", "/usr/sbin/oracle-libs-update"
116     ) or
117     process.parent.name in ("rkhunter", "vivaldi-stable.postinst", "runc") or
118     process.parent.command_line == "runc init" or
119     process.parent.command_line like "/home/*/bin/DownloadExchangeFiles_mcx*" or
120     process.command_line in (
121       "nice -10 /opt/aws/discovery/update", "xargs -n 1 curl -o lpsc -L", "/usr/bin/ruby /usr/bin/rake run:server_hooks",
122       "nohup ./update2.sh"
123     ) or
124     process.parent.command_line in ("/bin/sh -c nice -n 15 $HOME/bin/cron.pl > /dev/null 2>&1", "/bin/sh /etc/cron.daily/rkhunter") or
125     process.command_line like ("*/home/linuxbrew/.linuxbrew/*", "*Homebrew*", "*webhook*") or
126     process.args like ("/usr/lib/jvm/*", "/root/.forge/provision-*.sh", "/usr/src/ucrm/scripts/update-certificates.sh", "/etc/periodic/weekly/update_mmdb.sh") or
127     (process.name == "nohup" and process.command_line like "nohup /usr/*/*.sh") or
128     (process.name == "julia" and process.parent.name == "julia")
129   )
130  ] by process.entity_id
131  [network where host.os.type == "linux" and event.type == "start" and event.action == "connection_attempted" and
132   process.name in ("wget", "curl") and not (
133     destination.ip == null or destination.ip == "0.0.0.0" or cidrmatch(
134       destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29",
135       "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24",
136       "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10",
137       "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1", "FE80::/10",
138       "FF00::/8"
139     )
140   )
141  ] by process.parent.entity_id
142'''
143
144[[rule.threat]]
145framework = "MITRE ATT&CK"
146
147  [rule.threat.tactic]
148  name = "Defense Evasion"
149  id = "TA0005"
150  reference = "https://attack.mitre.org/tactics/TA0005/"
151
152    [[rule.threat.technique]]
153    id = "T1218"
154    name = "System Binary Proxy Execution"
155    reference = "https://attack.mitre.org/techniques/T1218/"
156
157[[rule.threat]]
158framework = "MITRE ATT&CK"
159
160  [rule.threat.tactic]
161  name = "Execution"
162  id = "TA0002"
163  reference = "https://attack.mitre.org/tactics/TA0002/"
164
165  [[rule.threat.technique]]
166  id = "T1059"
167  name = "Command and Scripting Interpreter"
168  reference = "https://attack.mitre.org/techniques/T1059/"
169
170    [[rule.threat.technique.subtechnique]]
171    name = "Unix Shell"
172    id = "T1059.004"
173    reference = "https://attack.mitre.org/techniques/T1059/004/"
174
175[[rule.threat]]
176framework = "MITRE ATT&CK"
177
178  [rule.threat.tactic]
179  id = "TA0011"
180  name = "Command and Control"
181  reference = "https://attack.mitre.org/tactics/TA0011/"
182
183[[rule.threat]]
184framework = "MITRE ATT&CK"
185
186  [rule.threat.tactic]
187  id = "TA0010"
188  name = "Exfiltration"
189  reference = "https://attack.mitre.org/tactics/TA0010/"

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 Egress Network Connection via LoLBin

This detects outbound connections from curl or wget when they are launched via living-off-the-land binaries that can execute shell commands, signaling proxy execution to mask activity. It matters because attackers abuse trusted utilities to fetch payloads, stage command-and-control, or exfiltrate while evading simple controls. Example: an attacker uses awk or busybox to run curl to an external host, downloads a script into /tmp, pipes it to sh, or saves a binary and runs it under the proxy’s context.

Possible investigation steps

  • Pull the full process tree around the event and review the parent LoLBin’s command line for signs of proxy execution such as pipelines to a shell, write-to-file flags (-o/-O), exfil options (--data/--upload-file), or TLS bypass (-k), noting working directory and effective user for context.
  • Identify any paths or filenames used by the transfer and inspect the filesystem for newly created or modified artifacts in temp locations, recording hashes, timestamps, permission changes (e.g., chmod +x), and any immediate execution or persistence actions.
  • Correlate the outbound destination with threat intelligence and internal allowlists, examine DNS/SNI/certificate details, and flag unusual ports or use of proxies/TOR that suggest evasion.
  • Validate whether the parent LoLBin and its execution path align with legitimate software or maintenance workflows on the host, and broaden the search for similar executions across hosts within the same timeframe.
  • Hunt for follow-on activity including new listeners, reverse shells, additional outbound beacons, or other GTFOBins invoking curl/wget, and tie findings back to the same domains/IPs or dropped filesystem artifacts.

False positive analysis

  • During legitimate dependency installation or build workflows, pip/npm/gem/bundler/yarn may run post-install hooks that invoke curl/wget to fetch supplemental files from public mirrors, with the package manager as the parent process.
  • Operations or maintenance tasks may use watch/busybox/run-parts/awk to proxy execution of curl/wget for external availability checks or bootstrap downloads in init scripts, producing short-lived egress that matches the LoLBin-parent pattern.

Response and remediation

  • Immediately isolate the affected Linux host or apply an outbound block, terminate active curl/wget and their invoking LoLBins (e.g., awk, busybox, run-parts), and add temporary firewall/DNS rules to deny the contacted domain/IP and port.
  • Enumerate and delete files fetched via curl/wget (-o/-O) in /tmp, /var/tmp, /dev/shm, and user home (including scripts piped to sh), remove any persistence added (new cron entries, systemd units, rc.local edits), and record hashes/paths for evidence.
  • Rotate credentials or tokens exposed via -u/--header or ~/.netrc, purge malicious proxy settings and config files (http_proxy/https_proxy environment, ~/.wgetrc, ~/.curlrc), and revoke SSH keys or cookies discovered alongside the downloads.
  • Restore the system by reimaging or reinstalling if tampering is suspected, re-enable egress only after validation, verify application functionality, and re-enroll the endpoint with EDR while limiting curl/wget usage to approved service accounts.
  • Escalate to incident response if curl/wget is piped to a shell (e.g., curl https://... | sh), a downloaded binary is made executable and run (chmod +x followed by execution), the destination matches known malicious infrastructure, or torify/torsocks/proxy chaining is used.
  • Harden by mounting /tmp, /var/tmp, and /dev/shm with noexec/nosuid/nodev, enforcing AppArmor/SELinux to restrict curl/wget network access and file writes, constraining GTFOBins from spawning shells, and requiring egress via a proxy allowlist with TLS validation (disallow --insecure/-k).

References

Related rules

to-top