Revenir au blog

Suivre et s’abonner

Qu’est-ce que Style Smuggler (CVE-2026-75650) ?

La vulnérabilité CVE-2026-75650 (StyleSmuggler) est une faille SSTI critique qui fait actuellement l’objet d’attaques sur des plateformes d’e-commerce. Découvrez en quoi elle consiste et comment les clients de Fastly peuvent s’en protéger.

Matthew Mathur
Matthew MathurIngénieur en sécurité, Fastly
Équipe de recherche en sécurité Fastly
Équipe de recherche en sécurité FastlyÉquipe de recherche en sécurité Fastly, Fastly

Aperçu

  • Sansec a découvert la vulnérabilité dans Adobe Commerce & Magento et a constaté qu’elle était déjà exploitée en conditions réelles avant même la publication des correctifs, dès le 4 septembre 2026

  • Adobe a publié l’avis de sécurité APSB26-146 le 7 septembre 2026 pour remédier à certains éléments de la chaîne de vulnérabilités

  • Fastly a publié un correctif virtuel pour la CVE-2026-75650 que les clients peuvent activer pour bloquer les requêtes visant la vulnérabilité

Analyse des vulnérabilités

La vulnérabilité CVE-2026-75650 est une faille de type « injection de modèle côté serveur sans authentification » (SSTI) qui conduit directement à l’exécution de code à distance (RCE). L’exploitation de cette vulnérabilité se déroule en trois étapes, réparties sur quatre requêtes : 

  1. Injection de code PHP dans les logs 

  2. Configuration du panier et ajout de la charge utile SSTI dans les informations d’adresse du panier 

  3. Exécution de la SSTI et déclenchement d’une RCE via un e-mail d’échec de paiement

Étape 1 : injection de code PHP dans les logs

La première étape consiste à injecter du code PHP non nettoyé sur le disque de la cible. Nous avons reproduit une méthode dans nos laboratoires, tandis qu’au moins une autre méthode confirmée a été observée en conditions réelles. Il est important de noter qu’il existe probablement de nombreuses autres façons de mener à bien cette étape. La variante que nous avons reproduite localement consigne un message d’erreur non échappé provenant d’un code de magasin invalide, préservant ainsi le code PHP malveillant intégré à la requête. Une requête ressemblerait à ceci :

POST /graphql HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
Store: <?=eval(base64_decode('{{payload_b64}}'));?>

{"query":"{ storeConfig { store_code } }"}

C’est dans l’en-tête « Store » que la charge utile est intégrée ; dans des conditions réelles, elle comprendra probablement du contenu encodé à des fins de contournement. Lorsque Magento consigne cette erreur, le <?= est consigné sans échappement, ce qui revêt une importance particulière lorsque nous aborderons l’étape 3. Le code PHP proprement dit variera au cours de l’exploitation.

Étape 2 : insertion d’une charge utile SSTI dans les coordonnées

La deuxième requête crée un panier d’invité, et la troisième requête, qui contient la charge utile SSTI, figure dans l’adresse de ce panier. La deuxième requête ne présente aucun intérêt particulier ; elle est donc omise par souci de concision.

Pour comprendre la charge utile SSTI, il est nécessaire de connaître certains aspects du moteur de modèles de Magento. Le moteur de modèles de Magento effectue la substitution de variables à l’aide de « directives » (par exemple, var, block), qui sont identifiées par des règles regex différentes pour chaque directive. Un « filtre » est chargé de traiter les directives et procède en deux passes. Lors de la première passe, un filtre résout toutes les directives qu’il peut, puis, lors de la deuxième passe, il traite les directives « différées » qui ont été signées par un filtre intégré. Lorsqu’une directive est traitée, qu’elle possède un filtre parent et que sa sortie est identique à la directive elle-même, elle est « signée » (c’est-à-dire *Sig*{{directive}}*Sig*) afin que le filtre parent puisse la résoudre. 

C’est là que les problèmes commencent. Lorsqu’une directive est signée, un str_replace est appliquée à la sortie pour remplacer la directive d’origine par la directive signée. Toutefois, la sortie inclut toutes les directives traitées précédemment, et pas seulement celle en cours. Voyons donc comment Style Smuggler utilise ces directives.

Style Smuggler utilise un modèle d’e-mail d’échec de paiement qui analyse les champs d’adresse à l’aide d’un filtre associé. Le filtre chargé de traiter l’adresse ne peut pas traiter les directives « block ». Nous envoyons donc les éléments suivants dans les champs d’adresse de la troisième requête :

rue : {{if postcode}}{{var postcode}}{{/if}}{{/var}}{{if postcode}}{{var postcode}}{{/if}}{{if city}}{{block class=Magento\\Email\\Block\\Adminhtml\\Template\\Preview}}{{/if}}

code postal : {{var postcode}}

Lorsque le code postal est traité par le filtre d’adresse, il correspond au contenu initial de la directive et est signé. Cependant, comme la fonction `str_replace` s’applique à l’ensemble de la sortie, les signatures apparaissent également aux endroits où nous avons inséré {{var postcode}} dans la partie « rue » de l’adresse. En raison d’une certaine confusion dans la règle regex d’identification des directives, l’adresse finale « traitée » est transmise au filtre d’e-mail contenant {{var postcode}}{{var postcode}}Sig{{blockclass=Magento\\Email\\Block\\Adminhtml\\Template\\Preview}}Sig<br /> Le filtre d’e-mail résout ensuite la directive « block » signée que nous avons dissimulée dans la partie rue de l’adresse. Avant le correctif d’Adobe, les directives « block » instancient la classe fournie, qu’il s’agisse ou non d’une classe « Block » ; nous assistons donc désormais à la création d’objets arbitraires.

Étape 3 : transformer la SSTI en RCE

À ce stade, nous disposons 1) d’un code PHP dans un logl et 2) d’une SSTI capable d’instancier des classes arbitraires. Pour relier ces deux éléments, il faut instancier une classe capable d’exécuter le code que nous avons inséré dans le log lors de la première étape. C’est là que le Magento\Email\Block\Adminhtml\Template\Preview inséré devient important. Il s’agit d’une classe capable de générer des modèles à partir des paramètres de requête « text », « styles » et « type ». Nous allons donc envoyer une requête avec les paramètres suivants (encodés en URL) :

texte : {{block class=Magento\Backend\Block\Widget\Grid\ColumnSet rowUrl=$this.template_styles cache_key=y}}

styles (formatés sous la forme d’un paramètre de requête encodé en JSON) :

 {
    "first": "../var/log/system.log",
    "generatorClass": "Aws\\S3\\S3Client",
    "region": "us-east-1",
    "version": "latest",
    "s3_us_east_1_regional_endpoint": "regional",
    "with_resolved": [
      {
        "instance": "Magento\\Setup\\Module\\Di\\Code\\Scanner\\ArrayScanner"
      },
      "collectEntities"
    ],
    "path": "dummy"
  }

type : 2

Dans cette requête, nous utilisons également la mutation graphql handlePayflowProResponse pour déclencher le traitement du modèle de paiement ayant échoué. Cela déclenche la chaîne d’événements suivante :

  1. Notre bloc « Preview » inséré précédemment est traité lors du traitement du modèle d’e-mail, ce qui entraîne la création de notre autre bloc « ColumnSet » à partir du paramètre de requête « text ».

  2. ColumnSet reçoit le tableau « styles » en tant qu’argument et appelle une instance « UrlGeneratorFactory » avec la classe de générateur que nous avons fournie, « Aws\S3\S3Client ».

  3. Lors de la création du S3Client, notre classe « Magento\Setup\Module\Di\Code\Scanner\ArrayScanner » est instanciée et appelle la méthode « collectEntities »

  4. collectEntities appelle « include » sur la valeur « first » que nous avons fournie dans le tableau styles, qui est notre fichier de logs corrompu. 

  5. Le code que nous avons placé dans le fichier de logs est exécuté lors de l’« include » (en raison du <?= non échappé), ce qui nous expose désormais à une vulnérabilité de type RCE. 

C’est de là que « Style Smuggler » tire son nom. Elle utilise le paramètre « styles » utilisé par la classe Preview pour introduire des informations supplémentaires relatives aux gadgets, nécessaires à l’exécution du code. Il est également important de noter qu’il est possible que d’autres gadgets exploitables existent au sein du code source de Magento et que nous avons identifié au moins une variante utilisant une charge utile différente de celle du bloc « Preview ».

Modèle Nuclei

Afin d’aider la communauté à tester les instances vulnérables à Style Smuggler, nous avons soumis un modèle Nuclei correspondant à la vulnérabilité CVE-2026-75650 au référentiel officiel nuclei-templates. Bien que nous ayons développé ce modèle nous-mêmes, nous avons attendu que Graycore publie une analyse détaillée de la vulnérabilité et que celle-ci soit validée par Sansec avant de le soumettre, afin d’éviter de divulguer des informations sur cette vulnérabilité qui n’avaient pas encore été rendues publiques. Nous avons testé ce modèle localement sur Magento v2.4.9 et v2.4.7-p2, afin de nous assurer qu’il fonctionnerait correctement sur plusieurs versions.

Correctif virtuel pour la CVE-2026-75650

Fastly a publié un correctif virtuel pour la CVE-2026-75650 qui couvre chaque étape de l’exploit Style Smuggler. Ce correctif offre une défense en profondeur contre les variantes présentes au sein d’une partie de la chaîne d’attaque et donne aux opérateurs le temps d’appliquer les correctifs à leurs systèmes. Ce correctif virtuel résiste aux faux positifs dans le cadre des opérations classiques, notamment lors des mises à jour des modèles d’administration, et n’a aucun lien avec les faux positifs décrits dans d’autres articles.

Prêt à commencer ?

Contactez-nous dès aujourd’hui