Web shells dans PrestaShop : ce que c'est, où elles se cachent et comment les trouver
Une web shell est la clé que l'attaquant laisse derrière lui pour revenir quand il veut. Nous expliquons où elles se trouvent habituellement dans une boutique PrestaShop, comment elles se déguisent, comment les rechercher avec méthode et ce qu'il faut vérifier en plus de les supprimer.
Quand quelqu'un s'introduit dans une boutique, la première chose qu'il fait n'est presque jamais de voler. La première chose, c'est de s'assurer qu'il pourra revenir. Pour cela, il dépose une web shell : un fichier PHP qui, appelé par URL, lui permet de lister des dossiers, de modifier des fichiers, de lancer des requêtes sur la base de données ou d'exécuter des commandes sur le serveur. Avec ça, même si vous corrigez la vulnérabilité par laquelle il est entré et changez tous les mots de passe, il restera à l'intérieur.
Cet article explique à quoi elles ressemblent, où elles se logent dans PrestaShop et comment les rechercher sans vous perdre dans les faux positifs.
Ce qu'est exactement une web shell
C'est un petit programme écrit dans le même langage que la boutique, qui s'exécute avec les droits de l'utilisateur web. Il n'a besoin d'exploiter rien d'autre : si le serveur exécute du PHP dans ce dossier, la shell fonctionne. Il en existe de toutes les tailles :
- Chargeurs d'une ligne. Trente ou quarante octets qui se contentent d'inclure un autre fichier. Le code malveillant se trouve dans cet autre fichier, qui porte souvent une extension d'image.
- Gestionnaires de fichiers complets. Une interface pour parcourir le serveur, modifier, téléverser, renommer et supprimer, protégée par un mot de passe écrit dans le fichier lui-même.
- Exécuteurs de commandes. Ils reçoivent un paramètre et le transmettent au système d'exploitation.
- Modules entiers. Un dossier avec la structure d'un module PrestaShop, un fichier principal irréprochable et la charge cachée dans un contrôleur.
Où elles se cachent dans PrestaShop
L'attaquant cherche des endroits où un nouveau fichier n'attire pas l'attention. Dans PrestaShop, il y a plusieurs classiques :
Fichiers en trop dans les modules natifs
Un ajax.php ou un config.php dans le dossier d'un module officiel qui, dans le paquet d'origine, ne contient pas ce fichier. Personne ne regarde à l'intérieur des modules livrés avec la boutique, et le nom paraît tout à fait banal. La seule façon de le repérer est de comparer le dossier avec le paquet publié par son auteur.
Modules orphelins
Des dossiers de modules désinstallés qui restent sur le disque. Ils n'apparaissent pas dans le gestionnaire de modules, personne ne les met à jour et leur PHP reste accessible par URL. C'est une cachette confortable et, en même temps, une porte d'entrée.
Le cœur et vendor/
Une ligne ajoutée à la fin d'un fichier du cœur (les classes produit, le dispatcher, l'autoloader) ou d'une bibliothèque de vendor/. Beaucoup de scanners excluent vendor/ parce qu'il génère du bruit, et c'est justement pour cela que c'est un bon endroit. Lors d'incidents réels, on a trouvé plus d'une dizaine de portes dérobées dans des fichiers légitimes d'une même boutique, toutes ajoutées à la fin et sans aucun mot suspect visible.
Images contenant du PHP
Un JPEG ou un PNG parfaitement valide, qui s'affiche dans n'importe quelle visionneuse, avec du code PHP ajouté à la fin. Seul, il ne s'exécute pas ; c'est un chargeur qui l'inclut qui l'exécute. Donc, si vous en trouvez un, cherchez aussi l'autre.
Dossiers de données
upload/, download/, img/ ou translations/ ne devraient jamais contenir de .php exécutable. S'il en apparaît un, il n'y a aucune explication innocente.
Comment elles se camouflent
Les shells qui durent des mois ne sont pas celles qui affichent eval(base64_decode(...)). Ce sont celles qui ressemblent à du code normal :
- Elles portent l'en-tête de licence de PrestaShop copié d'un autre fichier, avec son bloc de commentaires et sa garde de version au début.
- Elles portent un nom inoffensif :
uninstall.php,index.php,cron.php, ou un titre qui parle d'un lecteur de codes QR. - Elles construisent les noms des fonctions dangereuses à l'exécution, en prenant des lettres isolées dans une longue chaîne. Aucune fonction interdite n'apparaît dans le texte.
- Elles répondent 404 si elles ne reçoivent pas la bonne clé, exactement comme une URL qui n'existe pas. Parcourir la boutique en appelant des chemins ne les trouve pas.
- Elles conservent la date de modification du fichier d'origine, pour ne pas ressortir quand on trie par date.
Comment les rechercher avec méthode
L'ordre compte. Allez du plus concluant et du moins coûteux au plus coûteux :
- Est-il identique à celui publié par son auteur ? Comparez le cœur avec le ZIP officiel de votre version exacte (celui de la release, pas le dépôt, qui contient des dossiers de développement et produit des centaines de fausses différences) et chaque module avec son paquet. Un fichier identique octet par octet n'est pas infecté.
- Était-il dans le paquet ? Ce qui n'y était pas, quelqu'un l'a ajouté après. Cette question trouve des fichiers qu'aucun motif ne détecterait, car ils peuvent être impeccablement écrits.
- A-t-il changé depuis la dernière fois ? Si vous disposez d'une référence d'intégrité datant de l'époque où la boutique était saine, tout changement sans mise à jour derrière est une réponse.
- Que sait-il faire ? Pour ce qui n'a pas de référence : lister des répertoires et écrire des fichiers avec un chemin reçu en paramètre, exécuter des commandes, lire des fichiers système, des mots de passe comparés à un hash stocké dans le code lui-même.
- D'où peut-on l'atteindre ? Un contrôleur
controllers/front/d'un module s'appelle depuis Internet sans session ; un contrôleurcontrollers/admin/exige une session d'employé. C'est ce qui décide s'il faut agir ce soir ou demain.
Et une règle pour le bruit : si vous marquez quelque chose comme sûr, faites-le par le hash du contenu, pas par le chemin. Une exception par chemin continuera de masquer ce fichier le jour où quelqu'un le remplacera.
Pourquoi il ne suffit pas de la supprimer
Supprimer la shell est la dernière étape, pas la première. Avant d'y toucher :
- Faites une copie de la boutique en l'état, pour savoir ce qu'elle a fait et depuis quand.
- Vérifiez si d'autres portes ont été laissées. Des clés dans les
authorized_keysdes comptes du serveur, de nouveaux employés dans le back-office, des comptes webservice aux droits étendus et des tâches planifiées qui téléchargent et exécutent quelque chose toutes les quelques minutes. Supprimer un fichier ne ferme ni une clé SSH ni un cron. - Trouvez la voie d'entrée. Un module vulnérable, un mot de passe FTP volé, une version de PrestaShop non corrigée. Si vous ne la fermez pas, la shell revient en quelques jours.
- Changez les identifiants après le nettoyage, pas avant : base de données, FTP, panneau d'hébergement, employés et la clé des cookies si vous soupçonnez que la configuration a été lue.
Et une fois la boutique propre, l'habituel : PrestaShop, PHP et modules à jour. L'immense majorité des intrusions exploitent des failles déjà corrigées dans des versions que la boutique n'avait pas installées.
Comment le résoudre dans PrestaShop
RKR Security Alert analyse les fichiers de la boutique à la recherche de skimmers, de portes dérobées et de web shells, y compris celles qui n'ont pas de signatures dangereuses : il détecte les shells par ce qu'elles savent faire, les chargeurs qui incluent une image, le PHP caché dans des images valides et les fichiers dont les noms de fonction sont assemblés par index. Il compare le cœur avec le ZIP officiel, indique pour chaque découverte si elle est accessible par URL et sans session, et tient une référence d'intégrité qui n'est construite qu'une fois le premier audit marqué comme vérifié, pour ne pas valider une infection antérieure. Il prévient par Telegram, conserve les alertes dans la boutique et n'envoie aucun fichier hors du serveur. RKR Sentinel complète la surveillance en vous alertant des erreurs PHP, des réponses 500 et des paiements qui n'aboutissent pas à une commande, souvent le premier symptôme visible que quelque chose a été modifié.