# Detecting Hidden Cron Jobs as a Backdoor

> Detect a cron job backdoor: check every place for scheduled tasks on Linux, interpret suspicious entries and secure what you find before you delete it.

Source: https://phpsos.de/en/blog/cronjobs-als-hintertuer/  
As of: 25/10/2026  
Provider: PHP SOS, PHP emergency help and server security. Immediate help via WhatsApp: https://wa.me/491736494914?text=Hello%20PHP%20SOS%2C%20we%20need%20help%20with%20our%20PHP%20server.%20Company%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**In short:** A hidden cron job is one of the most common backdoors on Linux servers: it regularly reloads malicious code or restarts processes, even after a PHP update. Check all places for scheduled tasks, not just `crontab -l`: the crontabs of all users, `/etc/crontab`, `/etc/cron.d`, the cron folders, systemd timers and at jobs. Secure what you find before you remove it.

## Why cron jobs are such a popular backdoor

After a successful break-in, an attacker has a problem: his access is fragile. An update closes the vulnerability, an admin deletes the webshell, a restart ends the process. A cron job solves this problem. It starts commands at fixed times without anyone intervening, and so restores lost access.

For PHP2Shell there are no confirmed indicators of compromise. According to the reports available to us, however, new cron jobs are among the general warning signs after break-ins through web applications. Anyone who has already searched for webshells should check the scheduled tasks at the same time. The other steps of a follow-up are listed in the [checklist after a hack](https://phpsos.de/en/ratgeber/checkliste-nach-dem-hack/).

## Where scheduled tasks can hide

Linux has several mechanisms for scheduled tasks. Many checks fail because only one of them is looked at.

| Location | Debian/Ubuntu | RHEL family | Who may write |
|---|---|---|---|
| Crontab per user | `/var/spool/cron/crontabs/` | `/var/spool/cron/` | the respective user |
| System-wide crontab | `/etc/crontab` | `/etc/crontab` | root |
| Individual files | `/etc/cron.d/` | `/etc/cron.d/` | root |
| Periodic folders | `/etc/cron.hourly` to `/etc/cron.monthly` | likewise | root |
| systemd timers | `/etc/systemd/system/`, user units | likewise | root, partly users |
| at jobs | queue of `atd` | likewise | users, if permitted |

Important for web servers: the web server user can usually create its own crontab without root rights. An attacker with the rights of `www-data` therefore needs no further vulnerability for that. Entries in `/etc/cron.d` or systemd units, by contrast, indicate that he has gained root rights.

Hosting panels such as Plesk or cPanel offer their own interface for scheduled tasks. Behind it, as a rule, are likewise the crontabs of the respective system users. Anyone who looks only in the interface therefore does not recognize every entry that was created directly on the server. When in doubt, check both.

## How to check all locations completely

The following commands only read. Run them as root and save the outputs with a date.

```bash
# Print the crontabs of all users
for u in $(cut -d: -f1 /etc/passwd); do
  out=$(crontab -l -u "$u" 2>/dev/null) && printf '### %s\n%s\n' "$u" "$out"
done

# System-wide entries and modification times
cat /etc/crontab
ls -la --time-style=full-iso /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly

# systemd timers and at jobs
systemctl list-timers --all
atq 2>/dev/null

# Search all cron files for typical patterns
grep -rnE "curl|wget|base64|/tmp/|/dev/shm|\| *(ba)?sh" /etc/crontab /etc/cron.* /var/spool/cron 2>/dev/null
```

Two tricks deserve special attention. Some entries hide commands behind many spaces so that they run off the right edge of the screen in the editor. Others use control characters that overwrite text on display. With `cat -A`, such characters become visible:

```bash
cat -A /var/spool/cron/crontabs/www-data 2>/dev/null | less
```

A second angle is the logs of the cron service. On many systems, cron records every execution with user and command. That way you also see entries that an attacker has since removed again, and you can tell since when a suspicious command has been running:

```bash
# Executed cron commands of the web server user (Debian/Ubuntu or systemd journal)
grep -h "CRON" /var/log/syslog* 2>/dev/null | grep -E "\((www-data|apache|nginx)\) CMD"
journalctl -u cron -u crond --since "2026-10-17" --no-pager 2>/dev/null | grep CMD | head -100
```

## How to recognize a cron job backdoor

1. **Reloading from the internet:** A download whose result is passed directly to a shell.
2. **Encoded content:** Long strings that are decoded only at runtime.
3. **Unusual paths:** Programs in `/tmp`, `/dev/shm`, hidden folders or upload directories.
4. **Wrong user:** Tasks under the web server user although the application needs none.
5. **Conspicuous schedule:** Execution every minute or at every restart via `@reboot`.
6. **Odd timestamps:** File modified in a period in which nobody worked on the server, for example after 17 October.

Do not forget: applications also have schedules of their own. WordPress, for example, manages scheduled tasks in the database. How to check there is described in [Finding backdoors in WordPress](https://phpsos.de/en/ratgeber/backdoor-wordpress-finden/).

> **Important:**
> A cron job rarely comes alone. Whoever created a scheduled task has often also deposited SSH keys or hidden files. Also check the keys, as described in the article [Finding unknown SSH keys](https://phpsos.de/en/blog/ssh-schluessel-pruefen/).

## Secure the find, understand it, then remove it

A malicious cron job is a valuable piece of evidence. It shows the download address, the time of its creation and often the user through whom the attacker came. Secure the file with a checksum and timestamps before you remove it. The timestamp later helps to reconstruct the sequence; how to do that is shown in [Building the timeline of an incident](https://phpsos.de/en/blog/zeitleiste-eines-vorfalls/). For a possible notification to the data protection authority or for the insurer, too, the find is important evidence of since when an attacker had access.

Removing alone is not enough. If a process is still running that rewrites the entry, it is back after the next minute. And as long as the original vulnerability is open, the attacker can start again at any time. The order is therefore: secure, close the cause, remove all components, change credentials, monitor.

## Securing cron jobs preventively

So that a cron job backdoor cannot arise in the first place or is noticed quickly, three measures help. First, you can determine which users may create a crontab at all. If the file `/etc/cron.allow` exists, only the users named there may use `crontab`. If your application needs no cron job under the web server user, that user does not belong on the list. Check beforehand which tasks the application actually needs, and create them deliberately under a user of their own.

Second, monitoring the files is worthwhile. An integrity checking tool reports as soon as a file in the cron directories or under `/var/spool/cron` changes. Third, scheduled tasks belong in the server's documentation: whoever knows which entries should exist recognizes a foreign one immediately.

## How does PHP SOS help?

- **Check completely:** We examine all mechanisms for scheduled tasks, including systemd timers, at jobs and application schedules.
- **Classify findings:** We evaluate suspicious entries without executing them and derive further traces.
- **Clean up properly:** With [malware removal](https://phpsos.de/en/leistungen/malware-entfernung/), we remove all components and close the cause.
- **Detect recurrence:** We set up monitoring that reports new or changed scheduled tasks.


## Frequently asked questions

**Why do attackers use cron jobs?**  
A cron job runs commands regularly and without further action. Attackers use it to reload malicious code, recreate deleted files or restart processes. That way their access survives an update and often a superficial cleanup too.

**Is crontab -l enough for the check?**  
No. crontab -l shows only the current user's crontab. Scheduled tasks also sit in the crontabs of other users, in /etc/crontab, /etc/cron.d, the cron.daily folders, in systemd timers and in at jobs.

**How do I recognize a malicious cron job?**  
Typical are downloads from the internet with direct execution, commands with encoded strings, programs in temporary folders, tasks under the web server user and entries that run every minute. A single feature is a hint; several are a serious suspicion.

**Can I simply delete suspicious cron jobs?**  
Secure first, then remove. The entry often reveals origin, download address and further components. Without clarifying how it came about, the attacker often creates it again.

## Sources

- [BSI: German Federal Office for Information Security](https://www.bsi.bund.de/)
- [BSI IT-Grundschutz](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
