
IDOR + Stored XSS через нарушенную авторизацию на уровне объектов в JoomGallery
JoomGallery ≤ 4.3.0 — пользователь с ролью Editor перехватывает любые изображения галереи и сохраняет XSS-нагрузку, что позволяет захватить сессию администратора
Метод UserimageController::save() в JoomGallery проверяет checkACL('edit', ...) вместо checkACL('edit.own', ...). Пользователь с ролью Editor может отправить POST-запрос на task=userimage.save&id=N для любого изображения независимо от права собственности (IDOR — CWE-639). Поскольку роль Editor глобально обладает правом core.edit, проверка авторизации проходит для любого ID изображения на сайте, включая изображения, принадлежащие администраторам.
В сочетании с отсутствующим вызовом $this->escape() в шаблоне изображения на фронтенде, пользователь с ролью Editor может сохранить XSS-нагрузку в заголовке любого изображения — включая изображения, принадлежащие администраторам, — что приводит к выполнению JavaScript в браузере каждого посетителя. Это позволяет полностью захватить сессию администратора и скомпрометировать весь сайт.
| КОМПОНЕНТ | УЯЗВИМЫЕ | ПРОТЕСТИРОВАНО НА | ИСПРАВЛЕНО |
|---|---|---|---|
| JoomGallery (com_joomgallery) | 4.0.0 – 4.3.0 | Joomla 5.4.7 + JoomGallery 4.3.0-stable (PHP 8.2 / Apache) | 4.4.0 |
Тип: Нарушенная авторизация на уровне объектов / IDOR (CWE-639) в связке с сохранённым межсайтовым скриптингом (CWE-79) Требуемая аутентификация: Учётная запись Editor с низкими привилегиями
Файл: components/com_joomgallery/src/Controller/UserimageController.php
Действие save() выполняет проверку ACL с использованием разрешения edit вместо edit.own. Разрешение edit предоставляется всем пользователям с ролью Editor глобально, поэтому проверка успешно проходит для любого ID изображения независимо от того, кто его создал.
USERIMAGECONTROLLER.PHP — УЯЗВИМЫЙ КОД (СТРОКА 145)
// Vulnerable
if (!$this->checkACL('edit', 'image', $recordId, $parent_id, true)) { ... }
Поскольку группа Editor глобально обладает правом core.edit, условие принимает значение false для каждого ID изображения, предоставляя неограниченный доступ на запись. При успешном сохранении модель дополнительно обновляет поле created_by на ID пользователя-атакующего, незаметно передавая право собственности на изображение атакующему.
Файл: components/com_joomgallery/tmpl/image/default.php
Шаблон изображения на фронтенде выводит $this->item->title без HTML-кодирования в контекст атрибута alt. Фильтр STRING из Joomla JInput не удаляет символы двойных кавычек, поэтому нагрузка, содержащая ", выходит за пределы атрибута и внедряет произвольные обработчики событий.
DEFAULT.PHP — УЯЗВИМЫЙ КОД (СТРОКИ 64, 78)
// Vulnerable
item->title; ?>" ...>
Нагрузка abc" onmouseover="alert(document.domain);" x=" сохраняется в jos_joomgallery.title и при каждой отрисовке страницы внедряется в HTML-атрибут в исходном виде. Никакой санитизации на уровне хранения или вывода не происходит.
task=userimage.save&id=3 с XSS-нагрузкой в jform[title]. Проверка ACL проходит (core.edit, а не edit.own). Сервер возвращает HTTP 303 — не 403.created_by переходит к ID пользователя-атакующего.jos_joomgallery.title.alt="abc" onmouseover="alert(document.domain);". XSS срабатывает. Сессия администратора перехвачена → полная компрометация сайта.Администратор создаёт admin_image через бэкенд JoomGallery (Joomla 5.4.7). Изображение опубликовано, одобрено и принадлежит Administrator

GET /index.php/component/users/login — JSON-ответ содержит "csrf.token":"a68c2b3a...". Токен перехвачен для последующего POST-запроса на вход.

joomla_user_state=logged_inPOST /index.php/component/users/login с CSRF-токеном и учётными данными Editor. Ответ: HTTP 303 и Set-Cookie: joomla_user_state=logged_in. Cookie сессии перехвачена.

GET /index.php?option=com_joomgallery с cookie сессии. Ответ содержит новый "csrf.token":"2d96934b..." для использования в запросе сохранения.

Editor отправляет POST-запрос на option=com_joomgallery&task=userimage.save&id=3 с jform[title], установленным в:
abc" onmouseover="alert(document.domain);" x="
Сервер возвращает HTTP 303 (не 403), подтверждая IDOR. Заголовок Location содержит XSS-нагрузку в URL перенаправления, что подтверждает принятие и сохранение заголовка.

Бэкенд JoomGallery показывает, что у изображения ID=3 теперь Владелец: Editor User. Поле created_by было незаметно обновлено в базе данных во время несанкционированного сохранения.

SQL-запрос к jos_joomgallery подтверждает, что XSS-нагрузка сохранена — " хранится как сырая двойная кавычка, а не как ". Никакой санитизации на уровне хранения не произошло.

Любой пользователь, посещающий /index.php/component/joomgallery/gallery, запускает нагрузку. Диалоговое окно alert() в браузере подтверждает выполнение JavaScript в origin жертвы (document.domain).

created_by атакующему, навсегда изменяя журнал аудита.alt может похитить cookie сессии администратора, предоставляя атакующему полный доступ к бэкенду и контроль над всей установкой Joomla.S:C), пересекая границу доверия между сессией атакующего с низкими привилегиями и сессией жертвы с высокими привилегиями.