Modules orphelins dans PrestaShop : le code que personne ne regarde et qui répond toujours
Désinstaller un module ne supprime pas toujours ses fichiers. Ces dossiers orphelins n'apparaissent pas dans le gestionnaire de modules, ne sont jamais mis à jour et leur PHP peut être appelé par URL. Nous expliquons comment les trouver et les retirer en toute sécurité.
Une boutique qui a des années derrière elle accumule les modules comme un débarras accumule les cartons. On a essayé un module d'avis, on a changé de passerelle de paiement, on a installé quelque chose pour une campagne de Noël. On les a désinstallés depuis le back-office, mais les dossiers sont toujours là, dans modules/, avec tout leur code.
Ces dossiers, nous les appelons des modules orphelins. Ils n'apparaissent pas dans le gestionnaire de modules, personne ne les met à jour, et dans beaucoup de boutiques leur PHP répond toujours à quiconque l'appelle par URL.
Pourquoi ils deviennent orphelins
- Désinstaller n'est pas supprimer. Dans PrestaShop, désinstaller exécute le
uninstall()du module (qui retire ses tables et sa configuration), mais le dossier peut rester sur le disque. Le supprimer est une autre action, et elle est souvent oubliée. - Migrations et copies. Lors d'une migration ou d'une restauration, on copie des dossiers de modules qui ne sont jamais installés dans la nouvelle boutique.
- Envois par FTP. Quelqu'un a envoyé un module par FTP pour l'essayer et ne l'a jamais installé.
- Restes de thèmes. Certains thèmes commerciaux apportent leurs propres modules ; quand on change de thème, ceux de l'ancien restent.
Pourquoi ils représentent un risque
Du code vulnérable qui n'est jamais mis à jour
Un module installé, même ancien, apparaît au moins dans la liste, et quelqu'un peut voir qu'une mise à jour existe. Un orphelin n'apparaît nulle part. Si sa version avait une vulnérabilité connue, il l'aura pour toujours.
Leur PHP s'exécute toujours
C'est le point essentiel. Le fait que le module ne soit pas installé n'empêche pas ses fichiers de répondre. Beaucoup d'anciens modules contiennent des fichiers PHP prévus pour être appelés directement par URL : un ajax.php, un validation.php, un script d'import. Ces fichiers démarrent PrestaShop par eux-mêmes et font leur travail, qu'ils soient enregistrés ou non.
Dans PrestaShop 8 et les versions antérieures, le dossier modules/ ne comporte aucune protection par défaut empêchant l'exécution de ces .php. PrestaShop 9 inclut bien un .htaccess dans modules/ qui refuse les .php appelés directement, ce qui règle une grande partie du problème sous Apache et LiteSpeed. Mais les contrôleurs front qui passent par le dispatcher de PrestaShop restent accessibles si le module est installé, et sous Nginx le .htaccess est ignoré.
Une cachette confortable
Pour un attaquant, un dossier que personne ne regarde est l'endroit idéal pour laisser une porte dérobée. Un nouveau fichier dans un module orphelin a beaucoup moins de chances d'être remarqué qu'un fichier à la racine.
Comment les inventorier
L'idée est de croiser deux listes : les dossiers de modules/ sur le disque et les modules enregistrés dans la base de données.
- Récupérez la liste des modules enregistrés. Dans la base de données :
SELECT name, active, version FROM ps_module ORDER BY name; - Récupérez la liste des dossiers de
modules/, depuis le gestionnaire de fichiers de l'hébergement ou par SSH. - Les dossiers absents de la première liste sont orphelins. Notez pour chacun : s'il contient des fichiers
.phphors decontrollers/, sa version (dansconfig.xmlou dans le fichier principal) et la date de ses fichiers. - Distinguez les modules installés mais désactivés. Ceux-là figurent dans la liste, mais méritent aussi une vérification : s'ils ne servent pas, mieux vaut les désinstaller et les supprimer.
- Repérez les suspects. Un module à l'auteur inconnu, sans documentation, avec une compatibilité déclarée impossible ou une description qui ne décrit rien n'a probablement été installé par personne de votre équipe.
Comment les retirer sans casser le thème
Supprimer un dossier semble anodin, mais il arrive que quelque chose en dépende :
- Des templates du thème qui incluent des fichiers d'un module. Certains thèmes appellent directement des templates ou du CSS de modules précis. Cherchez le nom du module dans le dossier du thème avant de supprimer.
- Des overrides orphelins. Un module désinstallé peut avoir laissé dans
override/des fichiers qui s'exécutent toujours. Vérifiez ce dossier et, si vous retirez un override, videz aussi le cache des classes. - Des modules qu'un autre module utilise comme bibliothèque. C'est le cas de certains paquets qui partagent un dossier commun entre plusieurs modules du même auteur.
- Des crons externes qui appellent un fichier du module. Si le panneau de l'hébergement a une tâche planifiée qui pointe vers ce dossier, elle échouera ; mieux vaut le savoir avant.
La procédure sûre :
- Faites une sauvegarde des fichiers et de la base de données.
- Au lieu de supprimer, déplacez le dossier hors du répertoire web (ou renommez-le si vous n'avez pas d'autre choix) et laissez passer quelques jours.
- Parcourez la boutique, passez une commande de test, vérifiez le back-office et les journaux d'erreurs.
- Si rien ne s'est plaint, supprimez-le définitivement.
- Refaites l'inventaire tous les quelques mois, ou chaque fois que quelque chose est désinstallé.
Ce qu'il vaut mieux faire en plus
- Bloquez l'exécution directe de PHP dans
modules/si votre boutique est antérieure à PrestaShop 9, avec des exceptions uniquement pour les fichiers qui en ont vraiment besoin. - Analysez les orphelins avant de les supprimer : si l'un d'eux contient une porte dérobée, le supprimer sans plus vous laisse sans savoir comment ils sont entrés ni ce qu'ils ont fait d'autre.
- Profitez d'une migration pour repartir avec un
modules/propre : dans une nouvelle boutique, n'entre que ce qui est réellement installé. C'est l'un des avantages les moins évoqués du fait de quitter une 1.6 ou une 1.7 chargée d'années de restes.
Comment le résoudre dans PrestaShop
RKR Security Alert recherche dans modules/ les dossiers sans enregistrement dans la base de données et en gradue la gravité selon leur contenu : informatif s'il n'y a que des ressources, critique s'il y a du PHP accessible avec des découvertes. Il vérifie aussi quelles extensions le .htaccess de modules/ refuse réellement et les croise avec les points d'entrée qu'il trouve, pour savoir combien de fichiers de module n'importe qui peut appeler depuis l'extérieur, et il compte les modules installés qui ne sont pas couverts par la référence d'intégrité. Si vous préférez que nous nous en chargions, avec un forfait d'heures de support Rekire nous inventorions les modules de votre boutique, retirons ceux qui sont en trop en vérifiant qu'ils ne cassent pas le thème et vous laissons la liste de ce qu'il convient de mettre à jour.