
CVE-2026-9811 — это уязвимость типа «Межсайтовый скриптинг с сохранением» (Stored XSS), затрагивающая Mautic 7 (версии с 7.0.0 по 7.1.1).
CVE-2026-9811 — это уязвимость типа «межсайтовый скриптинг с сохранением» (Stored XSS), затрагивающая Mautic 7 (версии с 7.0.0 по 7.1.1). Уязвимость существует в компоненте Project Selector, где имена проектов, возвращаемые через AJAX-запрос, вставляются на страницу без надлежащего кодирования вывода или санитизации. Аутентифицированный пользователь с разрешением на создание проектов может сохранить вредоносную JavaScript-нагрузку в имени проекта. Когда другой администратор позже открывает редактор сущности, содержащий селектор проекта, вредоносный сценарий выполняется в его браузере.
Свойство Значение Продукт Mautic Затронутые версии 7.0.0 – 7.1.1 Исправленная версия 7.1.2 Компонент Project Selector Тип уязвимости Межсайтовый скриптинг с сохранением (XSS)
Приложение сохраняет имена проектов, указанные аутентифицированными пользователями, и позже получает их через AJAX-эндпоинт. При отображении селектора проекта приложение вставляет эти значения непосредственно в DOM в виде HTML-элементов option без экранирования или санитизации содержимого.
Концептуально:
User creates project
│
▼
Project name stored in database
│
▼
AJAX returns project name
│
▼
Inserted into DOM without sanitization
│
▼
Browser executes embedded JavaScript
Поскольку приложение доверяет сохранённым данным, вредоносный JavaScript выполняется всякий раз, когда другой привилегированный пользователь загружает уязвимую страницу.
Attacker
│
▼
Creates a project with a malicious JavaScript payload as its name
│
▼
Payload is stored in the database
│
▼
Administrator opens an entity editor
│
▼
AJAX request retrieves project names
│
▼
Application inserts project name into the DOM without encoding
│
▼
Browser executes the malicious script
│
▼
Attacker gains actions within the administrator's session
Злоумышленник с разрешением на создание проектов создаёт проект, имя которого содержит вредоносную JavaScript-нагрузку. Позже администратор редактирует другую сущность, включающую Project Selector. Селектор загружает имена проектов через AJAX и вставляет их непосредственно на страницу. Поскольку имя проекта не санитизируется, браузер выполняет встроенный сценарий с правами администратора.
Представьте, что в Mautic есть форма следующего вида:
POST /projects/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
projectName=Marketing Campaign
description=Email Campaign
Проект сохраняется как:
Marketing Campaign
Шаг 2: Злоумышленник создаёт проект
Вместо обычного имени злоумышленник вводит HTML, содержащий безвредное JavaScript-событие:
POST /projects/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
projectName=<img src="https://raw.githubusercontent.com/aj2108/cve-2026-9811/main/x" onerror="console.log('XSS Demo')">
description=Test
Теперь база данных хранит именно эту строку.
Шаг 3: AJAX возвращает сохранённое значение
Позже администратор открывает страницу, которая загружает проекты.
Ответ AJAX:
{
"id": 7,
"projectName": ""
}
Шаг 4: Уязвимый JavaScript
Предположим, приложение делает следующее:
const project = response.projectName;
document.getElementById("projects").innerHTML +=
`<option>${project}</option>`;
Браузер видит:
<option>
<img src="https://raw.githubusercontent.com/aj2108/cve-2026-9811/main/x" onerror="console.log('XSS Demo')">
</option>
Поскольку приложение вставило строку как HTML, а не как текст, браузер интерпретирует её как фактический элемент . Изображение не загружается (src="x"), что приводит к выполнению обработчика onerror.
Успешная эксплуатация может позволить злоумышленнику:
| Метрика | Оценка |
|---|---|
| CVSS v3.1 (CNA) | 5.4 (Средний) |
NVD ещё не опубликовал собственную оценку CVSS для этой CVE.
Примечание: Поставщик не опубликовал точный уязвимый исходный код. Приведённый ниже пример лишь иллюстрирует паттерн уязвимости.
// Data returned from AJAX
const project = response.projectName;
// Unsafe: inserted directly into the DOM
document.getElementById("projectSelector").innerHTML +=
`<option>${project}</option>`;
Имя проекта происходит из пользовательского ввода, но вставляется на страницу без HTML-кодирования. Если сохранённое значение содержит HTML или JavaScript, браузер интерпретирует его как исполняемое содержимое, а не как обычный текст.
const option = document.createElement("option");
// Safe: assign as text, not HTML
option.textContent = response.projectName;
document.getElementById("projectSelector").appendChild(option);
Или, если вывод HTML неизбежен, обеспечьте надлежащее кодирование вывода перед вставкой.
Использование textContent (или эквивалентного безопасного API) гарантирует, что любые специальные символы обрабатываются как обычный текст, а не как исполняемый HTML или JavaScript. Даже если вредоносное имя проекта сохранено в базе данных, оно будет отображаться буквально, а не выполняться.