Linux · Lesson 12

Cron Jobs & Scheduled Persistence

Review Linux scheduled tasks across user crontabs, system cron files, periodic directories, and anacron while preserving required automation and investigating suspicious persistence.

Scheduled execution is normal on Linux. Backups, updates, cleanup, reporting, and applications often depend on it. The defensive skill is deciding which job is expected, which is misconfigured, and which requires evidence-driven containment.

Lesson Snapshot

Core concepts6
Common schedule fields6
Inspection commands12
Main goalSafe persistence review

Learning objectives

Find scheduled persistence without destroying required automation

01

Explain how cron, system cron directories, anacron, and user crontabs schedule work on Ubuntu and Linux Mint.

02

Inspect scheduled tasks without immediately deleting unfamiliar entries.

03

Distinguish legitimate maintenance jobs from unnecessary, misconfigured, suspicious, or unknown persistence.

04

Trace a scheduled command to its owner, executable, script, package, environment, logs, and downstream effects.

05

Preserve evidence before disabling or removing a suspicious scheduled task.

06

Verify that required maintenance and application jobs still run after changes.

Core idea

A schedule is only the trigger

The real security question is what the task executes, under which account, from which path, with which permissions, and for what required purpose.

Evidence risk

Deleting the scheduler entry can erase the map to persistence

Preserve the entry, referenced scripts, metadata, ownership, logs, and package information before removing a confirmed unauthorized task.

Cron fundamentals

Six concepts behind scheduled execution

cron

cron is a time-based job scheduler. It launches commands according to crontab entries and system scheduling files.

crontab

A crontab contains scheduled entries. Users can have their own crontabs, while system-wide jobs may be defined in /etc/crontab or cron directories.

Owner context

A scheduled task runs under a user identity. User context determines privileges, file access, environment, and impact.

Environment

cron jobs usually run with a smaller environment than an interactive shell. PATH, working directory, variables, and shell behavior can differ.

Persistence

Scheduled execution can be legitimate automation or a persistence mechanism. The schedule itself is not proof of malicious activity.

Verification

A scheduled task is not fully understood until you know what it runs, who owns it, why it exists, and whether required behavior still works after remediation.

Schedule syntax

Understand what the five time fields mean

Minute

0-59

The minute of the hour when the job may run.

Hour

0-23

The hour of the day when the job may run.

Day of month

1-31

Limits execution by calendar day.

Month

1-12

Limits execution by month.

Day of week

0-7

Limits execution by weekday on many cron implementations, commonly with 0 or 7 representing Sunday.

Command

Executable / shell command

The actual command cron launches when the time expression matches.

15 2 * * * /usr/local/sbin/backup-job

This example means run the command at 02:15 each day. On a user crontab there is no separate user field. In /etc/crontab and many files under /etc/cron.d, a user field appears before the command.

Important paths

Scheduled jobs can live in several places

/etc/crontab

System-wide crontab. Unlike ordinary user crontabs, entries include a user field before the command.

Do not copy user-crontab syntax into /etc/crontab without accounting for the user field.

/etc/cron.d/

Package and administrator system cron files.

Entries may be package-managed. Identify ownership before editing or removing.

/etc/cron.hourly/

Scripts intended for hourly execution on systems using these directories.

Inspect script contents, ownership, executable permissions, and package origin.

/etc/cron.daily/

Scripts commonly used for daily maintenance.

Many legitimate package maintenance jobs live here.

/etc/cron.weekly/

Scripts commonly scheduled for weekly maintenance.

Frequency alone does not indicate whether a job is required.

/etc/cron.monthly/

Scripts commonly scheduled for monthly maintenance.

Review package ownership and application purpose before changing.

/var/spool/cron/crontabs/

Common Ubuntu-family storage location for user crontabs.

Do not edit spool files directly unless you understand the platform behavior; use crontab tools for normal administration.

/etc/anacrontab

Controls anacron jobs designed to run periodic work even when the machine was powered off at the scheduled time.

Anacron complements cron behavior and can explain jobs that execute after boot.

Inspection first

Inventory schedules before changing them

crontab -l

Show the current user's crontab.

sudo crontab -l

Show root's crontab.

sudo crontab -u username -l

Show a specific user's crontab.

sudo cat /etc/crontab

Review the main system-wide crontab.

sudo ls -la /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly

Inventory common system cron locations.

sudo find /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly -maxdepth 1 -type f -ls

Collect file ownership, permissions, timestamps, and paths for scheduled scripts.

sudo systemctl status cron

Review the cron service state on Ubuntu-family systems.

sudo journalctl -u cron --since today

Review cron service events where journal logging captures them.

sudo grep -i CRON /var/log/syslog | tail -n 50

Review recent cron-related syslog entries on systems that log cron activity there.

sudo cat /etc/anacrontab

Review anacron schedules and commands.

dpkg -S /path/to/script

Check whether a scheduled script belongs to an installed Debian package.

stat /path/to/script

Review script ownership, permissions, size, and timestamps.

Special schedules

Named schedule shortcuts deserve the same review

@reboot

Runs once after the cron daemon starts following boot.

Useful for legitimate startup automation but also valuable for persistence.

@hourly

Runs once per hour.

Frequent schedules deserve review if the command is unfamiliar or resource-heavy.

@daily

Runs once per day.

Common for maintenance and backups; identify purpose before changing.

@weekly

Runs once per week.

Can support maintenance or delayed persistence.

@monthly

Runs once per month.

Long intervals make quick testing more difficult, so validate logic carefully.

Cron environment

Scheduled jobs do not run like your interactive shell

PATH may be limited

A command that works interactively may fail under cron if it depends on a shell PATH that cron does not provide.

Working directory may differ

Relative paths can point somewhere unexpected. Security-sensitive cron jobs should generally use explicit paths.

Shell behavior matters

Cron commonly uses /bin/sh unless otherwise specified. Bash-specific syntax may fail.

Variables may be absent

Interactive profile variables are not guaranteed. Required environment values should be set deliberately.

Output may reveal failures

Cron output can be mailed, logged, redirected, or discarded depending on configuration. Missing visible output does not prove success.

Permissions still apply

The cron daemon does not magically bypass file permissions for non-root users. Execution context matters.

Classification

Required, legitimate, misconfigured, suspicious, or unknown

Required

Evidence

Named by the scenario, supports backups, updates, logs, applications, reporting, or another known required function.

Response

Preserve it and verify the command, permissions, output, and schedule are secure.

Legitimate

Evidence

Package-owned maintenance task or known administrative automation with expected ownership and behavior.

Response

Leave intact unless there is a specific configuration problem.

Misconfigured

Evidence

Required task runs as the wrong user, uses unsafe writable paths, has broken syntax, leaks output, or executes too frequently.

Response

Correct the narrow configuration issue and verify the task still performs its required function.

Suspicious

Evidence

Unexpected root execution, script in /tmp or unusual user directory, encoded command, network download, strange interpreter chain, misleading filename, or persistence after an incident.

Response

Preserve crontab entry, script, metadata, logs, command line, package status, and related files before disabling it.

Unknown

Evidence

Purpose, owner, executable origin, schedule, or application relationship is unclear.

Response

Investigate further instead of deleting it because the name looks unfamiliar.

Persistence indicators

Patterns that increase investigation priority

Unexpected @reboot entry

Boot-triggered execution can maintain persistence. Inspect the command and owner.

Root job launching a user-writable script

A privileged scheduler executing a file writable by lower-privileged users creates a serious trust problem.

Script stored in /tmp or hidden user directory

Location can be suspicious, especially when paired with root execution or network activity.

Encoded or heavily obfuscated command

Obfuscation increases investigation priority because it hides intent.

Repeated download-and-execute pattern

Remote retrieval combined with immediate execution can create persistence or supply-chain risk.

Task recreates a removed file or process

Recurring recreation suggests the scheduler may be the persistence source rather than the visible child process.

Evidence-based reasoning

Investigate the command behind the schedule

A root cron job runs every five minutes

Weak response

Delete it because frequent root jobs are dangerous.

Better reasoning

Inspect the command, executable, package ownership, logs, script permissions, and scenario role. Monitoring or application jobs can legitimately run frequently.

A cron script lives in /tmp

Weak response

Delete the file immediately.

Better reasoning

Treat the location as high-priority evidence. Preserve the job entry, file metadata, script contents, owner, parent directories, and logs before containment.

A daily cron file belongs to a package

Weak response

It must be safe because a package owns it.

Better reasoning

Package ownership increases context but does not prove current configuration is secure. Review the package, script behavior, permissions, and scenario requirements.

A user's crontab is empty

Weak response

There are no cron jobs for that user.

Better reasoning

Also inspect system cron files, /etc/cron.d, periodic directories, root's crontab, and other users.

A job uses curl or wget

Weak response

Any download command is malicious.

Better reasoning

Determine the destination, source, package/application purpose, integrity expectations, and whether the scenario authorizes network retrieval.

A scheduled job is failing

Weak response

Remove it because it does not work.

Better reasoning

Determine whether it is required, inspect logs and environment differences, then repair or remove based on purpose.

Evidence sources

Preserve the persistence chain

User crontab

sudo crontab -u username -l

Shows the user's scheduled entries at the time of inspection.

System crontab

sudo cat /etc/crontab

Shows system-wide schedules including execution user.

Cron directories

sudo find /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly -maxdepth 1 -type f -ls

Shows scheduled files with ownership, timestamps, and permissions.

Cron logs

sudo grep -i CRON /var/log/syslog | tail -n 50

Can show when commands were launched, depending on logging configuration.

Script metadata

stat /path/to/script

Shows ownership, permissions, timestamps, and other filesystem metadata.

Package ownership

dpkg -S /path/to/script

Shows whether the file belongs to an installed Debian package.

Controlled actions

Preserve before you disable

Edit the current user's crontab

crontab -e

Use for intentional administration. Preserve the original entry before removing anything important.

Edit root's crontab

sudo crontab -e

Root jobs have high impact. Review the command and script permissions carefully.

Edit another user's crontab

sudo crontab -u username -e

Confirm the user's role and preserve the existing schedule first.

Temporarily preserve but disable one line

# comment the confirmed entry in the appropriate crontab or cron file

Commenting can preserve context better than deleting immediately, but only use a syntax-safe method for the specific file type.

Validate a referenced shell script

bash -n /path/to/script

Checks Bash syntax only. It does not prove the script is safe or appropriate to execute.

Review executable ownership

stat /path/to/script

Confirm ownership and permissions before allowing privileged scheduled execution.

High-risk shortcuts

Scheduled-task cleanup that can break the system or erase evidence

Deleting every unfamiliar cron entry

Can break backups, updates, reporting, application maintenance, and other required automation.

Stopping cron entirely

Removes all cron-based scheduling, including legitimate system and application tasks.

Deleting a suspicious script before preserving it

Destroys evidence about commands, network destinations, filenames, and attacker or administrator behavior.

Assuming user crontab review is complete

System cron directories, root, other users, and anacron may still schedule jobs.

Running an unfamiliar cron command manually

Can trigger the exact behavior you are investigating under the wrong context or at the wrong time.

Ignoring script permissions

A root cron job that executes a user-writable script can turn a legitimate schedule into a privilege-escalation path.

Verification

Prove required automation still works

Cron service

Confirm the cron service remains healthy when required.

Required jobs

Confirm backup, maintenance, reporting, or application jobs that the scenario requires still exist.

Removed persistence

Confirm the unauthorized process or file is not recreated by the scheduled task.

Permissions

Confirm privileged jobs reference scripts and directories with appropriate ownership and write permissions.

Logs

Review subsequent cron and application logs for expected execution or unexpected failures.

System function

Verify required applications and maintenance workflows still operate after the scheduling change.

Defensive lab

Investigate fictional cron-based persistence

01

Read the fictional scenario: nightly backup and daily package-maintenance jobs are required; a root-owned @reboot entry launches /tmp/.sync-agent and requires investigation.

02

Inventory root, user, system, periodic-directory, and anacron schedules without changing anything.

03

Preserve the suspicious @reboot line, script contents, stat output, ownership, package lookup, hashes if your lab workflow supports them, and relevant logs.

04

Trace whether /tmp/.sync-agent launches a process, creates network connections, or recreates other files in the fictional lab.

05

Classify the required backup and maintenance jobs as Required, and classify the unknown @reboot task as Suspicious only after the evidence supports that conclusion.

06

Disable the confirmed unauthorized persistence while preserving the original evidence and leaving required schedules intact.

07

Verify cron health, required jobs, absence of recreation, logs, and normal application behavior.

Lesson checklist

Before moving on

01

I understand the difference between user crontabs, /etc/crontab, /etc/cron.d, periodic cron directories, and anacron.

02

I know that system-wide cron entries may include an execution-user field.

03

I inspect root and multiple user schedules instead of checking only my own crontab.

04

I trace scheduled commands to their scripts, executables, owners, packages, and logs.

05

I understand that cron has a different environment from an interactive shell.

06

I treat unexpected @reboot jobs as high-priority evidence rather than automatic proof of malware.

07

I preserve suspicious entries and scripts before destructive cleanup.

08

I review permissions on scripts launched by privileged cron jobs.

09

I avoid stopping cron or deleting broad sets of jobs during routine hardening.

10

I verify required scheduled functions after changes.

Reflection

Check your reasoning

Question 1

Why can a command work in a terminal but fail when launched by cron?

Question 2

Why does an @reboot entry deserve careful review?

Question 3

What evidence should be preserved before removing a suspicious scheduled task?

Question 4

Why is a root cron job that launches a user-writable script dangerous?

Question 5

Why is an empty user crontab not proof that no scheduled persistence exists?

Question 6

What should you verify after disabling a suspicious cron task?

Carry this forward

Scheduled persistence is a chain: scheduler, owner, command, script, permissions, logs, and resulting process or network activity. Investigate the whole chain before removing the trigger.