
Небезопасная десериализация в e107 CMS install.php
Сообщено: 18 сентября 2025 г.
CVE присвоен: 9 октября 2025 г.
Опубликовано: 2 февраля 2026 г.
Идентификатор CVE: CVE-2025-61505
Обнаружил: Анас Абдеррахман Бенбарек
Уязвимость внедрения PHP-объектов (CWE-502: Десериализация недоверенных данных) была обнаружена в скрипте установки (install.php) e107 CMS версии 2.3.3.
Уязвимость позволяет неаутентифицированным удаленным злоумышленникам создавать вредоносные сериализованные данные, что потенциально может привести к выполнению произвольного кода, манипуляции данными или другим вредоносным действиям — в зависимости от наличия эксплуатируемых классов-гаджетов в кодовой базе e107 или её зависимостях.
Эта проблема возникает из-за небезопасного использования функции PHP unserialize() для ввода, контролируемого пользователем, без каких-либо ограничений (например, опции allowed_classes). Хотя она ограничена фазой установки, она представляет значительный риск при настройке на открытых серверах, поскольку установщик выполняет чувствительные операции, такие как создание базы данных и запись файлов.
install.php)Процесс установки e107 CMS является многоэтапным. Вводимые пользователем данные (язык, учетные данные базы данных, данные администратора и т.д.) сохраняются между этапами с помощью сериализованного массива, хранящегося в параметре POST previous_steps. Эти данные кодируются base64 для передачи и декодируются/десериализуются на сервере.
Основная проблема заключается в прямой передаче декодированного пользовательского ввода в unserialize() без проверки, очистки или белого списка классов. Это происходит в двух местах:
if(isset($_POST['previous_steps']))
{
$tmp = unserialize(base64_decode($_POST['previous_steps']));
$override = (isset($tmp['paths']) && isset($tmp['paths']['hash'])) ? array('site_path'=>$tmp['paths']['hash']) : array();
unset($tmp);
}
Скрипт предполагает, что previous_steps содержит доверенные сериализованные данные из предыдущих шагов формы. Но поскольку это обычный параметр POST, злоумышленник полностью его контролирует. base64_decode() преобразует ввод в двоичные данные, а unserialize() восстанавливает их в объекты или массивы PHP. Если ввод содержит нотацию объекта (начинающуюся с O:), PHP создает экземпляры этих классов, если они существуют в текущей области видимости или загружаются автоматически. Это может немедленно вызвать __wakeup() или другие магические методы, что потенциально может привести к побочным эффектам, таким как запись файлов или неожиданные вызовы базы данных, если присутствуют цепочки гаджетов.
Примечание по эксплуатации: Успех зависит от доступных классов-гаджетов. Без них воздействие может ограничиваться сбоями или повреждением данных.
if(isset($_POST['previous_steps']))
{
$this->previous_steps = unserialize(base64_decode($_POST['previous_steps']));
// ... (filtering and password restoration logic)
unset($_POST['previous_steps']);
}
Этот экземпляр более опасен, поскольку десериализованные данные становятся частью состояния объекта ($this->previous_steps) и влияют на дальнейшие действия установщика (настройка MySQL, создание администратора, генерация конфигурационных файлов). Внедрение объектов здесь может сохраняться на протяжении всего процесса установки и затрагивать операции с высокими привилегиями. Опять же, отсутствие ограничения allowed_classes означает, что может быть создан экземпляр любого автоматически загруженного класса (ядро, обработчики, плагины, библиотеки).
Примечание по эксплуатации: Реальная эксплуатация обычно требует объединения нескольких объектов ("цепочка гаджетов") для достижения опасного поведения, такого как выполнение кода. Например, __wakeup() одного класса может вызвать другой метод, который оценивает строки, контролируемые пользователем. Без таких цепочек воздействие может остаться на уровне отказа в обслуживании (например, истощение ресурсов в деструкторах). Контекст с высокими привилегиями установщика (запись e107_config.php, создание каталогов) усиливает риски, но удаление скрипта после установки снижает долгосрочную подверженность.
Уязвимость доступна через неаутентифицированные HTTP POST запросы к /install.php на любом этапе установки.
.htaccess, правила nginx или переместите файл за пределы корня веб-сервера при развертывании.unserialize() на json_decode() для сохранения состояния или, как минимум, используйте:unserialize($data, ['allowed_classes' => false]);