Faille PolyShell Magento : ce que vous devez faire maintenant

PolyShell (APSB25-94) permet à n'importe qui d'uploader et d'exécuter du code sur votre boutique Magento sans authentification. Comment détecter une compromission et appliquer le patch.

8 min de lecture Par L'équipe Vesora

Le 17 mars 2026, la société Sansec a divulgué publiquement PolyShell, une faille critique dans Magento Open Source et Adobe Commerce. Elle permet à n’importe qui, sans compte ni authentification, d’uploader et d’exécuter du code arbitraire sur votre serveur.

Trois jours après la divulgation, l’exploitation de masse avait déjà démarré. Au 14 avril 2026, 82 % des boutiques Magento vulnérables avaient reçu des uploads malveillants. Aucun patch officiel n’existe pour les versions de production stables à ce jour.

Ce que fait PolyShell

PolyShell exploite le endpoint d’upload de fichier des options de panier dans l’API REST de Magento :

POST /rest/default/V1/carts/{cartId}/items

Ce endpoint accepte un objet file_info contenant un fichier encodé en base64, censé représenter une option produit de type “fichier joint”. Magento valide ce fichier en regardant uniquement son en-tête, pour détecter s’il s’agit d’une image.

L’attaque repose sur un fichier polyglotte : un fichier qui est simultanément une image valide et un script PHP exécutable. Il suffit de faire commencer le fichier par la signature GIF89a pour passer la validation, puis d’y glisser le payload PHP.

Trois lacunes de sécurité se cumulent :

  1. Aucune blacklist d’extension : les fichiers .php, .phtml et .phar sont acceptés
  2. Aucune vérification de l’option produit : l’upload se déclenche même si le produit n’a pas d’option de type fichier
  3. Validation MIME insuffisante : seul l’en-tête est contrôlé, pas le contenu réel

Le fichier uploadé atterrit dans pub/media/custom_options/quote/. Si la configuration du serveur web autorise l’exécution PHP dans ce répertoire, l’attaquant n’a plus qu’à appeler l’URL du fichier pour obtenir une exécution de code à distance (RCE).

Pour obtenir un SKU produit et un identifiant de panier invité, les seules données nécessaires à l’attaque, l’API GraphQL publique de Magento suffit. Aucun compte n’est requis.

Ce que les attaquants font une fois entrés

Les campagnes d’exploitation observées incluent :

  • Injection de skimmers JavaScript dans les pages CMS et les blocs statiques, pointant vers des domaines malveillants (lanhd6549tdhse.top, jslibrary.net, canevaslab.com) pour exfiltrer les données de paiement des visiteurs
  • Dépôt de backdoors nommés accesson.php dans plusieurs répertoires, pour garder l’accès même après un nettoyage partiel
  • Prise de contrôle complète du serveur quand la configuration PHP le permet

Versions affectées

  • Magento Open Source : toutes les versions jusqu’à 2.4.8 inclus
  • Adobe Commerce : toutes les versions jusqu’à 2.4.8 inclus

Le correctif est intégré dans la 2.4.9, actuellement en pré-release. Aucun patch isolé n’a été publié pour les versions de production stables, d’où l’importance des mesures ci-dessous.

Comment savoir si vous avez été attaqué

1. Scanner les fichiers uploadés suspects

Tout fichier .php, .phtml ou .phar dans pub/media/custom_options/ est un indicateur de compromission :

find pub/media/custom_options/ -type f \
  ! -name '.htaccess' \
  ! -name '*.png' \
  ! -name '*.jpg' \
  ! -name '*.gif' \
  ! -name '*.jpeg'

2. Chercher les backdoors

find . -name 'accesson.php' 2>/dev/null

3. Détecter les injections dans les pages CMS

grep -r "lanhd6549tdhse.top\|jslibrary.net\|canevaslab.com" pub/ app/ 2>/dev/null

Complétez avec une vérification directe en base de données sur les tables cms_block et cms_page :

-- Domaines malveillants connus
SELECT 'cms_block' AS source, identifier, title
FROM cms_block
WHERE content LIKE '%lanhd6549tdhse.top%'
   OR content LIKE '%jslibrary.net%'
   OR content LIKE '%canevaslab.com%';

SELECT 'cms_page' AS source, identifier, title
FROM cms_page
WHERE content LIKE '%lanhd6549tdhse.top%'
   OR content LIKE '%jslibrary.net%'
   OR content LIKE '%canevaslab.com%';

-- Balises <script> avec src externe (hors CDN légitimes)
SELECT 'cms_block' AS source, identifier, title
FROM cms_block
WHERE content REGEXP '<script[^>]+src=["\']https?://';

SELECT 'cms_page' AS source, identifier, title
FROM cms_page
WHERE content REGEXP '<script[^>]+src=["\']https?://';

-- Code JavaScript obfusqué (base64 inline ou eval)
SELECT 'cms_block' AS source, identifier, title
FROM cms_block
WHERE content LIKE '%eval(%'
   OR content LIKE '%atob(%'
   OR content LIKE '%String.fromCharCode%';

SELECT 'cms_page' AS source, identifier, title
FROM cms_page
WHERE content LIKE '%eval(%'
   OR content LIKE '%atob(%'
   OR content LIKE '%String.fromCharCode%';

Inspectez également vos pages CMS et blocs statiques depuis l’admin Magento à la recherche de balises <script> inattendues ou de code JavaScript obfusqué.

4. Vérifier les accès OAuth et les intégrations API

Une compromission PolyShell ne s’arrête pas à l’upload d’un backdoor. Les attaquants créent souvent des tokens OAuth, des consumers ou des intégrations API pour garder un accès à votre boutique après la suppression des fichiers malveillants. Ces accès leur permettent notamment de modifier vos blocs CMS via l’API REST.

Vérifiez en base de données les entrées suspectes :

-- Tokens OAuth actifs (trier par date de création décroissante)
SELECT ot.oauth_token_id,
       ot.token,
       ot.created_at,
       oc.name AS consumer_name,
       oc.callback_url
FROM oauth_token ot
JOIN oauth_consumer oc ON ot.consumer_id = oc.entity_id
ORDER BY ot.created_at DESC
LIMIT 20;

-- Consumers OAuth non reconnus
SELECT entity_id, name, `key`, callback_url, created_at
FROM oauth_consumer
ORDER BY created_at DESC;

-- Intégrations API créées (toutes, à auditer)
SELECT integration_id, name, email, endpoint, status, created_at
FROM integration
ORDER BY created_at DESC;

Comparez les dates de création avec la date d’incident suspectée. Tout token ou intégration apparu après cette date est à considérer comme compromis.

Depuis l’admin Magento, auditez et révoquez les accès non reconnus :

  • Intégrations : Système > Extensions > Intégrations, supprimez toute intégration inconnue
  • Tokens OAuth : révocables directement en base (DELETE FROM oauth_token WHERE oauth_token_id = ?) ou via l’API admin

5. Analyser les logs d’accès

Recherchez des requêtes POST suspectes vers le endpoint de panier avec un paramètre file_info contenant du base64 volumineux :

POST /rest/default/V1/carts/*/items

Une rafale de ces requêtes sur une courte période, venant d’adresses IP inconnues, est un signal d’alerte fort.

Surveiller les accès à /rest/V1/cmsBlock

Le endpoint /rest/V1/cmsBlock permet de créer, modifier et supprimer des blocs CMS via l’API REST. C’est l’un des vecteurs privilégiés pour injecter des skimmers JavaScript après une compromission : une intégration ou un token OAuth créé par l’attaquant suffit pour altérer vos blocs sans jamais passer par l’interface admin.

Ce qu’il faut surveiller :

  • PUT /rest/*/V1/cmsBlock/:id : modification d’un bloc existant
  • POST /rest/*/V1/cmsBlock : création d’un bloc
  • DELETE /rest/*/V1/cmsBlock/:id : suppression d’un bloc

Dans vos logs Nginx ou Apache, filtrez ces accès :

grep -E '"(POST|PUT|DELETE) /rest/[^/]+/V1/cmsBlock' /var/log/nginx/access.log \
  | awk '{print $1, $7, $9}' \
  | sort

Toute modification via l’API provenant d’une IP inattendue ou en dehors des plages horaires habituelles doit déclencher une investigation immédiate.

Mise en place d’une alerte préventive :

Si votre infrastructure le permet, configurez une règle dans votre WAF ou votre outil de monitoring pour alerter en temps réel sur tout appel POST/PUT/DELETE vers /rest/*/V1/cmsBlock. En production, vos blocs CMS ne devraient jamais être modifiés programmatiquement, sauf pendant un déploiement lancé par votre pipeline CI/CD.

Si vous n’utilisez pas l’API REST pour gérer vos blocs CMS, vous pouvez bloquer ce endpoint entièrement au niveau du serveur web :

# Nginx : bloquer les modifications CMS via l'API
location ~* ^/rest/[^/]+/V1/cmsBlock {
    limit_except GET {
        deny all;
    }
}
# Apache : restreindre aux GET uniquement
<LocationMatch "^/rest/[^/]+/V1/cmsBlock">
    <LimitExcept GET>
        Require all denied
    </LimitExcept>
</LocationMatch>

Comment patcher

Option A : le patch officiel Magento (priorité absolue)

Le correctif a été extrait directement du commit de correction intégré dans la 2.4.9. Il est applicable sur votre installation actuelle :

# Télécharger le patch
curl -O https://github.com/magento/magento2/commit/796c4ce195cee0814ac92e5a19fc2ecfa79dae69.patch

# Appliquer
patch -p1 < 796c4ce195cee0814ac92e5a19fc2ecfa79dae069.patch

Vérifiez en staging avant d’appliquer en production. Ce patch corrige les trois lacunes de validation décrites plus haut : blacklist d’extensions, vérification des option IDs et validation stricte du contenu uploadé.

Option B : bloquer au niveau du serveur web

Si le patch ne peut pas être appliqué immédiatement, bloquez l’exécution PHP dans le répertoire d’upload.

Pourquoi ne pas bloquer le endpoint /V1/carts/*/items directement ? Ce endpoint sert à tout ajout de produit au panier : le bloquer casserait le checkout pour tous vos clients. Ce qui distingue une requête PolyShell d’une requête normale, c’est le champ file_info dans le body JSON, que Varnish et Fastly n’inspectent pas. Bloquer le vecteur d’upload lui-même demande un WAF capable de lire le contenu des requêtes.

Nginx, à ajouter dans votre configuration de virtualhost :

location ~* ^/pub/media/custom_options/ {
    return 403;
}

Apache, dans votre .htaccess ou la configuration du virtualhost :

<Directory /var/www/html/pub/media/custom_options>
    php_flag engine off
    AddType text/plain .php .phtml .phar
    Deny from all
</Directory>

Redémarrez votre serveur web après modification. Cette mesure empêche l’exécution des fichiers déjà uploadés et limite le risque d’exploitation active.

Varnish / Fastly, à ajouter dans votre vcl_recv :

# PolyShell mitigation : recv snippet
if (req.url.path ~ "^/pub/media/custom_options/") {
    error 403 "Forbidden";
}

Si votre plan inclut le WAF Fastly Next-Gen, créez une règle personnalisée ciblant les requêtes POST vers /rest/*/V1/carts/*/items dont le body contient le champ file_info. C’est le seul moyen de bloquer l’upload sans casser le panier.

Option C : un module tiers

En dernier recours, si aucune des options précédentes n’est applicable dans votre environnement :

  • markshust/magento-polyshell-patch sur GitHub

Ce module Composer applique les corrections de validation directement dans le code Magento. À utiliser uniquement si le patch officiel (option A) ne peut pas être appliqué.

Si vous avez été compromis : procédure de nettoyage

  1. Isoler. Si l’infection est confirmée, passez la boutique en mode maintenance le temps du nettoyage.
  2. Supprimer les fichiers suspects. Videz pub/media/custom_options/ après avoir sauvegardé son contenu pour analyse.
  3. Supprimer les backdoors. Cherchez et supprimez tous les accesson.php et les autres scripts inconnus.
  4. Nettoyer les pages CMS. Retirez le JavaScript injecté depuis l’admin Magento.
  5. Révoquer les accès API. Supprimez les tokens OAuth, consumers et intégrations non reconnus (voir la section 4 ci-dessus).
  6. Réinitialiser les accès. Changez tous les mots de passe admin et invalidez les sessions actives.
  7. Auditer les logs. Remontez les logs d’accès pour repérer d’autres points d’entrée, notamment les appels à /rest/V1/cmsBlock.
  8. Appliquer le patch. Une fois la boutique nettoyée, patchez avant de la remettre en ligne.

Par où commencer

PolyShell est activement exploitée et ne demande aucune authentification. Si votre boutique tourne sur Magento 2.4.8 ou une version antérieure et que rien n’a encore été fait, lancez les commandes de détection ci-dessus : dix minutes suffisent pour savoir où vous en êtes. Appliquez ensuite le patch, ou le blocage serveur si le patch doit attendre.


Vous préférez qu’un expert audite votre boutique et applique le patch ? Contactez-nous, nous intervenons sous 48h.