Zum Inhalt springen

PersistenzAusführung

Cron, Anacron, at und systemd-Timer: Zeitplanung unter Linux

Artefakte geplanter Aufgaben unter Linux (Crontabs, Anacron-Stempel, at-Jobs, systemd-Timer), die Persistenz aufdecken und Ausführungen belegen.

Speicherort
/var/spool/cron/
Belegt
Welche Befehle von welchem Konto zur Ausführung geplant waren und wann cron, anacron oder ein Timer sie zuletzt ausgelöst hat
Zeitstempel
mtime/ctime der Dateien; Zeit in syslog oder Journal für Ausführungen; Anacron-Stempel als lokales Datum YYYYMMDD
Zugriff
root für alle Spool-Verzeichnisse; jeder Benutzer für die eigene Crontab über crontab -l
Aufbewahrung
Bis zur Löschung; Ausführungsspuren folgen der Rotation von syslog/Journal
Sicherung
UAC, Velociraptor, cp -a, journalctl

Was es ist

Linux kennt vier sich überschneidende Scheduler. cron (Vixie cron unter Debian und Ubuntu, cronie in der RHEL-Familie) führt wiederkehrende Jobs aus System- und Benutzertabellen aus. anacron führt tägliche, wöchentliche und monatliche Jobs auf Rechnern aus, die nicht ständig laufen, und merkt sich das Datum des letzten Laufs. at (atd) führt einmalige Jobs aus. systemd-Timer sind .timer-Units, die einen Dienst nach Kalender- oder monotonem Zeitplan aktivieren; sie übernehmen inzwischen einen Großteil der Wartungsaufgaben, die früher cron erledigte.

Alle vier bestehen aus einfachen Dateien auf der Platte. Das macht sie leicht zu sichern und für Eindringlinge leicht zu missbrauchen (MITRE ATT&CK T1053.003 cron, T1053.002 at, T1053.006 systemd-Timer).

Wo es liegt

ArtefaktDebian / UbuntuRHEL / Fedora / Rocky / Alma
Systemtabelle (mit Benutzerfeld)/etc/crontab/etc/crontab
Drop-in-Systemtabellen/etc/cron.d/*/etc/cron.d/* (einschließlich 0hourly)
run-parts-Skriptverzeichnisse/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthlyidentisch
Benutzer-Crontabs (ohne Benutzerfeld)/var/spool/cron/crontabs/<user>/var/spool/cron/<user>
Anacron-Konfiguration/etc/anacrontab/etc/anacrontab
Anacron-Stempel des letzten Laufs/var/spool/anacron/<job-id>/var/spool/anacron/<job-id>
at-Jobs/var/spool/cron/atjobs/ (plus atspool/)/var/spool/at/ (plus .SEQ)
Zugriffssteuerung/etc/cron.allow, /etc/cron.deny, /etc/at.allow, /etc/at.denyidentisch
Timer-Units*.timer in den systemd-Unit-Pfaden (siehe systemd-Units)identisch
Stempel persistenter Timer/var/lib/systemd/timers/stamp-<name>.timeridentisch
Transiente Timer (systemd-run --on-*)/run/systemd/transient/, /run/user/<uid>/systemd/transient/identisch
AusführungslogCRON[pid]-Zeilen in /var/log/syslog oder im Journal/var/log/cron oder das Journal

Unter RHEL startet /etc/cron.d/0hourly die Skripte in /etc/cron.hourly, und ein Skript dort startet anacron, das dann die täglichen, wöchentlichen und monatlichen Verzeichnisse abarbeitet. Unter Debian ruft /etc/crontab für diese Verzeichnisse run-parts auf, sofern anacron nicht installiert ist.

Was es belegt

  • Geplante Persistenz: welcher Befehl wie oft ausgeführt werden soll und (bei Systemtabellen) unter welchem Benutzer. Benutzer-Crontabs laufen als Eigentümer der Datei.
  • Ausführung: Eine CMD-Logzeile belegt, dass cron den Befehl in dieser Minute gestartet hat. Sie belegt nicht, dass der Befehl erfolgreich war.
  • Letzter periodischer Lauf: Ein Anacron-Stempel hält das Datum des letzten Laufs fest; die mtime eines Timer-Stempels die letzte Auslösung eines Timers mit Persistent=true.
  • Wer eine Crontab bearbeitet hat: Zeilen crontab[pid]: (user) BEGIN EDIT / REPLACE / END EDIT im Log.
  • Nicht belegt: Das bloße Vorhandensein einer Jobdatei zeigt nicht, dass sie je lief (der Daemon kann deaktiviert sein oder die Datei ignoriert werden; Debians cron überspringt Namen in /etc/cron.d, die einen Punkt enthalten).

Wichtige Felder

ElementBedeutung
m h dom mon dowFünf Zeitplanfelder in jeder Crontab-Zeile
BenutzerfeldSechstes Feld, nur in /etc/crontab und /etc/cron.d/*
@reboot, @hourly, @daily ...Kurzschreibweisen für Zeitpläne; @reboot ist für Persistenz besonders beliebt
MAILTO, SHELL, PATH, CRON_TZUmgebungszeilen innerhalb einer Crontab; CRON_TZ (cronie) ändert die Zeitzone des Zeitplans
anacrontab period delay job-identifier commandTage zwischen den Läufen, Verzögerung in Minuten, Name der Stempeldatei, Befehl
START_HOURS_RANGE, RANDOM_DELAYZeitfenster und Zufallsverzögerung von Anacron
at-JobdateiShell-Skript: erfasste Umgebung, cd ins ursprüngliche Arbeitsverzeichnis, Befehl am Ende
.timer OnCalendar=, OnBootSec=, OnActiveSec=, OnUnitActiveSec=Kalender- oder monotoner Auslöser
.timer Unit=, Persistent=Aktivierte Unit (Standard: gleicher Basisname mit .service); Nachholen nach Ausfallzeiten

Zeitstempel

  • Crontab- und Jobdateien tragen nur Dateisystemzeiten. Da crontab die Spool-Datei neu schreibt, ist ihre mtime der Zeitpunkt der letzten Installation. Unter Debian beginnt eine per crontab installierte Datei mit einem Header DO NOT EDIT THIS FILE, der die temporäre Datei und das Installationsdatum nennt; eine Spool-Datei ohne diesen Header wurde vermutlich direkt geschrieben.
  • Anacron-Stempel enthalten das Datum des letzten Laufs als YYYYMMDD (ohne Uhrzeit), in Ortszeit.
  • Timer-Stempeldateien sind leer; die Information steckt in der mtime der Datei.
  • Logzeilen folgen dem Syslog-Format (siehe syslog und auth.log); Journal-Einträge speichern Mikrosekunden seit der Unix-Epoche in UTC.
stat -c '%y  %z  %n' /mnt/evidence/var/lib/systemd/timers/stamp-*.timer
cat /mnt/evidence/var/spool/anacron/cron.daily      # e.g. 20260927

Aufbewahrung

Crontabs, ausstehende at-Jobs, Timer und Anacron-Stempel bleiben bis zur Löschung erhalten. Anacron löscht seine eigenen Stempel nie, veraltete Stempel können also Jobs aufdecken, die später aus /etc/anacrontab entfernt wurden. Transiente Timer unter /run gehen beim Neustart verloren. Ausführungsspuren (CMD-Zeilen, Startmeldungen von Units) bleiben nur so lange erhalten, wie Syslog-Rotation oder Größenlimits des Journals es zulassen.

Sicherung

UAC sammelt /etc vollständig sowie /var/spool/cron, /var/spool/anacron und /var/spool/at über sein Artefakt für Job-Scheduler; das systemd-Artefakt ergänzt Unit-Verzeichnisse und transiente Timer. Auf einem laufenden Host zeichnet es zusätzlich systemctl list-timers --all auf.

# dead box, read-only mount
tar -C /mnt/evidence -czf sched.tgz etc/crontab etc/cron.* etc/anacrontab \
  var/spool/cron var/spool/anacron var/spool/at var/lib/systemd/timers 2>/dev/null

# live
systemctl list-timers --all          # NEXT, LEFT, LAST, PASSED, UNIT, ACTIVATES
journalctl -D /mnt/evidence/var/log/journal SYSLOG_IDENTIFIER=CRON -o short-iso   # CROND on RHEL

Velociraptors Linux.Sys.Crontab parst Crontabs und listet die run-parts-Skripte auf.

Auswertung

Crontabs sind Text: Entfernen Sie Kommentare und lesen Sie jede Zeile.

grep -HvE '^\s*(#|$)' /mnt/evidence/etc/crontab /mnt/evidence/etc/cron.d/* \
  /mnt/evidence/var/spool/cron/crontabs/* /mnt/evidence/var/spool/cron/* 2>/dev/null
tail -n 5 /mnt/evidence/var/spool/cron/atjobs/* /mnt/evidence/var/spool/at/a* 2>/dev/null
grep -hE 'CRON\[|CROND\[|crontab\[' /mnt/evidence/var/log/syslog* /mnt/evidence/var/log/cron*

Lesen Sie bei Timern jede .timer-Datei und die Unit, die sie aktiviert, und suchen Sie dann im Journal nach den passenden Startmeldungen.

Tipps für die Untersuchung

  • Sortieren Sie alle Scheduler-Dateien nach ctime, nicht nach mtime; touch kann die mtime zurückdatieren, die ctime nicht.
  • Ein neues Skript in /etc/cron.daily erfordert keine Crontab-Änderung und erzeugt nur die allgemeine CMD-Zeile von run-parts. Prüfen Sie also den Inhalt der Verzeichnisse, nicht nur die Tabellen.
  • Häufige Zeitpläne (* * * * *), @reboot, an eine Shell weitergeleitetes curl/wget, Base64-Blobs und Pfade in /tmp, /dev/shm oder versteckten Verzeichnissen sind klassische Indikatoren. Siehe /tmp und /dev/shm.
  • Eine Crontab-Änderung ohne passende crontab[pid]-Logzeile deutet darauf hin, dass die Spool-Datei direkt geschrieben wurde.
  • Dienstkonten (www-data, apache, postgres) haben selten Crontabs; taucht nach einer Webkompromittierung eine auf, ist das eine starke Spur. Korrelieren Sie mit den Webserver-Logs.
  • Benutzer-Timer unter ~/.config/systemd/user laufen nur, solange der Benutzer angemeldet ist, es sei denn, Lingering ist aktiviert (/var/lib/systemd/linger/<user>).
  • Verknüpfen Sie jeden Job mit Ausführungsspuren aus Journal oder syslog und, sofern vorhanden, mit EXECVE-Datensätzen aus auditd.

Siehe auch