
Proof-of-concept eseguibile per CVE-2026-88789, che dimostra XXE e SSRF in Apache Camel Quarkus camel-quarkus-support-xalan tramite XSLT TransformerFactory.
TransformerFactory Xalan forzato elimina le restrizioni JAXP sull'accesso esternoRiproduttore proof-of-concept eseguibile per la vulnerabilità di Apache Camel Quarkus in cui l'estensione di supporto XSLT
(camel-quarkus-support-xalan) fornisce il proprio TransformerFactory basato su Xalan al componente xslt
e lo registra come default JAXP. Xalan-J 2.7.x è precedente a JAXP 1.5 e non può rispettare
javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD o ACCESS_EXTERNAL_STYLESHEET — setAttribute() genera
IllegalArgumentException per entrambi — quindi le restrizioni di accesso esterno che Apache Camel applica al
TransformerFactory che crea non sono mai state in vigore.
| Runtime | Directory | Stack |
|---|---|---|
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.36.0 (Quarkus 3.36.0, Camel 4.20.0) |
Solo Camel Quarkus. Il codice vulnerabile è un'estensione di Camel Quarkus, non un componente Camel. Il semplice Camel e Camel Spring Boot usano il
TransformerFactorydel JDK, che rispetta entrambi gli attributi, quindi non c'è nulla da riprodurre lì — questo repository pertanto non ha una variantecamel-spring-boot/.
Un attaccante che fornisce il documento XML da trasformare può leggere file locali o raggiungere posizioni di rete interne tramite una dichiarazione di entità esterna in quel documento.
cd camel-quarkus
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
Output atteso su una build affetta (abbreviato — il driver esegue sei probe, vedi
camel-quarkus/README.md):
1) xslt endpoint, body is a StreamSource, external entity -> file:///tmp/cve-2026-88789-secrets/db-password.txt
transformation result: [db.password=LOCAL-FILE-s3cr3t-99]
local file contents in the output: true
2) xslt endpoint, body is a StreamSource, external entity -> http://127.0.0.1:8080/internal/secret
transformation result: [INTERNAL-SECRET-s3cr3t-42]
internal endpoint response in the output: true
4) CONTROL - same document as a String body (Camel converts it to a SAXSource itself)
transformation result: []
local file contents in the output: false
5) TransformerFactory.newInstance() anywhere in the application
factory: org.apache.camel.quarkus.support.xalan.XalanTransformerFactory
setAttribute(ACCESS_EXTERNAL_DTD, ""): REFUSED, IllegalArgumentException: ...
identity transform of the same document: [... <data>db.password=LOCAL-FILE-s3cr3t-99</data> ...]
Requests the XML parser made to internal endpoints on its own: [GET /internal/secret, GET /internal/leak.dtd]
>>> PROVEN: ...
Verificato anche con Camel Quarkus 3.40.0: ogni probe che perdeva dati diventa silenzioso, gli endpoint interni
non ricevono alcuna richiesta, e il driver stampa NOT reproduced.
Sul percorso del componente xslt, sono affetti solo i body che raggiungono il transformer già come
javax.xml.transform.Source. I body di altri tipi — String, byte[], InputStream — vengono
convertiti da Apache Camel in un SAXSource con entità esterne e caricamento DTD esterni disabilitati, e non sono
affetti. Il probe 4 nel riproduttore è quel percorso sicuro, affiancato a quello non sicuro.
Poiché la factory è anche registrata come default JAXP (l'estensione di supporto fornisce
META-INF/services/javax.xml.transform.TransformerFactory), qualsiasi altro codice nell'applicazione che ottiene
una factory tramite TransformerFactory.newInstance() perde le stesse restrizioni, senza un errore. Ecco
perché l'advisory elenca estensioni che non trasformano mai nulla esse stesse:
| Estensione | Esposizione |
|---|---|
camel-quarkus-xslt | il percorso del componente xslt e il default JAXP |
camel-quarkus-xslt-saxon | il default JAXP |
camel-quarkus-tika | il default JAXP |
camel-quarkus-xmlsecurity | il default JAXP |
| Proprietà | Valore |
|---|---|
| Componente | camel-quarkus-support-xalan (estensione di supporto XSLT) |
| CWE | CWE-611 (Improper Restriction of XML External Entity Reference) |
| Gravità | Alta |
| Vettore di attacco | Un'entità esterna o un DTD esterno dichiarato nel documento XML da trasformare, dove il body raggiunge l'endpoint xslt già come javax.xml.transform.Source |
| Impatto | Lettura di file locali; invio di richieste a posizioni di rete interne (SSRF) |
| Versioni affette | Dalla 3.2.0 precedente alla 3.33.3, dalla 3.34.0 precedente alla 3.40.0 |
| Versioni corrette | 3.33.3 (ramo LTS), 3.40.0 |
| Issue GitHub | apache/camel-quarkus#9115 |
| Crediti | Scoperta tramite analisi interna, utilizzando Claude Security Tool |
Advisory: https://camel.apache.org/security/CVE-2026-88789.html
XalanTransformerFactory ora applica le restrizioni da sé invece di affidarsi ad attributi che Xalan non può
rispettare:
XMLReader che non risolve né entità generali esterne né
entità parametro esterne e non carica DTD esterni — la stessa configurazione che XmlConverter.createSAXParserFactory() di Apache Camel usa per i body che camel-xslt converte esso stesso in un SAXSource.
Un SAXSource che porta un XMLReader configurato dal chiamante viene usato così com'è, e DOMSource e StAXSource
sono già analizzati.document() vengono negate a meno che il
URIResolver dell'applicazione stessa non le risolva, e la restrizione è installata su ogni punto di ingresso che
fornisce qualcosa con cui trasformare, inclusi i punti di ingresso push SAX i cui transformer Xalan non copia il
resolver della factory. Le applicazioni che impostano il proprio resolver — camel-xslt lo fa su ogni exchange —
continuano a sovrascriverlo come prima.Corretto su main in
9a570b64 e
9dd11779,
backportato su 3.33.x in
ad9c5236 e
3d886769.
javax.xml.transform.Source costruito da input non attendibile a un endpoint xslt. Lascia il
body del messaggio come String, byte[] o InputStream in modo che Apache Camel lo converta prima in un SAXSource con
entità esterne disabilitate.convertBodyTo su un body Source esistente non è una soluzione alternativa: quella conversione esegue una
trasformazione identità attraverso la stessa factory. Il probe 5 nel riproduttore è quella trasformazione identità, e perde dati.com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl,
invece di affidarsi a TransformerFactory.newInstance(). Il probe 6 è quel controllo, e nega la lettura.Questo repository è pubblicato per scopi educativi e difensivi: per aiutare gli utenti di Apache Camel Quarkus a comprendere la vulnerabilità, verificare se sono affetti e confermare che l'aggiornamento la risolve. Non usare questo materiale contro sistemi che non possiedi o gestisci.