
Drupal 11.4.8 - Alta - Remoto - XSS - Le etichette dei blocchi adiacenti ignorano l'escaping di @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 memorizzato Portata: Remota
Drupal core 11.4.8 (61044508) - Drupal
SA-CORE-2026-012 ha modificato la riga corrente di Move Block in t('@label (current)'), che viene sottoposta a Html::escape(). Le righe adiacenti nella stessa regione assegnano ancora BlockPluginTrait::label() direttamente a #markup in MoveBlockForm. Quell'etichetta è configuration['label'], un campo di testo grezzo. Renderer::ensureMarkupIsSafe applica quindi un filtro XSS a una stringa usando l'elenco dei tag consentiti agli amministratori, per cui un <b> (e altri tag amministrativi) sopravvive.
Un editor di Layout Builder che può impostare il titolo di un blocco con HTML raggiunge un altro editor o amministratore che apre Move su un blocco diverso in quella regione. XSS memorizzato nella finestra di dialogo Move. Non è RCE né LPE.
| ID | nessuna CVE al momento |
| Classe | XSS memorizzato |
| Portata | Remota (configurazione blocco in Layout Builder; la vittima apre Move Block) |
| CWE | CWE-79 |
| CVSS | Medio: 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
| Prodotto | Drupal core |
| Affetto | 11.4.8 (61044508071749629aaf3380aa85971e94df9e84) |
| Autenticazione | Configurazione blocco in Layout Builder. La vittima apre Move Block. |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Scrittore: utente che può posizionare o configurare blocchi di Layout Builder (non la configurazione del sito). Vittima: un altro editor LB o amministratore che apre Move su un blocco diverso nella stessa regione.
| Privilegio | Metodo / sink | Tipo | Dimostrato in lab o dedotto |
|---|---|---|---|
| Stampare l'HTML dell'attaccante nella riga adiacente della finestra di dialogo Move | $label['#markup'] = $plugin->label(); poi ensureMarkupIsSafe | Integrità dell'HTML | Dimostrato in lab. L'HTML adiacente è <b class="lb-sib">DRUPAL-MOVE-BLOCK-MARKUP-WITNESS</b> |
Conservare il markup dei tag amministrativi (<b> e il resto di Xss::getAdminTagList) | la stringa #markup viene filtrata XSS con l'elenco amministrativo, non sottoposta a escape | Integrità dell'HTML | Dimostrato in lab per <b> |
| Sessione / azioni come l'editor vittima nell'origine di Layout Builder | XSS memorizzato in quella finestra di dialogo | Integrità della sessione della vittima | Dedotto. Il lab si ferma all'HTML grezzo nella cella adiacente |
| Negativo: riga corrente | t('@label (current)', ...) | Chiuso | Dimostrato in lab. <em class="lb-cur">... |
Negativo: riga adiacente tramite @label | percorso del gadget corretto | Chiuso | Dimostrato in lab. <b class="lb-sib">... |
Chiuso su questo residuo: installazione di un sito Drupal live (questo lab è un gadget); furto di sessione tramite l'interfaccia di Layout Builder come oracolo HTTP misurato; RCE; LPE. I visitatori non autenticati non possono aprire Move Block.
Stesso residuo del pin: AttributeXss HTMX attrs.
Ho fissato Drupal 11.4.8 dopo SA-CORE-2026-012. L'advisory ha chiuso il titolo del blocco corrente. MoveBlockForm.php 210-218:
if ($is_current_block) {
$label['#markup'] = $this->t('@label (current)', ['@label' => $plugin->label()]);
// ...
}
else {
$label['#markup'] = $plugin->label();
}
BlockPluginTrait::label() restituisce configuration['label'] quando impostato. Renderer::ensureMarkupIsSafe non applica il filtro XSS a MarkupInterface (@label è già escapato). Una stringa grezza viene filtrata con la lista dei tag amministrativi.
Vicoli ciechi già registrati: trattare la riga corrente come ancora grezza (non lo è); sostenere che si tratti di RCE; un sito Drupal live come unico oracolo (il residuo sono queste funzioni); una reverse shell. Teatro.
python3 drupal-move-block-markup-Abraxas-Labs.py
o
cd lab
./run.sh
Prendi di mira solo http://127.0.0.1:19490. Gadget fedele delle funzioni della 11.4.8 (copia residua di MoveBlockForm, FormattableMarkup, ensureMarkupIsSafe, Xss::filter). Non è un sito drupal:11.4.8 attivo. L'ultima riga 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
Usa @label (o Html::escape) per ogni riga, non solo per il blocco corrente.
61044508071749629aaf3380aa85971e94df9e84)MoveBlockForm.php · BlockPluginTrait.phpGNU Affero GPL v3.0. Vedi LICENSE. Solo per laboratorio loopback. Nessuna garanzia.