Уязвимость CVE-2025-22235 в Spring Boot
Уязвимость CVE-2025-22235 затрагивает механизм безопасности Spring Boot, связанный с обработкой запросов к актуаторным endpoint. Проблема возникает когда метод EndpointRequest.to() создает некорректный matcher для пути /null/** в случае, если соответствующий актуаторный endpoint отключен или не экспонирован через web-интерфейс. Это может привести к обходу механизмов аутентификации и авторизации для определенных путей в приложении.
Анализ уязвимости
Уровень опасности: 7.3 HIGH
Вектор атаки: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
-
AV:N (Вектор атаки: Сетевой) - атака может быть выполнена удаленно через сеть
-
AC:L (Сложность атаки: Низкая) - не требует специальных условий для эксплуатации
-
PR:N (Уровень привилегий: Не требуются) - атака не требует предварительных привилегий
-
UI:N (Вовлечение пользователя: Не требуется) - атака не требует участия пользователя
-
S:U (Область воздействия: Не изменяется) - уязвимость не затрагивает другие компоненты
-
C:L (Влияние на конфиденциальность: Низкое) - возможна утечка ограниченной информации
-
I:L (Влияние на целостность: Низкое) - возможно ограниченное воздействие на целостность
-
A:L (Влияние на доступность: Низкое) - возможно ограниченное воздействие на доступность
Условия эксплуатации уязвимости
Для успешной эксплуатации уязвимости необходимо одновременное наличие следующих условий:
-
Приложение использует Spring Security для защиты endpoints
-
В конфигурации безопасности используется метод
EndpointRequest.to()для настройки доступа к актуаторным endpoints -
Актуаторный endpoint, на который ссылается
EndpointRequest.to(), отключен или не экспонирован через web -
Приложение обрабатывает запросы к пути
/nullи этот путь требует защиты
Если любое из этих условий не выполняется, приложение не подвержено уязвимости.
Технический анализ уязвимости
Рассмотрим код эксплоита для понимания работы вектора атаки с использованием этой уязвимости. Основная проблема заключается в реализации метода EndpointRequest.to() в Spring Boot.
Анализ проблемного кода
Исходный код метода EndpointRequest.to() в уязвимых версиях Spring Boot:
public static EndpointRequest to(String... endpointIds) {
return new EndpointRequest(Arrays.asList(endpointIds));
}
private EndpointRequest(List<String> endpointIds) {
this.endpointIds = endpointIds;
}
public final boolean matches(HttpServletRequest request) {
String requestPath = getRequestPath(request);
// Проблемная логика: если endpoint не экспонирован,
// создается matcher для "/null/**"
if (!isExposed()) {
return pathMatcher.match("/null/**", requestPath);
}
return doMatch(request);
}
Когда актуаторный endpoint не экспонирован (не включен в management.endpoints.web.exposure.include), метод isExposed() возвращает false, и тогда создается matcher для пути /null/**. Это приводит к тому, что все правила безопасности, примененные к неэкспонированному endpoint'у, фактически применяются к пути /null/**.
Пример конфигурации безопасности с уязвимостью
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorize -> authorize
.requestMatchers(EndpointRequest.to("health")).permitAll() // Уязвимое место
.requestMatchers("/null").authenticated() // Защита для /null
.anyRequest().permitAll()
).formLogin(Customizer.withDefaults());
return http.build();
}
}
В этом примере, если endpoint health не экспонирован, правило .requestMatchers(EndpointRequest.to("health")).permitAll() будет применено к пути /null/**, что откроет доступ без аутентификации к пути /null.
Пример контроллера с уязвимым endpoint
@RestController
public class VulnerableController {
@GetMapping("/null")
public String sensitiveData() {
return "Конфиденциальные данные!";
}
@GetMapping("/info")
public String publicInfo() {
return "Публичная информация";
}
}
Пример конфигурации application.properties
# Актуаторные endpoints: health не экспонирован! management.endpoints.web.exposure.include=info management.endpoint.health.enabled=true # Включение security для актуаторов management.endpoint.health.access=authenticated
Вредоносный HTTP-запрос
При наличии уязвимости злоумышленник может получить доступ к защищенным ресурсам без аутентификации:
GET /null HTTP/1.1 Host: vulnerable-app.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Accept: text/html,application/xhtml+xml,application/xml Accept-Language: en-US,en;q=0.5 Connection: close
Ответ сервера при уязвимости:
HTTP/1.1 200 OK Content-Type: text/plain;charset=UTF-8 Content-Length: 28 Конфиденциальные данные!
Возможные последствия эксплуатации уязвимости
Злоумышленник может получить различную чувствительную информацию в зависимости от функциональности, реализованной по пути /null:
-
Конфиденциальные данные приложения: параметры конфигурации, ключи API, учетные данные
-
Пользовательские данные: персональная информация, токены сессий
-
Системная информация: данные о сервере, логи, метрики производительности
-
Бизнес-логика: внутренние API, алгоритмы принятия решений
Методы защиты
1. Обновление версии Spring Boot
Наиболее эффективный способ защиты - обновление до исправленной версии Spring Boot:
-
Spring Boot 2.7.x → 2.7.25
-
Spring Boot 3.1.x → 3.1.16
-
Spring Boot 3.2.x → 3.2.14
-
Spring Boot 3.3.x → 3.3.11
-
Spring Boot 3.4.x → 3.4.5
2. Проверка конфигурации endpoint
Убедитесь, что все endpoint, используемые в EndpointRequest.to(), правильно экспонированы:
# Правильная конфигурация management.endpoints.web.exposure.include=health,info,metrics management.endpoint.health.enabled=true
3. Регулярная проверка безопасности
Реализуйте автоматизированные проверки безопасности:
@Component
public class SecurityConfigValidator implements ApplicationRunner {
private final ApplicationContext applicationContext;
public SecurityConfigValidator(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void run(ApplicationArguments args) {
// Проверка, что /null требует аутентификации
try {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/null");
SecurityFilterChain chain = applicationContext.getBean(SecurityFilterChain.class);
// Проверка логики безопасности
} catch (Exception e) {
logger.error("Обнаружена потенциальная уязвимость CVE-2025-22235");
}
}
}
WAF/IPS правила для защиты
Пример правила для ModSecurity
SecRule REQUEST_URI "@streq /null" \
"id:1001,\
phase:1,\
block,\
msg:'Potential CVE-2025-22235 Exploit Attempt',\
tag:'application-multi',\
tag:'language-java',\
tag:'platform-spring',\
tag:'attack-authentication-bypass',\
tag:'paranoia-level/1',\
ver:'OWASP_CRS/3.3.0',\
severity:'CRITICAL'"
Правило для Suricata
alert http any any -> any any (msg:"CVE-2025-22235 Spring Boot Auth Bypass Attempt"; flow:established,to_server; http.uri; content:"/null"; nocase; http.header; content:"Host"; nocase; classtype:web-application-attack; sid:202522235; rev:1;)
Данное правило можно найти в моём наборе правил к Suricata (https://alekseycheremnykh.ru/post/moj-nabor-pravil-k-suricata/).
Размещение WAF/IPS
Для эффективного обнаружения и блокирования атак на данную уязвимость WAF/IPS должен быть размещен:
-
Перед балансировщиком нагрузки: для проверки всех входящих запросов
-
В DMZ: если приложение доступно из интернета
-
На границе сети: для защиты всех web-приложений организации
-
Внутри микросервисной инфраструктуры: как sidecar-контейнер или сервисная сеть
Мониторинг и обнаружение атак
Реализуйте мониторинг подозрительной активности:
@Component
public class NullEndpointMonitor {
private static final Logger logger = LoggerFactory.getLogger(NullEndpointMonitor.class);
@EventListener
public void handleRequest(HttpServletRequest request) {
if ("/null".equals(request.getRequestURI())) {
logger.warn("Доступ к /null endpoint: IP={}, User-Agent={}, Session={}",
request.getRemoteAddr(),
request.getHeader("User-Agent"),
request.getSession(false) != null ? request.getSession().getId() : "no-session");
// Дополнительные проверки и оповещения
}
}
}
Заключение
Уязвимость CVE-2025-22235 демонстрирует важность тщательной проверки конфигурации безопасности, особенно когда используются абстракции высокого уровня как EndpointRequest.to(). Разработчикам следует всегда проверять, что security-правила применяются к правильным путям, и регулярно проводить аудит безопасности своих приложений.
Для организаций критически важно иметь процессы оперативного обновления зависимостей, регулярного сканирования уязвимостей и мониторинга подозрительной активности. Реализация защитных мер на уровне приложения в сочетании с сетевыми контролями обеспечивает многоуровневую защиту от подобных уязвимостей.