Ir al contenido

PersistenciaEjecución

Cron, anacron, at y timers de systemd en Linux

Artefactos de tareas programadas en Linux (crontabs, sellos de anacron, trabajos at, timers de systemd) que revelan persistencia y prueban ejecuciones.

Ubicación
/var/spool/cron/
Prueba
Qué comandos se programaron, con qué cuenta, y cuándo los lanzó por última vez cron, anacron o un timer
Marcas de tiempo
mtime/ctime de los archivos; hora de syslog o del journal para las ejecuciones; sellos de anacron como fecha local YYYYMMDD
Acceso
root para todos los directorios de spool; cualquier usuario para su propio crontab con crontab -l
Retención
Hasta su borrado; las evidencias de ejecución siguen la rotación de syslog/journal
Adquisición
UAC, Velociraptor, cp -a, journalctl

Qué es

Linux tiene cuatro planificadores que se solapan. cron (Vixie cron en Debian y Ubuntu, cronie en la familia RHEL) ejecuta trabajos recurrentes a partir de tablas del sistema y de cada usuario. anacron ejecuta trabajos diarios, semanales y mensuales en máquinas que no están siempre encendidas, y recuerda la fecha de la última ejecución. at (atd) ejecuta trabajos puntuales. Los timers de systemd son unidades .timer que activan un servicio según un calendario o un plazo monotónico, y hoy se encargan de buena parte del mantenimiento que antes hacía cron.

Los cuatro son archivos planos en disco, lo que los hace fáciles de recoger y fáciles de abusar para un intruso (MITRE ATT&CK T1053.003 cron, T1053.002 at, T1053.006 systemd timers).

Dónde se encuentra

ArtefactoDebian / UbuntuRHEL / Fedora / Rocky / Alma
Tabla del sistema (con campo de usuario)/etc/crontab/etc/crontab
Tablas del sistema adicionales/etc/cron.d/*/etc/cron.d/* (incluye 0hourly)
Directorios de scripts de run-parts/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthlyigual
Crontabs de usuario (sin campo de usuario)/var/spool/cron/crontabs/<user>/var/spool/cron/<user>
Configuración de anacron/etc/anacrontab/etc/anacrontab
Sellos de última ejecución de anacron/var/spool/anacron/<job-id>/var/spool/anacron/<job-id>
Trabajos at/var/spool/cron/atjobs/ (más atspool/)/var/spool/at/ (más .SEQ)
Control de acceso/etc/cron.allow, /etc/cron.deny, /etc/at.allow, /etc/at.denyigual
Unidades timer*.timer en las rutas de unidades de systemd (ver unidades systemd)igual
Sellos de timers persistentes/var/lib/systemd/timers/stamp-<name>.timerigual
Timers transitorios (systemd-run --on-*)/run/systemd/transient/, /run/user/<uid>/systemd/transient/igual
Log de ejecuciónLíneas CRON[pid] en /var/log/syslog o en el journal/var/log/cron o el journal

En RHEL, /etc/cron.d/0hourly ejecuta /etc/cron.hourly, y un script de ese directorio lanza anacron, que a su vez se ocupa de los directorios diario, semanal y mensual. En Debian, /etc/crontab llama a run-parts para esos directorios salvo que anacron esté instalado.

Qué prueba

  • Persistencia programada: qué comando está configurado para ejecutarse, con qué frecuencia y (en las tablas del sistema) con qué usuario. Los crontabs de usuario se ejecutan como el propietario del archivo.
  • Ejecución: una línea de log CMD prueba que cron lanzó el comando en ese minuto. No prueba que el comando tuviera éxito.
  • Última ejecución periódica: un sello de anacron registra la última fecha en que se ejecutó un trabajo; el mtime del sello de un timer registra el último disparo de un timer Persistent=true.
  • Quién editó un crontab: las líneas crontab[pid]: (user) BEGIN EDIT / REPLACE / END EDIT del log.
  • Lo que no prueba: la mera presencia de un archivo de trabajo no demuestra que llegara a ejecutarse (el demonio puede estar desactivado o el archivo ignorado; el cron de Debian omite los nombres de /etc/cron.d que contienen un punto).

Campos clave

ElementoSignificado
m h dom mon dowLos cinco campos de programación de cada línea de crontab
campo de usuarioSexto campo, solo en /etc/crontab y /etc/cron.d/*
@reboot, @hourly, @daily ...Programaciones abreviadas; @reboot es una de las favoritas para la persistencia
MAILTO, SHELL, PATH, CRON_TZLíneas de entorno dentro de un crontab; CRON_TZ (cronie) cambia la zona horaria de la programación
anacrontab period delay job-identifier commandDías entre ejecuciones, retardo en minutos, nombre del archivo de sello, comando
START_HOURS_RANGE, RANDOM_DELAYVentana de ejecución y variación aleatoria de anacron
archivo de trabajo atScript de shell: entorno capturado, cd al directorio de trabajo original y el comando al final
.timer OnCalendar=, OnBootSec=, OnActiveSec=, OnUnitActiveSec=Disparador de calendario o monotónico
.timer Unit=, Persistent=Unidad activada (por defecto, el .service con el mismo nombre base); recuperación tras un periodo apagado

Marcas de tiempo

  • Los crontabs y los archivos de trabajo solo tienen las marcas de tiempo del sistema de archivos. Como crontab reescribe el archivo de spool, su mtime es la hora de la última instalación. En Debian, un archivo instalado con crontab empieza con una cabecera DO NOT EDIT THIS FILE que indica el archivo temporal y la fecha de instalación; un archivo de spool sin esa cabecera probablemente se escribió directamente.
  • Los sellos de anacron contienen la fecha de la última ejecución como YYYYMMDD (sin hora), en hora local.
  • Los archivos de sello de los timers están vacíos; la información es el mtime del archivo.
  • Las líneas de log siguen el formato syslog (ver syslog y auth.log); las entradas del journal guardan microsegundos desde la época 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

Retención

Los crontabs, los trabajos at pendientes, los timers y los sellos de anacron persisten hasta que se borran. Anacron nunca borra sus propios sellos, así que los sellos obsoletos pueden revelar trabajos que después se eliminaron de /etc/anacrontab. Los timers transitorios bajo /run se pierden al reiniciar. Las evidencias de ejecución (líneas CMD, mensajes de arranque de unidades) duran solo lo que permitan la rotación de syslog o los límites de tamaño del journal.

Adquisición

UAC recoge /etc completo y /var/spool/cron, /var/spool/anacron y /var/spool/at mediante su artefacto de planificadores de tareas; su artefacto de systemd añade los directorios de unidades y los timers transitorios. En un host en vivo también guarda 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

El artefacto Linux.Sys.Crontab de Velociraptor analiza los crontabs y enumera los scripts de run-parts.

Análisis

Los crontabs son texto: elimine los comentarios y lea cada línea.

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*

Para los timers, lea cada .timer y la unidad que activa, y después busque en el journal los mensajes de arranque correspondientes.

Consejos para la investigación

  • Ordene todos los archivos de planificación por ctime, no por mtime; touch puede retrasar el mtime, pero no el ctime.
  • Un script nuevo depositado en /etc/cron.daily no requiere editar ningún crontab y solo genera la línea CMD genérica de run-parts, así que revise el contenido de los directorios, no solo las tablas.
  • Las programaciones muy frecuentes (* * * * *), @reboot, curl/wget redirigidos a una shell, bloques en base64 y rutas en /tmp, /dev/shm o directorios ocultos son indicadores clásicos. Ver /tmp y /dev/shm.
  • Una edición de crontab sin la línea de log crontab[pid] correspondiente sugiere que el archivo de spool se escribió directamente.
  • Las cuentas de servicio (www-data, apache, postgres) rara vez tienen crontab; si aparece uno tras el compromiso de un servidor web, es una pista sólida. Correlacione con los logs del servidor web.
  • Los timers de usuario en ~/.config/systemd/user solo se ejecutan mientras el usuario tiene sesión iniciada, salvo que esté activado el lingering (/var/lib/systemd/linger/<user>).
  • Vincule cada trabajo con su ejecución mediante las entradas del journal o de syslog y, cuando existan, los registros EXECVE de auditd.

Ver también