
Drupal 11.4.8 - Élevé - À distance - XSS - Les étiquettes des blocs frères de Move Block ignorent l'échappement @label
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · drupal-move-block-markup
Article : https://abraxaslabs.tech/research/drupal-move-block-markup
Classe : XSS stocké Portée : Distant
Drupal core 11.4.8 (61044508) - Drupal
SA-CORE-2026-012 a fait passer la ligne actuelle de Move Block à t('@label (current)'), qui est échappé par Html::escape(). Les lignes voisines dans la même région assignent toujours BlockPluginTrait::label() directement à #markup dans MoveBlockForm. Ce label est configuration['label'], un champ texte brut. Renderer::ensureMarkupIsSafe applique ensuite un filtrage XSS à une chaîne avec la liste des balises admin, donc un <b> (et d'autres balises admin) survit.
Un éditeur Layout Builder qui peut définir le titre d'un bloc en HTML atteint un autre éditeur ou un administrateur qui ouvre Move sur un autre bloc de cette région. XSS stocké dans la boîte de dialogue Move. Ni RCE ni LPE.
| ID | pas encore de CVE |
| Classe | XSS stocké |
| Portée | Distante (configuration de bloc Layout Builder ; la victime ouvre Move Block) |
| CWE | CWE-79 |
| CVSS | Moyen : 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
| Produit | Drupal core |
| Affecté | 11.4.8 (61044508071749629aaf3380aa85971e94df9e84) |
| Auth | Configuration de bloc Layout Builder. La victime ouvre Move Block. |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Auteur : utilisateur qui peut placer ou configurer des blocs Layout Builder (pas la configuration du site). Victime : un autre éditeur LB ou un administrateur qui ouvre Move sur un autre bloc de la même région.
| Privilège | Méthode / sink | Type | Prouvé en lab ou déduit |
|---|---|---|---|
| Afficher le HTML de l'attaquant dans la ligne voisine de la boîte de dialogue Move | $label['#markup'] = $plugin->label(); puis ensureMarkupIsSafe | Intégrité du HTML | Prouvé en lab. Le HTML voisin est <b class="lb-sib">DRUPAL-MOVE-BLOCK-MARKUP-WITNESS</b> |
Conserver le balisage de balises admin (<b>, et le reste de Xss::getAdminTagList) | la chaîne #markup est filtrée XSS avec la liste admin, pas échappée | Intégrité du HTML | Prouvé en lab pour <b> |
| Session / actions en tant qu'éditeur victime dans l'origine Layout Builder | XSS stocké dans cette boîte de dialogue | Intégrité de la session de la victime | Déduit. Le lab s'arrête au HTML brut dans la cellule voisine |
| Négatif : ligne actuelle | t('@label (current)', ...) | Fermé | Prouvé en lab. <em class="lb-cur">... |
Négatif : voisin via @label | chemin du gadget corrigé | Fermé | Prouvé en lab. <b class="lb-sib">... |
Fermé sur ce reliquat : installation d'un site Drupal en production (ce lab est un gadget) ; vol de session de l'interface Layout Builder comme oracle HTTP mesuré ; RCE ; LPE. Les visiteurs non authentifiés ne peuvent pas ouvrir Move Block.
Même reliquat de version : AttributeXss HTMX attrs.
J'ai épinglé Drupal 11.4.8 après SA-CORE-2026-012. L'avis a corrigé le titre du bloc actuel. MoveBlockForm.php 210-218 :
if ($is_current_block) {
$label['#markup'] = $this->t('@label (current)', ['@label' => $plugin->label()]);
// ...
}
else {
$label['#markup'] = $plugin->label();
}
BlockPluginTrait::label() renvoie configuration['label'] lorsqu'il est défini. Renderer::ensureMarkupIsSafe ne filtre pas les XSS sur MarkupInterface (@label déjà échappé). Une chaîne brute est filtrée avec la liste de balises de l'administrateur.
Fausses pistes déjà consignées : traiter la ligne actuelle comme encore brute (elle ne l'est pas) ; prétendre qu'il s'agit d'une RCE ; un site Drupal en production comme unique oracle (le résidu, ce sont ces fonctions) ; un reverse shell. Du théâtre.
python3 drupal-move-block-markup-Abraxas-Labs.py
ou
cd lab
./run.sh
Ciblez uniquement http://127.0.0.1:19490. Gadget fidèle des fonctions 11.4.8 (copie résiduelle de MoveBlockForm, FormattableMarkup, ensureMarkupIsSafe, Xss::filter). Ce n'est pas un site drupal:11.4.8 en production. La dernière ligne utilise 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
Utilisez @label (ou Html::escape) pour chaque ligne, pas seulement pour le bloc actuel.
61044508071749629aaf3380aa85971e94df9e84)MoveBlockForm.php · BlockPluginTrait.phpGNU Affero GPL v3.0. Voir LICENSE. Laboratoire en boucle locale uniquement. Aucune garantie.