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
- Proxy Shell Execution via Busybox
- Base64 Decoded Payload Piped to Interpreter
- Git Hook Command Execution
- Node.js Pre or Post-Install Script Execution
- Potential Hex Payload Execution via Command-Line