Symptômes · 10 min · publié le 4 juillet 2024 · mis à jour le 7 mars 2025

Tâches cron inconnues : le malware qui revient à 3 h du matin

Un cron relance le mineur, réécrit un `.htaccess`, republie un article, envoie du spam. On liste les cron du compte d'hébergement, pas seulement ceux du CMS. C'est le motif n°1 de « c'est nettoyé, ça revient à 3 h ».

Réponse directe

Un cron relance le mineur, réécrit un fichier ou envoie du spam. Listez les cron du compte, pas seulement ceux du CMS. C'est le motif n°1 de « ça revient ».

cron malware tâche planifiée pirate wordpress cron hack

Pourquoi 3 h du matin revient si souvent

Moins de clients sur le site, moins d'admins connectés, parfois une fenêtre où les backups tournent (I/O masquée). Les kits copient les uns des autres : `0 3 * * *` est devenu un cliché. Votre pic à 3 h 07 n'est pas une coïncidence culturelle ; c'est une copie de tutoriel d'attaquant.

Le symptôme du matin : footer de retour, `radio.php` ressuscité, CPU à 100 %, file mail. Vous aviez « tout enlevé » à 18 h. Le cron n'était pas dans le dossier que vous avez scanné.

Traitez tout incident qui revient à heure fixe comme un cron jusqu'à preuve du contraire. Un hit HTTP à heure fixe peut être un ping externe ; un process sans hit, c'est local.

Trois étages : système, panel, CMS

Système (VPS) : crontab des users, `/etc/cron.*`, systemd timers. Panel : « Tâches planifiées » o2switch, cPanel, Plesk — souvent invisible depuis WordPress. CMS : WP-Cron, cron Magento, `cron.php` Presta, actions planifiées.

Nettoyer l'étage CMS et laisser le panel, le fichier revient. Inversement, un mu-plugin s'accroche à WP-Cron sans ligne panel. Les trois listes, la même heure.

Les voisins de compte n'ont pas votre crontab. Si le process n'est pas à votre uid, ticket hébergeur, pas réinstall WordPress.

  • crontab / timers (VPS).
  • Planificateur du panel.
  • WP-Cron, Presta cron, Magento cron.
  • Hooks « shutdown » qui simulent un cron.

Lire crontab et le planificateur cPanel

cPanel → Cron Jobs : chaque ligne, chaque PHP. Un chemin dans `tmp`, `cache`, `uploads`, un nom `wp-file.php` à la racine. Copiez toutes les lignes dans un fichier hors serveur avant d'effacer. La ligne est une preuve.

Plesk et les panels « simples » cachent parfois les cron système. Demandez au support « liste des cron de l'uid ». Sur un VPS, `crontab -l` pour chaque user, pas seulement `root`.

Une tâche « backup » qui lance un PHP que vous ne reconnaissez pas n'est pas un backup. Les vrais jobs backup ont un nom d'outil (restic, jetbackup, un script d'agence daté et commenté).

Effacer toutes les cron « pour voir » casse les backups et les commandes Presta. Isolez les lignes inconnues, gardez les connues.

WordPress : WP-Cron n'est pas crontab

WP-Cron tourne sur les visites (ou via un vrai cron qui appelle `wp-cron.php`). Les événements sont en base (`wp_options`, clé `cron`). Un plugin pirate s'y inscrit. Des outils (WP-CLI `cron event list`, un plugin d'inspection) listent les hooks. Un hook `my_custom_sync` toutes les cinq minutes vers un PHP inconnu sort.

`DISABLE_WP_CRON` + un cron système propre est une bonne hygiène après incident. `DISABLE_WP_CRON` + un cron système sale, vous avez seulement déplacé. Voir WP-Cron malware.

Les « Action Scheduler » WooCommerce (tables `actionscheduler_*`) sont un quatrième tiroir. Des milliers d'actions `spam_rebuild` : le générateur est là. Ne tronquez pas la table entière : vous tuez aussi les e-mails de commande. Filtrez le hook.

Presta, Magento, et les runners

PrestaShop : `Modules → Cron` et la crontab qui frappe `modules/…/cron.php`. Un token de cron dans l'URL, s'il est public, est une porte. Magento : `bin/magento cron:run` toutes les minutes est normal ; un second PHP dans la même crontab ne l'est pas.

Les runners CI (deploy à heure fixe) peuvent avoir été détournés. Lisez le script de deploy, pas seulement le site. Un deploy qui rsync un repo infecté « répare » le malware toutes les nuits — l'inverse du but.

Windows / Plesk scheduled tasks : même logique, autre UI. Exportez la liste.

Tuer ne suffit pas : trouver l'écrivain de cron

Un shell à la racine recrée la ligne crontab. Vous videz le panel, il la remet. Retirez le shell et changez le panel dans la même fenêtre. Voir PHP à la racine.

Un admin fantôme avec un plugin « Easy Cron » fait la même chose depuis l'UI. Les utilisateurs se listent le même jour.

Certains malwares écrivent dans `~/.bashrc` ou un `@reboot`. Sur VPS, lisez ça. Sur mutualisé, vous n'y avez souvent pas accès : le panel et le webroot suffisent presque toujours.

Ce que la ligne de commande révèle

`php /home/xxx/public_html/wp-core.php` : chemin du payload. `curl https://… | sh` : téléchargement à chaque run — tuer le fichier local ne suffit pas, l'URL fournit la suite. `wget` vers `tmp` idem.

Notez l'URL distante si elle est là. Elle sert au constat, parfois à un signalement. Ne la visitez pas depuis votre session admin habituelle sans précaution ; c'est un kit.

Un `mysql` en cron qui `UPDATE wp_posts` : l'injection est en SQL, pas en fichier. La ligne cron est alors plus précieuse que n'importe quel scan de thème.

Après : une nuit de test

Lignes pirates ôtées, shells copiés/retirés, panel changé. Laissez passer la fenêtre habituelle (3 h). Vérifiez : fichier absent, CPU calme, pas de nouvel article, `.htaccess` intact. Si ça revient, l'écrivain de cron est encore là — souvent un second étage.

Gardez la liste « avant » des cron. À J+7, comparez. Une nouvelle ligne est plus parlante qu'un Wordfence vert.

Google n'entre ici que si le cron régénère des pages ou un kit. Alors 404 + éventuellement Safe Browsing 24-72 h. Le cron lui-même n'a pas de réexamen.

Alertes pour ne pas revivre J+30

Moins de personnes avec l'accès panel. Un second admin hébergeur « au cas où » est une porte. Revue des cron à chaque incident, et une fois par trimestre si vous maintenez.

Sur VPS, une alerte si crontab change (inotify, un petit script). Sur mutualisé, une revue manuelle après chaque « le site a fait un truc bizarre ».

Vous pouvez déclarer le site. Les listes de cron exportées raccourcissent l'intervention plus qu'un accès admin CMS seul.

  • Export des trois étages.
  • Isolation des lignes inconnues, pas un wipe.
  • Shells et panel dans la même heure.
  • Nuit de test sur l'horaire habituel.

Questions fréquentes

WP-Cron est désactivé, donc je suis couvert ?

+
Vous avez déplacé vers le cron système. S'il est sale, c'est pire : ça tourne même sans trafic. Lisez le panel.

Une tâche « wget mon-site » toutes les 5 min, c'est pirate ?

+
Souvent un keep-alive WP-Cron maladroit, parfois un ping de monitoring. Lisez l'URL exacte. Un wget vers `radio.php`, lui, sort.

Puis-je tout passer sur Action Scheduler et supprimer crontab ?

+
Les backups hébergeur et les crons Presta/Magento ont besoin du système. Ne videz pas. Triez.

Le cron est revenu avec un autre chemin.

+
L'écrivain est vivant (shell, admin, deploy). Ne jouez pas au chat. Cherchez l'entrée, changez le panel.

L'hébergeur refuse de lister les cron. Que faire ?

+
Demandez une archive du compte ou un accès « scheduled tasks ». Sans liste, vous nettoyez à l'aveugle. C'est un argument de ticket, pas une option.
À lire ensuite
Processeur saturé Fichiers PHP à la racine WordPress cron malware Mon site envoie du spam Must-use plugin Déclarer mon site