
Пошаговая демонстрация обхода авторизации CVE-2022-22978 в RegexRequestMatcher из Spring Security, включая настройку уязвимого приложения, выполнение эксплойта и проверку исправления.
Согласно информации, которую я нашёл, это уязвимость, связанная с классом RegexRequestMatcher во фреймворке Spring Security. В частности, приложения, использующие RegexRequestMatcher, в регулярном выражении которых содержится точка (.), могут быть обойдены с помощью символов \r(%0a) , \n(%0d); благодаря этому атакующие могут без аутентификации получать доступ к запрещённым путям.
Уязвимые версии фреймворка Spring Security:
5.5.x до 5.5.75.6.x до 5.6.4Нам нужно обратиться к исходному коду Spring Security для статического анализа этой уязвимости. Здесь я использую функцию сравнения коммитов между версиями 5.6.3 (уязвимая версия) и 5.6.4 (исправленная версия) на Github. Смотрите по ссылке: Comparing 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

Я проверил изменения в классе RegexRequestMatcher. Можно заметить, что в версии 5.6.4 этот класс использует Pattern.DOTALL вместо стандартного ., как в версии 5.6.3.
В том числе:
Pattern — один из трёх классов в пакетеjava.util.regex, предназначенный для обработки регулярных выражений.Pattern.DOTALL — при использовании этого флага символ «.» в регулярном выражении будет соответствовать всем символам, включая символы перевода строки, такие как \n , \r.Pattern.CASE_INSENSITIVE — не учитывает регистр символов (строчные/прописные).
По умолчанию точка . в регулярном выражении соответствует всем символам, кроме символов перевода строки, таких как \n, \r. Поэтому, если есть функция regex, проверяющая шаблон некоторой строки, эта функция не сработает при наличии символов перевода строки в строке. Чтобы избежать этого, можно использовать флаг Pattern.DOTALL.
Однако если кто-то намеренно использует %0d вместо \n или%0a вместо \r, регулярное выражение по-прежнему не сможет совпасть. Поэтому в версии 5.6.4 в RegexRequestMatcherTests.java была добавлена дополнительная проверка этого случая. А именно, она преобразует %0d и %0a в \n и \r соответственно, а затем выполняет проверку регулярным выражением.

Шаг 1: Создайте веб-приложение Spring Boot с помощью Spring Initializr с двумя зависимостями: Spring Security и Spring Web.

Шаг 2: Создайте контроллер, выводящий текст This is a CVE-2022-22978 demo при запросе к пути /admin/*

Шаг 3: Настройте механизм аутентификации при каждом обращении пользователя к пути /admin/<любой> с помощью regexMatchers("/admin/.*").authenticated(). Именно эту уязвимость используют атакующие, чтобы просматривать содержимое страниц /admin/<любой> без аутентификации.

Шаг 4: В файле конфигурации объявите версию Spring Security, содержащую уязвимость. Здесь я выбираю версию 5.6.3.

Шаг 5: Запустите приложение командой gradlew bootRun; по умолчанию программа использует Apache Tomcat, прослушивающий порт 8080. Заходим на путь /admin/xyz (подойдёт любой путь, начинающийся с /admin/).

Результат — код 403 Forbidden, то есть доступ невозможен без аутентификации.
Тут, используя уязвимость функции regexMatchers в Spring Security (версия 5.6.3), которая не распознаёт символы перевода строки, такие как \r(%0d) и \n(%0a), можно получить доступ к указанному выше пути без аутентификации с помощью payload /admin/%0dxyz

Аналогично с payload /admin/%0axyz

Таким образом, мы успешно применили уязвимость CVE-2022-22978 с помощью очень простого payload.
5.7.1
Попробуем атаковать веб-приложение аналогичным payload: /admin/%0dxyz

В этом случае приложение уже не возвращает ожидаемый атакующим ответ.
git clone https://github.com/ducluongtran9121/CVE-2022-22978-PoC.git
cd CVE-2022-22978-PoC
gradlew bootRun
Java 18
Gradle 7.4.1