
Подробное уведомление о безопасности для CVE-2026-36669: неавторизованная произвольная загрузка файлов в Feng Office, обеспечивающая сохранённый XSS и перехват сессии. Включает технический анализ, PoC и шаги по устранению.
Уязвимость неаутентифицированной произвольной загрузки файлов существует в ck_upload_handler.php в Feng Office Community Edition (версия 3.11.13.11). Эта ошибка позволяет удалённым неаутентифицированным злоумышленникам загружать произвольные файлы (включая вредоносные .html или .php скрипты) в веб-доступную директорию. В сочетании с отсутствием защиты административных куки с помощью флага HttpOnly, данная уязвимость может привести к сохранённому межсайтовому скриптингу (Stored XSS) и угону административной сессии.
| Метрика | Детали |
|---|
| Идентификатор CVE | CVE-2026-36669 |
| Тип уязвимости | Неограниченная загрузка файла опасного типа (CWE-434) |
| Связанная слабость | Отсутствие аутентификации для критической функции (CWE-306) |
| Затронутый продукт | Feng Office Community Edition |
| Затронутые версии | Версия 3.11.13.11 (и, возможно, более ранние версии) |
| Статус эксплуатации | Подтверждено доказательство концепции |
| Статус исправления | Не исправлено (Поставщик уведомлён, патч не предоставлен в стандартный срок раскрытия) |
Конечная точка ck_upload_handler.php работает как самостоятельный скрипт. Она не загружает и не наследует промежуточное ПО аутентификации или списки контроля доступа (ACL) основного приложения. Следовательно, любой внешний запрос, отправленный непосредственно к этому скрипту, обрабатывается как аутентифицированный.
В исходном коде ck_upload_handler.php серверная логика проверки файлов (строки 21–25), предназначенная для ограничения загрузки определёнными форматами изображений (.jpg, .png, .gif), была явно закомментирована:
// $pattern = "/\.(jpg|png|gif)$/i";
// if (!preg_match($pattern,$_FILES['upload']['name'])) {
// ...
// }
Поскольку это ограничение регулярного выражения неактивно, механизм загрузки файлов принимает любое расширение, предоставленное пользователем.
Скрипт использует функцию PHP copy() для записи загруженных файлов непосредственно в директорию /tmp/, которая настроена как веб-доступная.
Глобальный конфигурационный файл application/config/config.php не устанавливает флаг HttpOnly для куки сессии. Когда злоумышленник загружает файл .html, содержащий клиентские скрипты, любой администратор, просматривающий этот файл, выполнит скрипт в контексте своей активной сессии. Это позволяет злоумышленникам незаметно извлекать активные токены административной сессии.
Примечание: Данное доказательство концепции предоставлено исключительно в образовательных целях и для защитного аудита.
Для проверки уязвимости отправьте многокомпонентный POST-запрос, содержащий безвредный проверочный файл (например, test.html), к конечной точке с добавлением необходимого параметра CKEditorFuncNum:
curl -i -X POST \
-F "[email protected]" \
"http://<target-domain>/ck_upload_handler.php?CKEditorFuncNum=1"
Где test.html содержит базовую разметку HTML для доказательства концепции:
<!DOCTYPE html>
<html>
<body>
<script>
alert("Vulnerability Verified: " + document.cookie);
</script>
</body>
</html>
Если уязвимость присутствует, сервер ответит статусом 200 OK и выведет JavaScript-блок, указывающий путь загрузки:
<script type="text/javascript">
window.parent.CKEDITOR.tools.callFunction("1", "/tmp/test.html", "");
</script>
Если вы используете затронутую версию Feng Office, примените следующие ручные исправления для защиты конечной точки загрузки файлов:
Убедитесь, что ck_upload_handler.php проверяет наличие активной административной сессии перед обработкой любой логики загрузки файлов.
Раскомментируйте и строго применяйте проверки расширений. Отклоняйте любые загрузки, которые явно не соответствуют ожидаемым неисполняемым MIME-типам изображений:
$pattern = "/\.(jpg|jpeg|png|gif)$/i";
if (!preg_match($pattern, $_FILES['upload']['name'])) {
header("HTTP/1.1 403 Forbidden");
exit("Invalid file type.");
}
Измените конфигурацию PHP или начальный загрузчик приложения, чтобы куки сессии не были доступны через клиентские скриптовые API:
session.cookie_httponly = On
Soufiane LAGZIRI