Уязвимость в Spring Boot
Уязвимость в Spring Boot
Категория: Программы Теги: Уязвимости Опубликовано: 12 сентября 2025

Уязвимость 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 (Влияние на доступность: Низкое) - возможно ограниченное воздействие на доступность

Условия эксплуатации уязвимости

Для успешной эксплуатации уязвимости необходимо одновременное наличие следующих условий:

  1. Приложение использует Spring Security для защиты endpoints

  2. В конфигурации безопасности используется метод EndpointRequest.to() для настройки доступа к актуаторным endpoints

  3. Актуаторный endpoint, на который ссылается EndpointRequest.to(), отключен или не экспонирован через web

  4. Приложение обрабатывает запросы к пути /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:

  1. Конфиденциальные данные приложения: параметры конфигурации, ключи API, учетные данные

  2. Пользовательские данные: персональная информация, токены сессий

  3. Системная информация: данные о сервере, логи, метрики производительности

  4. Бизнес-логика: внутренние 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 должен быть размещен:

  1. Перед балансировщиком нагрузки: для проверки всех входящих запросов

  2. В DMZ: если приложение доступно из интернета

  3. На границе сети: для защиты всех web-приложений организации

  4. Внутри микросервисной инфраструктуры: как 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-правила применяются к правильным путям, и регулярно проводить аудит безопасности своих приложений.

Для организаций критически важно иметь процессы оперативного обновления зависимостей, регулярного сканирования уязвимостей и мониторинга подозрительной активности. Реализация защитных мер на уровне приложения в сочетании с сетевыми контролями обеспечивает многоуровневую защиту от подобных уязвимостей.

Алексей Черемных Алексей Черемных
431