
Уязвимость CVE-2025-46822 в Java-springboot-codebase
Уязвимость в проекте Java-springboot-codebase позволяет злоумышленнику читать произвольные файлы на сервере через API-эндпоинт /api/v1/files/{fileName}
. Проблема возникает из-за некорректной обработки абсолютных путей в методе Path.resolve()
и отсутствия аутентификации.
Анализ уязвимости
Уровень опасности: Критический (CVSS 3.1: 9.8)
Вектор атаки: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
-
AV:N (Attack Vector: Network) – Уязвимость эксплуатируется через сеть, удалённо.
-
AC:L (Attack Complexity: Low) – Низкая сложность атаки: не требуется специальных условий.
-
PR:N (Privileges Required: None) – Привилегии не нужны.
-
UI:N (User Interaction: None) – Участие пользователя не требуется.
-
S:U (Scope: Unchanged) – Уязвимость не выходит за пределы компонента.
-
C:H (Confidentiality: High) – Полное раскрытие конфиденциальных данных.
-
I:H (Integrity: High) – Возможность модификации критических файлов.
-
A:H (Availability: High) – Серьёзное влияние на доступность системы.
Условия эксплуатации
-
Доступ к API: Злоумышленник должен иметь доступ к эндпоинту
/api/v1/files/{fileName}
(например, через публичный IP или внутреннюю сеть). -
Конфигурация хранилища: В
application-dev.properties
задан корневой путьfiles.store.root = /file-store/
. -
Абсолютный путь в запросе: Передача абсолютного пути (например,
/etc/passwd
) в параметрfileName
.
Пример уязвимого кода в FileController
:
@GetMapping("/{fileName}") public ResponseEntity<?> getFileByName(@PathVariable String name) { var resource = storageService.loadAsResource(name); // Уязвимость! return ResponseEntity.ok().body(resource); }
В классе StorageService
метод loadAsResource
использует Path.resolve()
, который не проверяет, находится ли итоговый путь внутри корневой директории:
public Resource loadAsResource(String filename) { Path file = rootPath.resolve(filename).normalize(); // Небезопасно! return new FileSystemResource(file); }
Если передать filename=/etc/passwd
, rootPath.resolve(filename)
вернет абсолютный путь /etc/passwd
, минуя корень /file-store/
.
Анализ эксплоита
Рассмотрим общедоступный эксплоит CVE-2025-46822.py для понимания работы вектора атаки с использованием этой уязвимости:
-
Формирование URL:
encoded_path = quote(file_path, safe='') url = target + "/api/v1/files/" + encoded_path
Кодирование пути гарантирует, что символы вроде
/
передаются как%2F
. -
Отправка запроса:
response = requests.get(url, allow_redirects=False)
Эксплоит использует HTTP GET без аутентификации.
Защита от уязвимости
-
Проверка относительных путей:
Path resolvedPath = rootPath.resolve(filename).normalize(); if (!resolvedPath.startsWith(rootPath)) { throw new SecurityException("Invalid path!"); }
-
Санкционирование входных данных:
if (filename.contains("..") || filename.startsWith("/")) { throw new IllegalArgumentException("Invalid filename!"); }
-
Аутентификация и авторизация:
Добавьте@PreAuthorize("isAuthenticated()")
к методу контроллера.
Пример исправленного StorageService
:
public Resource loadAsResource(String filename) { Path file = rootPath.resolve(filename).normalize(); if (!file.startsWith(rootPath)) { return null; } return new FileSystemResource(file); }
-
Использование безопасных библиотек:
Например, Apache Commons IOFilenameUtils.normalize()
.
Где используется уязвимый код?
Проект Java-springboot-codebase содержит примеры для обучения, но аналогичные ошибки встречаются в:
-
Веб-приложениях Spring Boot для загрузки файлов.
-
Микросервисах с публичными API для работы с хранилищами.
-
Корпоративных системах с конфигурацией
files.store.root
.
