Le WordPress d'aujourd'hui, décodé pour les développeurs

Sécurité

« wp cron event run » manuel : un événement planifié détourné

Un lien discret dans l'administration permettait de déclencher à volonté un traitement lourd, sans la moindre vérification de capacité.

Par Clément Hadrot • 11 mai 2024 • 4 min de lecture • Aucun commentaire
« wp cron event run » manuel : un événement planifié détourné

« Pourquoi ce traitement d’export s’exécute-t-il vingt-deux fois en une heure, alors qu’il est planifié une seule fois par jour ? » Cette question, posée par un développeur consultant les journaux applicatifs d’un site d’intranet associatif, a mené à la découverte d’un événement cron détournable par un utilisateur sans droit particulier.

Le site proposait, dans son tableau de bord d’administration, un bouton « Générer l’export maintenant », destiné à forcer manuellement l’exécution d’un événement normalement planifié une fois par jour via wp_schedule_event(). Ce bouton s’est révélé accessible à des comptes qui n’auraient jamais dû pouvoir le déclencher.

Symptôme

Les journaux du serveur montraient des appels répétés à l’action export_donnees_quotidien, générant chacun un fichier volumineux et consommant plusieurs secondes de traitement CPU intensif. La fréquence de ces appels ne correspondait à aucune planification légitime, et leur horaire ne suivait pas non plus le déclenchement habituel du planificateur WordPress lié au trafic du site.

Diagnostic

Le bouton du tableau de bord pointait vers une URL du type admin.php?page=export&action;=lancer_maintenant, traitée par un gestionnaire qui déclenchait directement l’action associée à l’événement cron :

add_action( 'admin_init', function () {
    if ( isset( $_GET['action'] ) && 'lancer_maintenant' === $_GET['action'] ) {
        do_action( 'export_donnees_quotidien' );
    }
} );

Ce code s’exécutait pour tout utilisateur connecté capable d’atteindre une page d’administration, sans distinction de rôle. Aucun appel à current_user_can() ni aucune vérification de nonce n’entourait le déclenchement. Reproduire le comportement en local, à l’aide de la commande wp cron event run export_donnees_quotidien, a confirmé que le traitement lui-même fonctionnait correctement : le défaut ne résidait pas dans la logique métier de l’export, mais uniquement dans son point de déclenchement manuel.

L'essentiel à retenir : Un déclenchement manuel d'événement doit vérifier une capacité, pas juste une connexion ; Un lien d'action directe expose la même surface qu'une route REST ; wp cron event run aide à reproduire le comportement sans attendre le planificateur

Correctif

La correction ajoute une vérification de capacité adaptée à l’action réellement sensible, accompagnée d’un nonce pour empêcher qu’un lien forgé ne déclenche l’action à l’insu d’un administrateur légitime naviguant sur le site.

add_action( 'admin_init', function () {
    if (
        isset( $_GET['action'], $_GET['_wpnonce'] )
        && 'lancer_maintenant' === $_GET['action']
        && current_user_can( 'manage_options' )
        && wp_verify_nonce( $_GET['_wpnonce'], 'lancer_export_maintenant' )
    ) {
        do_action( 'export_donnees_quotidien' );
    }
} );

Le lien du bouton a également été régénéré avec wp_nonce_url() pour intégrer ce nonce automatiquement, et la vérification de capacité a été alignée sur celle déjà utilisée pour accéder à la page d’administration elle-même, évitant toute incohérence entre les deux niveaux de contrôle.

Prévention

Ce type de défaut se reproduit facilement dès qu’un bouton d’action directe est ajouté à une page d’administration existante, sous la pression d’un besoin ponctuel, sans repasser par la même rigueur qu’un formulaire classique. Trois réflexes limitent ce risque à l’avenir.

  • Traiter tout déclenchement manuel d’un événement cron comme une action sensible à part entière, jamais comme un simple raccourci d’affichage.
  • Systématiser l’usage de wp cron event run en environnement de test pour isoler la logique métier du point de déclenchement, avant toute mise en production.
  • Revoir chaque bouton d’action directe d’une page d’administration lors des audits de sécurité périodiques, au même titre que les routes REST personnalisées.

Repère retenu de ce diagnostic : un événement cron déclenché manuellement depuis l’administration reste une action, avec les mêmes exigences de contrôle qu’un formulaire de suppression ou de publication.

En résumé

Le problème observé ne tenait ni à la configuration générale de WP-Cron ni à la fiabilité de sa planification, mais à un point de déclenchement manuel ajouté sans les mêmes garde-fous que le reste de l’interface d’administration. La commande wp cron event run s’est révélée précieuse pour isoler cette cause, en permettant de rejouer l’événement indépendamment du bouton défaillant.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi