Linux External IP Address Discovery via Curl

Detects applications making a curl request to a known public IP address lookup web service. Malware tends to perform this action to assess potential targets.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/07/02"
  3integration = ["endpoint", "sentinel_one_cloud_funnel"]
  4maturity = "production"
  5updated_date = "2026/09/18"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects applications making a curl request to a known public IP address lookup web service. Malware tends to perform this 
 11action to assess potential targets.
 12"""
 13from = "now-9m"
 14index = [
 15        "logs-endpoint.events.process*",
 16        "logs-sentinel_one_cloud_funnel.*",
 17]
 18language = "eql"
 19license = "Elastic License v2"
 20name = "Linux External IP Address Discovery via Curl"
 21note = """ ## Triage and analysis
 22
 23> **Disclaimer**:
 24> 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.
 25
 26### Investigating Linux External IP Address Discovery via Curl
 27
 28This rule flags a Linux process that uses curl to contact public IP lookup sites, a common way malware learns the host’s internet-facing address before choosing follow-on actions. An attacker who gains shell access on a server or container may run curl against services like ifconfig.me or ipify, then use the returned address to verify outbound reachability, tailor command-and-control, or decide whether the system sits behind cloud or NAT infrastructure.
 29
 30### Possible investigation steps
 31
 32- Trace the full process ancestry and nearby commands to determine whether the curl execution came from an interactive shell, scheduled task, deployment script, container entrypoint, or an unexpected program launched from a writable path.
 33- Review the invoked URL, arguments, working directory, and any captured output to determine whether the request was a one-off connectivity check or part of a broader script performing follow-on discovery, download, or beaconing.
 34- Correlate the activity with the initiating account, TTY/session details, recent SSH and sudo events, and change records to quickly separate approved administrator troubleshooting from suspicious post-compromise behavior.
 35- Pivot to surrounding network activity from the same host to identify repeated lookups, subsequent outbound connections to unfamiliar infrastructure, or signs of staging and command-and-control immediately after the public IP query.
 36- Inspect the parent script or binary on disk for recent creation or modification, unusual persistence mechanisms, and prevalence on peer systems to assess whether the behavior is tied to malware, a rogue change, or benign automation.
 37
 38### False positive analysis
 39
 40- Legitimate startup, login-banner, or scheduled maintenance scripts may use curl to learn the host’s public IP for configuration or status display, so verify the parent script or service path is expected, recently approved, and consistently seen at boot or on a routine schedule.
 41- An administrator or engineer may manually run curl to a public IP lookup site during troubleshooting or deployment validation, so confirm the initiating user, TTY or session context, and shell history align with authorized activity and that no suspicious follow-on commands occurred.
 42
 43### Response and remediation
 44
 45- Isolate the affected Linux host or container from the network immediately, allow only a secured management path, and preserve volatile evidence such as the running parent process, shell history, and the script or binary that launched curl.
 46- Terminate the malicious process chain and remove persistence by inspecting and cleaning cron jobs, systemd unit files, rc.local, user shell profiles, container entrypoints, SSH authorized_keys, and any attacker files staged in writable locations such as /tmp, /var/tmp, or /dev/shm.
 47- Rotate credentials and secrets exposed to the compromised system, including SSH keys, API tokens, cloud instance credentials, and application secrets found in scripts, environment files, or shell history.
 48- Restore the asset to a known-good state by rebuilding from a trusted image or clean backup and validating startup scripts, packages, and container images before returning the system to production.
 49- Escalate to incident response and broaden scoping across peer systems if the IP lookup was followed by downloads, reverse shells, new outbound connections to unfamiliar infrastructure, or if the same parent script, binary, or persistence artifact appears on multiple hosts.
 50- Harden the environment by restricting outbound curl access to approved destinations, blocking public IP lookup services where not needed, limiting execution from writable directories, and adding detections for unexpected systemd, cron, and shell-profile modifications.
 51"""
 52risk_score = 21
 53rule_id = "996e2e09-087e-4e99-a3cc-a9225d24ba3d"
 54setup = """## Setup
 55
 56This rule requires data coming in from one of the following integrations:
 57- Elastic Defend
 58
 59### Elastic Defend Integration Setup
 60Elastic 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.
 61
 62#### Prerequisite Requirements:
 63- Fleet is required for Elastic Defend.
 64- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
 65
 66#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
 67- Go to the Kibana home page and click "Add integrations".
 68- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
 69- Click "Add Elastic Defend".
 70- Configure the integration name and optionally add a description.
 71- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
 72- 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).
 73- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
 74- 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.
 75For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
 76- Click "Save and Continue".
 77- 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.
 78For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
 79"""
 80severity = "low"
 81tags = [
 82    "Domain: Endpoint",
 83    "OS: Linux",
 84    "Use Case: Threat Detection",
 85    "Tactic: Discovery",
 86    "Data Source: Elastic Defend",
 87    "Data Source: SentinelOne",
 88    "Resources: Investigation Guide",
 89    "Noise: Medium",
 90    "Performance: Normal",
 91    "Threat: Download Tool Abuse",
 92    "Rule Type: Event Correlation (EQL)",
 93    "Platform: Linux",
 94]
 95timestamp_override = "event.ingested"
 96type = "eql"
 97query = '''
 98process where host.os.type == "linux" and event.type == "start" and event.action in ("exec", "start") and
 99process.name == "curl" and (
100  process.parent.name like ".*" or process.parent.executable like (
101    "/tmp/*", "/var/tmp/*", "/dev/shm/*", "/opt/*",  "/etc/*", "./*", "/run/user/*", "/var/run/user/*",
102    "/usr/bin/*", "/bin/*", "/usr/local/bin/*", "/sbin/*", "/usr/sbin/*", "/usr/local/sbin/*",
103    "/usr/lib/*", "/usr/local/lib/*", "/lib/*", "/lib64/*", "/usr/lib64/*", "/usr/local/lib64/*"
104  )
105) and
106process.command_line like~ (
107  "*ip-api.com*", "*checkip.dyndns.org*", "*api.ipify.org*", "*whatismyip.akamai.com*", "*bot.whatismyipaddress.com*",
108  "*ifcfg.me*", "*ifconfig.me*", "*ident.me*", "*ipof.in*", "*ip.tyk.nu*", "*icanhazip.com*", "*curlmyip.com*",
109  "*wgetip.com*", "*eth0.me*", "*ipecho.net*", "*ip.appspot.com*", "*api.myip.com*", "*geoiptool.com*", "*api.2ip.ua*",
110  "*api.ip.sb*", "*ipinfo.io*", "*checkip.amazonaws.com*", "*wtfismyip.com*", "*iplogger.*", "*freegeoip.net*",
111  "*freegeoip.app*", "*geoplugin.net*", "*myip.dnsomatic.com*", "*www.geoplugin.net*",
112  "*api64.ipify.org*", "*ip4.seeip.org*", "*.geojs.io*", "*portmap.io*", "*api.db-ip.com*",
113  "*geolocation-db.com*", "*httpbin.org*", "*myip.opendns.com*", "*ipv4.icanhazip.com*", "*ipv6.icanhazip.com*"
114) and
115not (
116  process.parent.name in ("jamf", "make") or
117  process.parent.name in (".", "./alert_api_call.sh", "nvim", "teleport") or
118  process.parent.executable like (
119    "/usr/local/bin/teleport", "/usr/local/bin/current_ip", "/tmp/go-build*", "/usr/bin/neofetch",
120    "/usr/bin/show-location-info", "/opt/tpot/bin/myip.sh", "/usr/sbin/sshd", "/tmp/newroot/var/quest/kace/scripts/*",
121    "./Linux_Inventory_Sheets.sh", "/opt/qvm/bin/update_info_qsuite", "/usr/lib/check_mk_agent/local/public_ip_check",
122    "/opt/teleport/system/bin/teleport", "/opt/Elastic/Endpoint/elastic-endpoint", "/etc/update-motd.d/motd.sh",
123    "/opt/coe/cadence/IC231/tools.lnx86/cda/bin/64bit/cda.exe", "/etc/update-motd.d/10-armbian-header",
124    "/opt/saltstack/salt/bin/python*", "/usr/bin/python*", "/usr/local/bin/detect-external-ip"
125  ) or
126  process.parent.args in ("/var/www/html/admin/modules/leucoalarm/scripts/system.php", "/etc/cont-init.d/50-ddns") or
127  (
128    process.parent.executable == "/usr/bin/java" and
129    process.args like "/opt/streamsets-datacollector/libexec/bootstrap-libs/*"
130  ) or
131  process.parent.command_line == "runc init" or
132  (
133    process.parent.executable == "/usr/bin/busybox" and
134    (process.parent.command_line == "sh /etc/cont-init.d/50-ddns" or process.working_directory == "/opt/outline-server")
135  )
136)
137'''
138
139[[rule.threat]]
140framework = "MITRE ATT&CK"
141
142  [rule.threat.tactic]
143  name = "Discovery"
144  id = "TA0007"
145  reference = "https://attack.mitre.org/tactics/TA0007/"
146
147  [[rule.threat.technique]]
148  name = "System Network Configuration Discovery"
149  id = "T1016"
150  reference = "https://attack.mitre.org/techniques/T1016/"

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 Linux External IP Address Discovery via Curl

This rule flags a Linux process that uses curl to contact public IP lookup sites, a common way malware learns the host’s internet-facing address before choosing follow-on actions. An attacker who gains shell access on a server or container may run curl against services like ifconfig.me or ipify, then use the returned address to verify outbound reachability, tailor command-and-control, or decide whether the system sits behind cloud or NAT infrastructure.

Possible investigation steps

  • Trace the full process ancestry and nearby commands to determine whether the curl execution came from an interactive shell, scheduled task, deployment script, container entrypoint, or an unexpected program launched from a writable path.
  • Review the invoked URL, arguments, working directory, and any captured output to determine whether the request was a one-off connectivity check or part of a broader script performing follow-on discovery, download, or beaconing.
  • Correlate the activity with the initiating account, TTY/session details, recent SSH and sudo events, and change records to quickly separate approved administrator troubleshooting from suspicious post-compromise behavior.
  • Pivot to surrounding network activity from the same host to identify repeated lookups, subsequent outbound connections to unfamiliar infrastructure, or signs of staging and command-and-control immediately after the public IP query.
  • Inspect the parent script or binary on disk for recent creation or modification, unusual persistence mechanisms, and prevalence on peer systems to assess whether the behavior is tied to malware, a rogue change, or benign automation.

False positive analysis

  • Legitimate startup, login-banner, or scheduled maintenance scripts may use curl to learn the host’s public IP for configuration or status display, so verify the parent script or service path is expected, recently approved, and consistently seen at boot or on a routine schedule.
  • An administrator or engineer may manually run curl to a public IP lookup site during troubleshooting or deployment validation, so confirm the initiating user, TTY or session context, and shell history align with authorized activity and that no suspicious follow-on commands occurred.

Response and remediation

  • Isolate the affected Linux host or container from the network immediately, allow only a secured management path, and preserve volatile evidence such as the running parent process, shell history, and the script or binary that launched curl.
  • Terminate the malicious process chain and remove persistence by inspecting and cleaning cron jobs, systemd unit files, rc.local, user shell profiles, container entrypoints, SSH authorized_keys, and any attacker files staged in writable locations such as /tmp, /var/tmp, or /dev/shm.
  • Rotate credentials and secrets exposed to the compromised system, including SSH keys, API tokens, cloud instance credentials, and application secrets found in scripts, environment files, or shell history.
  • Restore the asset to a known-good state by rebuilding from a trusted image or clean backup and validating startup scripts, packages, and container images before returning the system to production.
  • Escalate to incident response and broaden scoping across peer systems if the IP lookup was followed by downloads, reverse shells, new outbound connections to unfamiliar infrastructure, or if the same parent script, binary, or persistence artifact appears on multiple hosts.
  • Harden the environment by restricting outbound curl access to approved destinations, blocking public IP lookup services where not needed, limiting execution from writable directories, and adding detections for unexpected systemd, cron, and shell-profile modifications.

Related rules

to-top