Mise à jour — mai 2026. Peu après la première publication de ce retour d'expérience, la même boutique a de nouveau été touchée. La réinfection n'est pas passée par une porte dérobée que nous aurions manquée — elle est entrée par la porte principale : une faille non corrigée au niveau applicatif (une injection SQL dans le module Wishlist blockwishlist, enchaînée avec la RCE du cache MySQL Smarty, CVE-2022-36408) que notre nettoyage sur place avait contenue sans jamais la fermer. Supprimer le malware ne revient pas à fermer le vecteur d'entrée. La remédiation plus profonde, au niveau applicatif — appliquer des correctifs virtuels aux vulnérabilités précises et verrouiller l'origine derrière Cloudflare — fait l'objet d'un article à part, durcissement avancé de PrestaShop pour les boutiques que vous ne pouvez pas encore mettre à niveau. La conclusion reste la même : le confinement fait gagner du temps ; sortir de 1.7.x est le remède.
Il s'agit d'un incident réel survenu sur une boutique PrestaShop 1.7.x que nous avons remise en état. Les identifiants ont été anonymisés, mais le flux d'exécution, les emplacements des fichiers, la structure du payload et la logique de détection sont conservés exactement. L'objectif de ce retour d'expérience n'est pas de faire peur — c'est de donner aux autres propriétaires de boutiques et aux développeurs une référence concrète de ce à quoi ressemble, de l'intérieur, une attaque moderne de type Magecart sur PrestaShop, afin que vous reconnaissiez les mêmes formes dans vos propres fichiers en quelques minutes plutôt qu'en plusieurs jours.
Le propriétaire nous a contactés parce que la page de paiement affichait un formulaire de paiement qu'il ne reconnaissait pas. Il ressemblait à un formulaire de carte Stripe Elements. La boutique utilise bien Stripe, donc la ressemblance visuelle était suffisamment crédible pour que personne ne s'en inquiète pendant près de deux jours. Lorsque nous sommes intervenus, le skimmer copiait déjà discrètement les données de carte de chaque client arrivé au paiement. Cet article suit l'enquête dans l'ordre réel de son déroulement — premier indice, payload côté serveur, astuce d'exfiltration, JavaScript, compromission root, puis enfin point d'entrée — parce que cet ordre est précisément la leçon.
Le premier indice : un formulaire de paiement qui ne devrait pas exister

Stripe Elements affiche ses champs de carte dans des iframes cross-origin. La page parente ne peut pas lire ce que le client y saisit — cette isolation est toute la raison d'être d'Elements, et c'est elle qui empêche une vitrine compromise de siphonner un formulaire Stripe correctement intégré. La première question à se poser devant un skimmer présumé est donc simple : les champs de carte sont-ils dans une iframe, ou sont-ils des champs bruts directement sur la page ?
Le formulaire que nous avions sous les yeux utilisait des champs HTML bruts, servis en first-party :
| Champ injecté | Ce que cela indique |
|---|---|
<input id="cardNumber" onkeyup="smenu(this)"> | Aucune iframe — la page parente peut lire chaque frappe |
<input id="cc_cid" onkeyup="smenu(this)"> | Un gestionnaire onkeyup sur chaque champ, qui appelle une fonction personnalisée smenu() |
<button onclick="processF()">PLACE ORDER</button> | Un gestionnaire d'envoi personnalisé qui contourne le véritable module de paiement |
Trois signaux immédiats : pas d'iframes, un gestionnaire de frappe sur chaque champ, et un léger décalage de langue entre le formulaire injecté et le reste de la boutique. Le module Stripe légitime était toujours installé et configuré — le faux formulaire avait simplement été peint par-dessus. L'intérêt de connaître cette règle simple (les vraies passerelles utilisent des iframes ; des champs de carte bruts sur une page de paiement PrestaShop sont presque toujours malveillants), c'est que n'importe quel marchand peut faire la vérification lui-même, aujourd'hui, avec l'inspecteur du navigateur et sans outil spécialisé — voir la liste des indicateurs à la fin de cet article.
Retrouver le payload côté serveur
Un keylogger dans le navigateur n'a d'intérêt que s'il peut envoyer quelque part ce qu'il capture. Nous avons passé tout le répertoire config/ au crible à la recherche de motifs suspects et avons trouvé le même bloc ajouté en tête de chaque fichier PHP qu'il contenait : un extrait qui surveillait la présence d'un champ $_POST['order_llx'] et, lorsqu'il le voyait, transmettait son contenu via curl vers deux URL encodées en base64, avec CURLOPT_SSL_VERIFYPEER désactivé, puis supprimait le champ pour que rien en aval ne le remarque.
Treize fichiers dans config/ contenaient ce bloc, et tous partageaient le même horodatage de changement d'inode — à la seconde près. L'attaquant avait scripté le déploiement. Les deux chaînes base64 se décodaient en adresses IP de deux serveurs chez un grand fournisseur cloud asiatique : le point d'exfiltration. Un fichier, settings.inc.php, avait été remplacé en entier — il ne restait que le code malveillant — et la boutique continuait pourtant de fonctionner, car sous PrestaShop 1.7 la vraie configuration de base de données se trouve dans app/config/parameters.php, pas dans le fichier obsolète settings.inc.php. L'attaquant le savait, ou il a eu de la chance.
L'astuce d'exfiltration en deux étapes
La partie vraiment habile de cette attaque tient à la manière dont les données sortent. La plupart des Content Security Policies, bloqueurs de publicité et extensions anti-skimmer sont conçus pour repérer un navigateur qui parle directement au serveur d'un attaquant. Ce skimmer ne le fait jamais. La boutique compromise sert de relais :
- Étape 1 (navigateur → boutique). Le gestionnaire
processF()du faux formulaire envoie en POST les données de carte capturées vers/sur le propre domaine du client, dans un champ nomméorder_llx. Du point de vue du navigateur, c'est un trafic first-party ordinaire — même origine, pas de CORS, rien qu'une CSP limitée aux tiers puisse signaler. - Étape 2 (boutique → C2). Le PHP injecté dans
config/intercepte ce champ côté serveur et le transmet viacurlaux IP de l'attaquant. C'est une requête serveur à serveur que le navigateur ne voit jamais : elle n'apparaît ni dans DevTools, ni dans l'onglet réseau, ni pour un administrateur réseau qui surveille la connexion du client.
Toute l'évasion est là. Un administrateur réseau voit une connexion vers la boutique légitime et arrête d'enquêter ; une CSP qui bloque seulement les scripts tiers ne détecte rien. Ce relais same-origin est l'une des formes de Magecart les plus difficiles à repérer côté client. Il faut être honnête : ce n'est pas la seule forme — Sansec et d'autres acteurs de veille continuent d'observer en parallèle de l'exfiltration directe depuis le navigateur, du stockage caché côté serveur et des variantes à récupération différée, sans modèle unique dominant — mais le relais est celui qui contourne la plupart des défenses client prêtes à l'emploi.
Le skimmer JavaScript, et l'écart de taille qui l'a trahi
Le faux formulaire lui-même se trouvait dans le thème. Nous avons recherché les jetons uniques déjà observés — cc_owner, processF, smenu — et trouvé l'injection ajoutée à la fin du fichier ps_shoppingcart.js du thème. À lui seul, l'écart de taille du fichier était la preuve flagrante : un ps_shoppingcart.js propre pèse environ 2,7 Ko, tandis que la copie infectée faisait autour de 340 Ko. Un bloc de 337 Ko avait été copié-collé à la fin de 74 fichiers JavaScript différents dans le thème parent et le thème enfant — chaque theme.js, chaque custom.js, chaque script front-office de module dans les dossiers de modules intégrés au thème.
Le payload était obfusqué, mais sans grande finesse : un tableau de chaînes encodées en hexadécimal (nommé _0x5aa5, 225 entrées) était référencé par index dans tout le code, de sorte que document[_0x5aa5[39]](_0x5aa5[158]) se résolvait simplement en document.getElementById("cardNumber"). Décoder le tableau révèle toute l'intention — entrées pour cardNumber, exp-date, cc_owner, cc_cid, les champs de facturation, le nom du champ d'exfiltration order_llx et le tag de campagne Zhang. Le skimmer assemble une chaîne séparée par des barres verticales avec tous les champs capturés, l'encode en hexadécimal, l'enveloppe en base64, puis l'envoie en POST sous forme de FormData vers /. Plusieurs champs leurres (products_hash, amount_hash, billing_hash) sont ajoutés comme bruit aléatoire, si bien que le POST ressemble dans les journaux à un beacon analytique ordinaire.
Le piège des assets compilés (spécifique à PrestaShop)
Nous avons remplacé le fichier ps_shoppingcart.js infecté par une copie propre. Le faux formulaire apparaissait toujours. C'est le piège qui attend spécifiquement ceux qui nettoient une boutique PrestaShop ; il mérite donc d'être bien compris.
Le pipeline CCC de PrestaShop (Combine, Compress, Cache) regroupe les scripts front-office enregistrés pour la page courante — tout ce qui est déclaré via registerJavascript sans async/defer — dans des fichiers combinés comme bottom-<hash>.js sous themes/<theme>/assets/cache/. Les scripts infectés étaient enregistrés exactement ainsi, si bien que le code malveillant avait été cuit dans les bundles compilés tant que la source était encore infectée. Tant que nous n'avions pas purgé ce répertoire de cache, le navigateur continuait de recevoir le skimmer depuis le bundle compilé, quoi que nous fassions au fichier source. La correction consistait à remplacer tout l'arborescence themes/ depuis une source connue comme propre et à purger tous les caches d'assets — themes/<theme>/assets/cache/, var/cache/ et var/compile/ — ainsi que tout cache objet Redis ou Memcached. En dessous de cela, les bundles peuvent se régénérer depuis une source infectée.
Le problème plus grave : la compromission root
En cherchant d'autres payloads de skimming, nous avons lancé find / -perm -4000 -type f et découvert une mauvaise surprise : deux binaires ELF dans le webroot, déguisés avec des extensions .js. Bit SUID activé, propriétaires root, 1,7 Mo chacun, SHA256 identique — et pas du JavaScript du tout, mais des exécutables ELF x86_64 (file indiquait setuid ELF 64-bit LSB executable, statically linked, stripped). Quatre autres binaires SUID-root se trouvaient dans /usr/bin avec des noms aléatoires, plus un nommé pkexem — une faute d'une lettre sur le pkexec légitime, conçue pour passer sous le radar d'un simple ls.
C'est le moment où l'incident a changé de catégorie. Créer un binaire SUID root nécessite root. Du PHP exécuté comme utilisateur du site ne peut pas le faire, même avec disable_functions vide ou open_basedir très permissif. La simple existence de ces fichiers prouvait que root avait été compromis, et pas seulement l'utilisateur web — ce qui signifie que nettoyer le webroot ne peut jamais suffire, car la persistance peut se cacher n'importe où sur l'hôte. Pour un propriétaire de boutique, la traduction pratique est directe : à ce stade, le seul état final pleinement défendable consiste à reprovisionner depuis une image OS propre, migrer le code et les données vérifiés comme propres, renouveler tous les secrets, et traiter l'hôte d'origine comme une surface de confinement temporaire maintenue en vie uniquement le temps de continuer à servir les clients.
Le vrai point d'entrée : un web shell dans index.php
Nous avions nettoyé le skimmer et retiré les binaires backdoor, mais nous ne savions toujours pas comment l'attaquant était entré au départ. Les journaux d'accès montraient une IP envoyant des requêtes POST / pendant plusieurs semaines, et les tailles de réponse formaient l'empreinte :
| Taille de réponse | Ce que faisait l'attaquant |
|---|---|
| ~46 KB | Page d'accueil complète — sondes d'exploitation avec les mauvais paramètres |
| 1–2 KB | Sortie de commandes (ls, cat, whoami) — reconnaissance |
| ~695 B | Confirmations d'écriture de fichiers — dépôt du payload |
| ~36 KB | Une réponse plus grande, toujours très loin d'un dump de base de données |
Cette distribution nous apprenait deux choses. Premièrement, POST / était lui-même un point d'exécution de code — des requêtes ordinaires vers la page d'accueil ne produisent pas un flux régulier de confirmations d'écriture de fichiers de 695 octets. Deuxièmement, un export complet de la table clients aurait atteint au minimum plusieurs centaines de kilo-octets, et rien dans les journaux ne s'en approchait ; l'attaquant utilisait le shell pour écrire des fichiers, pas pour extraire des données en masse. Ce décalage est un élément réellement rassurant à présenter à un propriétaire inquiet, et c'est le type de constat que les journaux d'accès donnent gratuitement si l'on sait lire la taille des réponses plutôt que le seul code de statut.
Le point d'accès nous a menés à index.php. La copie du site en production avait été nettoyée à un moment donné (probablement lors d'une tentative de reprise antérieure), mais un site de développement dans un répertoire voisin partageant le même docroot conservait encore l'original. Il commençait par un loader obfusqué : une seule chaîne littérale servant d'alphabet, avec les noms de fonctions dangereuses (create_function, assert, base64_decode) épelés caractère par caractère par indexation dans cette chaîne — de quoi échapper à un grep naïf. Le loader décodait un petit payload base64, construisait à l'exécution une fermeture PHP exécutable, puis l'appelait. Le payload décodé était le web shell lui-même : toute requête dont le paramètre product_id correspondait à un hash MD5 codé en dur pouvait exécuter via eval() du PHP arbitraire transmis dans le paramètre image_id. Les noms de paramètres sont délibérément choisis pour ressembler, dans les journaux, à du trafic e-commerce ordinaire.
Un détail mérite sa propre phrase, car c'est un cadeau accidentel de la mise à niveau : le loader dépend de create_function et de l'évaluation de chaînes via assert(), deux mécanismes supprimés par PHP en 8.0. Sur un hébergement PHP 8 moderne, cette backdoor provoquerait une erreur fatale d'elle-même. Déplacer ce code vers PHP 8 casserait involontairement le shell — une raison de plus pour laquelle la vraie correction consiste à avancer, pas à déplacer le problème de côté.
La chronologie, et ce qu'elle implique
Nous n'avons pas pu dater la pose initiale du web shell — elle était antérieure à la conservation disponible des journaux — mais le reste se reconstruit proprement à partir des horodatages de fichiers et des journaux d'accès :
| Jour par rapport à la découverte | Événement | Preuve |
|---|---|---|
| −60 ou avant | Web shell déposé dans index.php | Antérieur à la conservation des journaux |
| −25 | Binaires SUID-root déposés dans le webroot | Horodatages de création des fichiers |
| −22 | Binaires SUID-root déposés dans /usr/bin | Horodatages de création des fichiers |
| −10 à −5 | Reconnaissance via le web shell | Réponses POST /, 695–1844 o |
| −2 | Skimmer JS déployé dans 74 fichiers du thème | Horodatages de changement d'inode |
| −2 (≈30 min plus tard) | Skimmer PHP déployé dans 13 fichiers de configuration | Horodatages de changement d'inode |
| 0 | Le propriétaire signale le formulaire suspect | Inspection visuelle |
L'écart de 25 jours entre la compromission root et le déploiement du skimmer est la ligne la plus parlante de ce tableau. Il correspond à un schéma où l'accès initial et la monétisation sont deux étapes distinctes — l'accès arrive d'abord, le payload de skimming de cartes plusieurs semaines plus tard. Nous ne pouvons pas prouver à partir de ces seuls éléments si l'accès a été vendu à un second groupe ou simplement mis en file d'attente par le même opérateur traitant une liste de cibles, mais pour un défenseur la leçon est la même : les semaines silencieuses ne sont pas une sécurité, ce sont un compte à rebours. Une boutique qui détecte l'intrusion pendant ces semaines ne perd rien ; une boutique qui attend le symptôme perd toutes les cartes traitées entre-temps.
Remédiation, dans l'ordre qui compte
Deux contraintes ont structuré cette reprise, et ce sont celles que rencontrent la plupart des vraies boutiques. Le site était en ligne et traitait des commandes, il ne pouvait donc pas rester indisponible pendant des heures. Et une migration 1.7.x → 8.x/9.x est un projet de plusieurs semaines — compatibilité des modules, refonte du thème, recâblage du paiement — pas une opération d'une journée. Le plan était donc de contenir et durcir immédiatement, tout en préparant en parallèle une reconstruction propre. Le runbook complet étape par étape (préservation des preuves, rotation des identifiants, recherche de backdoors, blocage des IP C2 au pare-feu, suppression des outils d'administration exposés, réglage du WAF) fait l'objet d'un document à part — nous le maintenons dans la checklist de durcissement de sécurité PrestaShop afin qu'il reste à jour. Ce qui est propre à cet incident, et mérite d'être retenu, c'est l'ordre et quelques gestes adaptés à PrestaShop :
- Préservez les preuves avant de toucher quoi que ce soit. Faites un snapshot du disque (ou au minimum une archive tar du webroot, de
/etcet de/var/log), archivez les journaux d'accès et d'erreur, et calculez lesha256sumde chaque fichier suspect. Vous en aurez besoin pour le post-mortem, pour toute demande du prestataire de paiement, et pour l'inévitable second passage lorsque vous trouverez une backdoor que vous aviez manquée. - Arrêtez d'abord l'hémorragie visible côté client. Retirez l'injection PHP des 13 fichiers de configuration, restaurez
config/settings.inc.phpdepuis une copie propre de la même version exacte de PrestaShop (et concentrez la rotation DB/cookies surapp/config/parameters.php, où PS 1.7+ stocke réellement cette configuration), remplacez toute l'arborescencethemes/depuis une source propre, puis purgez tous les répertoires de cache et l'OPcache — sinon les bundles compilés continuent de servir le skimmer, comme expliqué plus haut. - Ensuite, traquez la persistance sur tout l'hôte, pas seulement dans le webroot. Comme root a été compromis, les artefacts dangereux peuvent se trouver dans
/etc/cron*, les timers et unités systemd, le fichier~/.ssh/authorized_keysde chaque utilisateur,/etc/sudoers.d/, les profils shell, les fichiers de vhost, ainsi que dans la table MySQLmysql.useret dans tout nouvel événement ou trigger. Tout ce qui a été modifié pendant la fenêtre de compromission est suspect. - Rendez les fichiers de point d'entrée immuables. Appliquez
chattr +isurindex.phpet tous les fichiersconfig/*.php. Un futur web shell ne pourra pas réécrire un fichier immuable sans exécuter d'abordchattr -i, ce qui nécessite root. (Attention : cela ne fonctionne que sur les systèmes de fichiers qui prennent en charge les attributs étendus — ext4/xfs/btrfs conviennent ; certaines configurations en overlay de conteneurs et ZFS non.)
Dès que root a été touché, un nettoyage sur place est du confinement, pas une guérison — et si le vecteur de réinfection est une vulnérabilité applicative non corrigée plutôt qu'un fichier oublié, le runbook ci-dessus ne vous sauvera pas. Ce problème de couche applicative (correctifs virtuels sur des CVE précises, verrouillage de l'origine derrière Cloudflare, confinement correct du runtime PHP) est exactement le sujet du guide durcissement avancé de PrestaShop pour les boutiques que vous ne pouvez pas encore mettre à niveau. Et si des données de carte ont atteint le C2 — partez du principe que oui jusqu'à preuve du contraire — vos obligations de signalement au prestataire de paiement commencent immédiatement ; la séquence complète est dans notre guide de réponse à une violation de données.
Indicateurs de compromission — quoi rechercher avec grep
Lancez la recherche depuis la racine de la boutique et traitez tout résultat comme un élément à inspecter, pas comme une preuve automatique en soi :
rg -n "order_llx|processF|smenu|cc_owner|cc_cid|CURLOPT_SSL_VERIFYPEER|base64_decode" \
config themes modules
find config themes modules -type f \( -name '*.php' -o -name '*.js' \) -mtime -14 -ls
Si vous exploitez une boutique PrestaShop et voulez vérifier cette famille précise, voici l'ensemble à fort signal. Lancez les greps récursifs lourds sur un snapshot ou en lecture seule lorsque c'est possible — un scan intensif sur un webroot très sollicité peut provoquer un pic d'I/O et déclencher ses propres alertes.
| Où chercher | Indicateur |
|---|---|
| Source PHP / JS | rg -n "order_llx|_0x5aa5|processF|smenu|__Pres_[il]dk" /var/www |
| Injection dans les fichiers de configuration | Le littéral @deprecated 1.7$ar=[ ajouté en tête de fichiers dans config/ |
| Loaders obfusqués | Chaînes eval(base64_decode(…)), assert(base64_decode(…)) ou create_function(…base64…) |
| Backdoors SUID | find / -perm -4000 -type f 2>/dev/null (à exécuter en root) |
| ELF déguisé en JS | find /var/www -name '*.js' -exec file {} + | grep ELF |
| Persistance par prepend | auto_prepend_file / auto_append_file dans .htaccess ou .user.ini |
Et dans le navigateur, sur la page de paiement rendue : des champs <input> bruts avec les IDs cc_owner, cardNumber, cardExpiry ou cc_cid (les vrais formulaires Stripe/Adyen/Braintree utilisent des iframes — les champs de carte bruts sont le signal d'alerte), des cookies nommés __Pres_idk ou __Pres_ldk en cours de création, et un index.php qui commence par une variable obfusquée de style <?php $e4d6=, avec une lettre suivie d'hexadécimal immédiatement après la balise d'ouverture. Le tag de campagne Zhang (base64 Wmhhbmc=) apparaît dans le payload d'exfiltration, mais il est trop générique pour être fiable seul — ne lui donnez du poids que s'il coexiste avec un autre indicateur ci-dessus. Pour des balayages plus profonds, pointez php-malware-finder, les règles YARA publiques de Sucuri/ESET ou un moniteur d'intégrité de fichiers (AIDE, Wazuh, OSSEC) sur le webroot — mais ignorez les scanners spécifiques à Magento ; leurs signatures ne correspondront pas à une attaque taillée pour PrestaShop.
Ce que cet incident raconte vraiment
Le web shell était la plaie. Le skimmer était le symptôme visible. Nettoyer le skimmer sans trouver le shell aurait laissé la porte grande ouverte pour redéployer le même payload — ou un plus intelligent — en quelques jours, ce qui est précisément la manière dont la réinfection mentionnée au début de cet article s'est produite. L'habitude la plus importante que cet incident enseigne est de continuer à tirer le fil : un faux formulaire de carte mène à des fichiers de configuration injectés, qui mènent à un piège de bundle compilé, qui mène à des binaires SUID-root, qui mènent à un web shell dans index.php. Si vous vous arrêtez à n'importe quelle couche avant la dernière, vous avez nettoyé un symptôme, pas fermé une attaque.
Et si vous exploitez encore PrestaShop 1.7.x aujourd'hui, le constat honnête est le suivant : vous êtes une cible, et les exploits utilisés pour déposer le shell initial sont anciens, bien connus et intégrés à des scanners automatisés. Migrer vers une branche PrestaShop prise en charge et entièrement corrigée — avec tous les modules et thèmes à jour, et l'hôte reconstruit puis durci — est la voie durable. Entre-temps — dans les faits, plusieurs semaines ou mois pour une boutique non triviale — les mesures de durcissement de la checklist de durcissement et les mesures applicatives du durcissement avancé pour les boutiques que vous ne pouvez pas encore mettre à niveau ne vous rendent pas invincible, mais ensemble elles augmentent le coût de l'attaque et — tout aussi précieux — rendent une intrusion suffisamment bruyante pour vous donner une vraie chance de la détecter pendant les semaines silencieuses, plutôt qu'après la disparition des cartes.
Références officielles PrestaShop
Pour les recommandations officielles, consultez l'alerte de sécurité de PrestaShop sur les skimmers numériques, l'article du projet sur une vulnérabilité majeure de sécurité sur les sites PrestaShop, la note de 2025 sur les attaques par injection SQL et le JavaScript injecté, ainsi que les bonnes pratiques de sécurisation d'une boutique de PrestaShop. Aucun de ces contenus ne décrit cet incident précis, mais ils constituent un contexte officiel utile pour les vérifications de skimmers, la rotation des identifiants et les obligations d'escalade.
Questions fréquentes
Comment savoir si ma propre page de paiement contient un skimmer comme celui-ci ?
Ouvrez votre page de paiement en production dans un navigateur, faites un clic droit sur les champs de carte et inspectez-les. Un formulaire Stripe, Adyen ou Braintree correctement intégré place les champs de carte dans des iframes cross-origin — la page parente ne peut pas les lire. Si vous voyez à la place des champs first-party <input> bruts avec des IDs comme cardNumber, cc_owner ou cc_cid directement sur la page, c'est le signal d'alerte. Lancez ensuite les greps de la section des indicateurs ci-dessus sur un snapshot de vos fichiers. Un résultat isolé est quelque chose à inspecter, pas une preuve automatique.
J'ai supprimé le malware. Pourquoi le faux formulaire est-il revenu ?
Deux pièges spécifiques à PrestaShop. D'abord, le pipeline CCC cuit les scripts infectés dans des bundles compilés sous themes/<theme>/assets/cache/ — tant que vous ne purgez pas ce cache (ainsi que var/cache/, var/compile/ et tout Redis/Memcached), le navigateur continue de recevoir le skimmer depuis le bundle, quoi que vous fassiez à la source. Ensuite, plus grave : si le vecteur d'entrée — un web shell, un module non corrigé — reste ouvert, l'attaquant redéploie tout simplement. Nettoyer les fichiers, c'est du confinement, pas une guérison.
Nous avons trouvé des binaires SUID-root. À quel point est-ce grave ?
Créer un binaire SUID-root nécessite root — du PHP exécuté comme utilisateur du site ne peut pas le faire, même avec disable_functions ou open_basedir très verrouillés. Leur existence prouve que root a été compromis, pas seulement l'utilisateur web ; la persistance peut donc se cacher n'importe où sur l'hôte. À ce stade, le seul état final pleinement défendable consiste à reprovisionner depuis une image OS propre, migrer le code et les données vérifiés comme propres, et renouveler tous les secrets — en traitant l'hôte d'origine comme un confinement temporaire.
Les données de carte des clients ont-elles réellement été volées ?
Dans cet incident, le motif des tailles de réponse dans les journaux d'accès suggérait que le shell avait été utilisé pour écrire des fichiers, pas pour exporter la base de données en masse — un dump complet de la table clients aurait atteint plusieurs centaines de kilo-octets, et rien ne s'en approchait. Mais le skimmer navigateur est resté actif pendant près de deux jours, donc toute carte saisie au paiement pendant cette fenêtre doit être considérée comme capturée. Partez du principe qu'il y a eu exposition jusqu'à preuve du contraire, et lancez immédiatement le signalement à votre prestataire de paiement — la séquence est dans notre guide de réponse à une violation de données.
Je suis encore en 1.7.x et je ne peux pas migrer avant plusieurs mois. Que faire maintenant ?
Vous êtes une cible, et les exploits utilisés ici sont anciens et intégrés à des scanners automatisés — mais vous n'êtes pas sans défense pendant l'intervalle. Appliquez des correctifs virtuels aux failles précises que vos journaux indiquent, verrouillez l'origine derrière un WAF, confinez le runtime PHP et ajoutez une surveillance d'intégrité des fichiers afin qu'une deuxième tentative soit bruyante. Le plan complet de transition est le durcissement avancé pour les boutiques que vous ne pouvez pas encore mettre à niveau, avec la base dans la checklist de durcissement.
Continuer la lecture
- Durcissement avancé de PrestaShop pour les boutiques que vous ne pouvez pas encore mettre à niveau — fermer le vecteur applicatif que ce nettoyage avait contenu sans jamais le fermer.
- Durcissement de sécurité PrestaShop : la checklist complète — le runbook de base complet, maintenu à jour.
- Réponse à une violation de données : que faire si votre boutique est piratée — la séquence des premières heures, obligations RGPD incluses.
Commentaires
Aucun commentaire pour le moment. Soyez le premier !
Soyez le premier à poser une question ou à partager un retour utile.
Laisser un commentaire
Partagez une question, un détail de pose ou un retour qui pourrait aider un autre lecteur.