O PoC do CVE-2026-44011: RCE no Craft CMS com um usuário autenticado.
Apenas para testes autorizados.
O aviso do Craft CMS lista >=4.0.0, <4.17.12 e >=5.0.0, <5.9.18 como afetados, e credita precicom-vincent-tl como descobridor.
python -m pip install -r requirements.txt
python cve-2026-44011.py -b 'https://example.com' -u '<username' -p '<password>' -c '<command>'
Argumentos obrigatórios:
-b, --base-url: URL do Craft, incluindo http:// ou https://.-u, --username: Nome de usuário do painel de controle.-p, --password: Senha do painel de controle.-c, --command: Comando a executar e capturar a saída.Argumentos opcionais:
-P, --cp-path: Caminho do painel de controle (padrão: /admin).-s, --site-id: ID do site (padrão: 1).-e, --element-type: Tipo de elemento (padrão: craft\elements\Category).-f, --csrf-field: Nome do campo CSRF de login (padrão: CRAFT_CSRF_TOKEN).-t, --timeout: Tempo limite de requisição e callback em segundos (padrão: 15).-F, --force: Continuar quando a versão do Craft estiver indisponível ou fora dos intervalos do aviso.-H, --callback-host: Endereço que o alvo consegue alcançar (endereço local inferido por padrão; sobrescreva-o atrás de um pivot).--listen-port: Porta do listener (padrão: uma porta livre selecionada pelo SO; defina uma porta fixa para encaminhamento).Na ação de busca vulnerável, condition vai do corpo do POST para a criação do objeto sem sanitização.
$conditionConfig = $this->request->getBodyParam('condition');
$condition = Craft::$app->getConditions()->createCondition($conditionConfig);
ElementCondition::setFieldLayouts() constrói um layout a partir de cada array fornecido.
if (is_array($fieldLayout)) {
$fieldLayout['type'] = $this->elementType;
return $fieldsService->createLayout($fieldLayout);
}
O payload do aviso anexa o AttributeTypecastBehavior do Yii com uma chave as e conecta um evento com on *. O behavior alcança Psy\Readline\Hoa\ConsoleProcessus::execute através do typecast de callable do Yii.
condition.fieldLayouts[]
-> FieldLayout behavior + event
-> AttributeTypecastBehavior::typecastValue()
-> call_user_func()
-> ConsoleProcessus::execute()
O controller corrigido aplica Component::cleanseConfig() à condição antes da criação do objeto.
ConsoleProcessus::execute() do Psy escapa metacaracteres de shell por padrão. O PoC serve um script temporário para executar -c, recebe sua saída em um listener HTTP embutido e desliga o listener depois. Use -H se o alvo não conseguir alcançar o endereço inferido.sh, curl e mktemp no alvo.python -m unittest discover -s tests -v.