Aller au contenu

PersistanceExécution

Cron, anacron, at et timers systemd : planification

Artefacts de planification Linux (crontabs, horodatages anacron, tâches at, timers systemd) qui révèlent la persistance planifiée et prouvent les exécutions.

Emplacement
/var/spool/cron/
Prouve
Quelles commandes étaient planifiées, par quel compte, et quand cron, anacron ou un timer les a lancées pour la dernière fois
Horodatages
mtime/ctime des fichiers ; heure syslog ou journal pour les exécutions ; horodatages anacron en date locale AAAAMMJJ
Accès
root pour tous les répertoires de spool ; tout utilisateur pour sa propre crontab via crontab -l
Rétention
Jusqu'à suppression ; les preuves d'exécution suivent la rotation de syslog/du journal
Collecte
UAC, Velociraptor, cp -a, journalctl

Ce que c'est

Linux dispose de quatre planificateurs qui se recoupent. cron (Vixie cron sous Debian et Ubuntu, cronie dans la famille RHEL) exécute des tâches récurrentes depuis des tables système et par utilisateur. anacron exécute les tâches quotidiennes, hebdomadaires et mensuelles sur les machines qui ne tournent pas en permanence, et mémorise la date de dernière exécution. at (atd) exécute des tâches ponctuelles. Les timers systemd sont des unités .timer qui activent un service selon un calendrier ou un délai monotone, et assurent désormais une bonne partie de la maintenance autrefois confiée à cron.

Tous les quatre reposent sur de simples fichiers sur disque, faciles à collecter et faciles à détourner pour un intrus (MITRE ATT&CK T1053.003 cron, T1053.002 at, T1053.006 timers systemd).

Où il se trouve

ArtefactDebian / UbuntuRHEL / Fedora / Rocky / Alma
Table système (avec champ utilisateur)/etc/crontab/etc/crontab
Tables système additionnelles/etc/cron.d/*/etc/cron.d/* (dont 0hourly)
Répertoires de scripts run-parts/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthlyidentique
Crontabs utilisateur (sans champ utilisateur)/var/spool/cron/crontabs/<user>/var/spool/cron/<user>
Configuration anacron/etc/anacrontab/etc/anacrontab
Horodatages de dernière exécution anacron/var/spool/anacron/<job-id>/var/spool/anacron/<job-id>
Tâches at/var/spool/cron/atjobs/ (plus atspool/)/var/spool/at/ (plus .SEQ)
Contrôle d'accès/etc/cron.allow, /etc/cron.deny, /etc/at.allow, /etc/at.denyidentique
Unités timer*.timer dans les chemins d'unités systemd (voir unités systemd)identique
Horodatages des timers persistants/var/lib/systemd/timers/stamp-<name>.timeridentique
Timers transitoires (systemd-run --on-*)/run/systemd/transient/, /run/user/<uid>/systemd/transient/identique
Journal d'exécutionLignes CRON[pid] dans /var/log/syslog ou le journal/var/log/cron ou le journal

Sous RHEL, /etc/cron.d/0hourly exécute /etc/cron.hourly, où un script lance anacron, qui gère ensuite les répertoires daily, weekly et monthly. Sous Debian, /etc/crontab appelle run-parts pour ces répertoires, sauf si anacron est installé.

Ce qu'il prouve

  • Persistance planifiée : quelle commande doit s'exécuter, à quelle fréquence et (pour les tables système) sous quel utilisateur. Les crontabs utilisateur s'exécutent sous le propriétaire du fichier.
  • Exécution : une ligne de journal CMD prouve que cron a lancé la commande à cette minute. Elle ne prouve pas que la commande a réussi.
  • Dernière exécution périodique : un horodatage anacron enregistre la dernière date d'exécution d'une tâche ; le mtime d'un fichier stamp de timer enregistre le dernier déclenchement d'un timer Persistent=true.
  • Qui a modifié une crontab : les lignes crontab[pid]: (user) BEGIN EDIT / REPLACE / END EDIT du journal.
  • Non prouvé : la seule présence d'un fichier de tâche ne montre pas qu'il a été exécuté (le démon peut être désactivé, ou le fichier ignoré ; le cron de Debian ignore les noms de /etc/cron.d contenant un point).

Champs clés

ÉlémentSignification
m h dom mon dowLes cinq champs de planification de chaque ligne de crontab
champ utilisateurSixième champ, uniquement dans /etc/crontab et /etc/cron.d/*
@reboot, @hourly, @daily ...Planifications abrégées ; @reboot est une favorite pour la persistance
MAILTO, SHELL, PATH, CRON_TZLignes d'environnement dans une crontab ; CRON_TZ (cronie) change le fuseau horaire de la planification
anacrontab period delay job-identifier commandJours entre deux exécutions, délai en minutes, nom du fichier d'horodatage, commande
START_HOURS_RANGE, RANDOM_DELAYFenêtre d'exécution et décalage aléatoire d'anacron
fichier de tâche atScript shell : environnement capturé, cd vers le répertoire de travail d'origine, commande à la fin
.timer OnCalendar=, OnBootSec=, OnActiveSec=, OnUnitActiveSec=Déclencheur calendaire ou monotone
.timer Unit=, Persistent=Unité activée (par défaut : le .service de même nom de base) ; rattrapage après une période d'arrêt

Horodatages

  • Les crontabs et fichiers de tâches ne portent que des horodatages du système de fichiers. Comme crontab réécrit le fichier de spool, son mtime correspond à la dernière installation. Sous Debian, un fichier installé par crontab commence par un en-tête DO NOT EDIT THIS FILE qui nomme le fichier temporaire et la date d'installation ; un fichier de spool sans cet en-tête a probablement été écrit directement.
  • Les horodatages anacron contiennent la date de dernière exécution au format YYYYMMDD (sans heure), en heure locale.
  • Les fichiers stamp des timers sont vides ; l'information réside dans le mtime du fichier.
  • Les lignes de journal suivent le format syslog (voir syslog et auth.log) ; les entrées du journal systemd stockent des microsecondes depuis l'epoch Unix en 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

Rétention

Les crontabs, les tâches at en attente, les timers et les horodatages anacron persistent jusqu'à leur suppression. Anacron ne supprime jamais ses propres horodatages : des fichiers périmés peuvent donc révéler des tâches retirées depuis de /etc/anacrontab. Les timers transitoires sous /run sont perdus au redémarrage. Les preuves d'exécution (lignes CMD, messages de démarrage d'unités) ne durent que ce que permettent la rotation de syslog ou les limites de taille du journal.

Collecte

UAC collecte /etc en entier ainsi que /var/spool/cron, /var/spool/anacron et /var/spool/at via son artefact de planification de tâches ; son artefact systemd ajoute les répertoires d'unités et les timers transitoires. Sur un hôte live, il enregistre aussi systemctl list-timers --all.

# 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

L'artefact Velociraptor Linux.Sys.Crontab analyse les crontabs et liste les scripts run-parts.

Analyse

Les crontabs sont du texte : retirez les commentaires et lisez chaque ligne.

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*

Pour les timers, lisez chaque .timer et l'unité qu'il active, puis recherchez les messages de démarrage correspondants dans le journal.

Conseils d'investigation

  • Triez tous les fichiers de planification par ctime, pas par mtime ; touch peut antidater le mtime mais pas le ctime.
  • Un nouveau script déposé dans /etc/cron.daily ne nécessite aucune modification de crontab et ne produit que la ligne CMD générique de run-parts : examinez le contenu des répertoires, pas seulement les tables.
  • Les planifications fréquentes (* * * * *), @reboot, curl/wget redirigés vers un shell, les blocs base64 et les chemins dans /tmp, /dev/shm ou des répertoires cachés sont des indicateurs classiques. Voir /tmp et /dev/shm.
  • Une modification de crontab sans ligne de journal crontab[pid] correspondante suggère que le fichier de spool a été écrit directement.
  • Les comptes de service (www-data, apache, postgres) ont rarement des crontabs ; l'apparition d'une crontab après la compromission d'un site web est une piste sérieuse. Corrélez avec les journaux du serveur web.
  • Les timers utilisateur sous ~/.config/systemd/user ne s'exécutent que pendant que l'utilisateur est connecté, sauf si le lingering est activé (/var/lib/systemd/linger/<user>).
  • Reliez chaque tâche à son exécution grâce aux entrées du journal ou de syslog et, si disponibles, aux enregistrements EXECVE d'auditd.

Voir aussi