
Drupal 11.4.8 - Alta - Remoto - XSS - Move Block: rótulos irmãos ignoram o escape de @label
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · drupal-move-block-markup
Write-up: https://abraxaslabs.tech/research/drupal-move-block-markup
Classe: XSS Armazenado Alcance: Remoto
Drupal core 11.4.8 (61044508) - Drupal
SA-CORE-2026-012 alterou a linha atual de Move Block para t('@label (current)'), que passa por Html::escape(). As linhas irmãs na mesma região ainda atribuem BlockPluginTrait::label() diretamente a #markup em MoveBlockForm. Esse label é configuration['label'], um campo de texto bruto. Renderer::ensureMarkupIsSafe então aplica o filtro XSS a uma string com a lista de tags de admin, de modo que um <b> (e outras tags de admin) sobrevive.
Um editor do Layout Builder que consegue definir o título de um bloco como HTML alcança outro editor ou admin que abre Move em um bloco diferente naquela região. XSS armazenado no diálogo Move. Não é RCE nem LPE.
| ID | ainda sem CVE |
| Classe | XSS Armazenado |
| Alcance | Remoto (configuração de bloco do Layout Builder; a vítima abre Move Block) |
| CWE | CWE-79 |
| CVSS | Médio: 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
| Produto | Drupal core |
| Afetado | 11.4.8 (61044508071749629aaf3380aa85971e94df9e84) |
| Autenticação | Configuração de bloco do Layout Builder. A vítima abre Move Block. |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1 |
Autor: usuário que pode posicionar ou configurar blocos do Layout Builder (não configuração do site). Vítima: outro editor de LB ou admin que abre Move em um bloco diferente na mesma região.
| Privilégio | Método / sink | Tipo | Comprovado em lab ou inferido |
|---|---|---|---|
| Imprimir HTML do atacante na linha irmã do diálogo Move | $label['#markup'] = $plugin->label(); depois ensureMarkupIsSafe | Integridade do HTML | Comprovado em lab. O HTML irmão é <b class="lb-sib">DRUPAL-MOVE-BLOCK-MARKUP-WITNESS</b> |
Manter marcação de tags de admin (<b>, e o restante de Xss::getAdminTagList) | a string #markup é filtrada por XSS com a lista de admin, não escapada | Integridade do HTML | Comprovado em lab para <b> |
| Sessão / ações como o editor vítima na origem do Layout Builder | XSS armazenado naquele diálogo | Integridade da sessão da vítima | Inferido. O lab para em HTML bruto na célula irmã |
| Negativo: linha atual | t('@label (current)', ...) | Fechado | Comprovado em lab. <em class="lb-cur">... |
Negativo: irmã via @label | caminho do gadget corrigido | Fechado | Comprovado em lab. <b class="lb-sib">... |
Fechado neste resíduo: instalação de site Drupal ao vivo (este lab é um gadget); roubo de sessão da UI do Layout Builder como oráculo HTTP medido; RCE; LPE. Visitantes não autenticados não conseguem abrir Move Block.
Mesmo resíduo de pin: AttributeXss HTMX attrs.
Fixe o Drupal 11.4.8 após o SA-CORE-2026-012. O advisory fechou o título do bloco atual. MoveBlockForm.php 210-218:
if ($is_current_block) {
$label['#markup'] = $this->t('@label (current)', ['@label' => $plugin->label()]);
// ...
}
else {
$label['#markup'] = $plugin->label();
}
BlockPluginTrait::label() retorna configuration['label'] quando definido. Renderer::ensureMarkupIsSafe não aplica filtro XSS a MarkupInterface (@label já escapado). Uma string bruta é filtrada com a lista de tags do admin.
Caminhos errados já registrados: tratar a linha atual como ainda bruta (não é); afirmar que isto é RCE; um site Drupal ao vivo como único oráculo (o resquício são estas funções); um reverse shell. Teatro.
python3 drupal-move-block-markup-Abraxas-Labs.py
ou
cd lab
./run.sh
Aponte apenas para http://127.0.0.1:19490. Gadget fiel das funções da versão 11.4.8 (cópia remanescente de MoveBlockForm, FormattableMarkup, ensureMarkupIsSafe, Xss::filter). Não é um site drupal:11.4.8 ativo. A última linha usa how=gadget.
SUCCESS drupal-move-block-markup how=gadget sibling-raw-tag=yes current-escaped=yes patched-sibling-escaped=yes DRUPAL-MOVE-BLOCK-MARKUP-WITNESS
Use @label (ou Html::escape) para cada linha, não apenas para o bloco atual.
61044508071749629aaf3380aa85971e94df9e84)MoveBlockForm.php · BlockPluginTrait.phpGNU Affero GPL v3.0. Consulte LICENSE. Apenas laboratório loopback. Sem garantias.