
Drupal 11.4.8 — высокий — удалённый — XSS — перемещение блока: метки соседних элементов пропускают экранирование @label
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · drupal-move-block-markup
Класс: Stored XSS Достижимость: Удалённая
Drupal core 11.4.8 (61044508) - Drupal
SA-CORE-2026-012 перевёл строку текущего блока в Move Block на t('@label (current)'), что применяет Html::escape(). Соседние строки в том же регионе по-прежнему присваивают BlockPluginTrait::label() напрямую в #markup в MoveBlockForm. Эта метка — это configuration['label'], необработанное текстовое поле. Затем Renderer::ensureMarkupIsSafe XSS-фильтрует строку с помощью списка административных тегов, поэтому <b> (и другие административные теги) выживает.
Редактор Layout Builder, который может задать заголовок блока как HTML, достигает другого редактора или администратора, открывающего Move на другом блоке в том же регионе. Stored XSS в диалоге Move. Не RCE и не LPE.
| ID | CVE пока нет |
| Класс | Stored XSS |
| Достижимость | Удалённая (настройка блока Layout Builder; жертва открывает Move Block) |
| CWE | CWE-79 |
| CVSS | Средний: 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
| Продукт | Drupal core |
| Затронуто | 11.4.8 (61044508071749629aaf3380aa85971e94df9e84) |
| Аутентификация | Настройка блока Layout Builder. Жертва открывает Move Block. |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1 |
Писатель: пользователь, который может размещать или настраивать блоки Layout Builder (не site-config). Жертва: другой редактор LB или администратор, открывающий Move на другом блоке в том же регионе.
| Привилегия | Метод / сток | Тип | Доказано в лаборатории или выведено |
|---|---|---|---|
| Вывод HTML атакующего в соседней строке диалога Move | $label['#markup'] = $plugin->label(); затем ensureMarkupIsSafe | Целостность HTML | Доказано в лаборатории. Соседний HTML — <b class="lb-sib">DRUPAL-MOVE-BLOCK-MARKUP-WITNESS</b> |
Сохранение разметки административных тегов (<b> и остального из Xss::getAdminTagList) | строковый #markup XSS-фильтруется с административным списком, а не экранируется | Целостность HTML | Доказано в лаборатории для <b> |
| Сессия / действия от имени редактора-жертвы в origin Layout Builder | Stored XSS в этом диалоге | Целостность сессии жертвы | Выведено. Лаборатория останавливается на необработанном HTML в соседней ячейке |
| Отрицательный: текущая строка | t('@label (current)', ...) | Закрыто | Доказано в лаборатории. <em class="lb-cur">... |
Отрицательный: соседняя через @label | пропатченный путь гаджета | Закрыто | Доказано в лаборатории. <b class="lb-sib">... |
Закрыто по этому остатку: установка на живой сайт Drupal (эта лаборатория — гаджет); кража сессии через UI Layout Builder как измеряемый HTTP-оракул; RCE; LPE. Неаутентифицированные посетители не могут открыть Move Block.
Тот же закреплённый коммит: AttributeXss HTMX attrs.
Я закрепил Drupal 11.4.8 после SA-CORE-2026-012. Рекомендация закрыла заголовок текущего блока. MoveBlockForm.php 210-218:
if ($is_current_block) {
$label['#markup'] = $this->t('@label (current)', ['@label' => $plugin->label()]);
// ...
}
else {
$label['#markup'] = $plugin->label();
}
BlockPluginTrait::label() возвращает configuration['label'], когда он задан. Renderer::ensureMarkupIsSafe не XSS-фильтрует MarkupInterface (@label уже экранирован). Необработанная строка фильтруется с административным списком тегов.
Уже зафиксированные ошибочные пути: считать текущую строку по-прежнему необработанной (это не так); утверждать, что это RCE; живой сайт Drupal как единственный оракул (остаток — это данные функции); reverse shell. Театр.
python3 drupal-move-block-markup-Abraxas-Labs.py
или
cd lab
./run.sh
Цель только http://127.0.0.1:19490. Точный гаджет функций 11.4.8 (копия остатка MoveBlockForm, FormattableMarkup, ensureMarkupIsSafe, Xss::filter). Не живой сайт drupal:11.4.8. Последняя строка использует 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
Использовать @label (или Html::escape) для каждой строки, а не только для текущего блока.
61044508071749629aaf3380aa85971e94df9e84)MoveBlockForm.php · BlockPluginTrait.phpGNU Affero GPL v3.0. См. LICENSE. Только лаборатория на loopback. Без гарантий.