
Reproduction d'un problème de sécurité de haute sévérité qui permet des attaques XXE (XML eXternal Entity) sur la sérialisation XML de Ktor.
CVE-2023-45612 est un problème de sécurité de haute sévérité qui permet des attaques XXE (XML eXternal Entity) sur la sérialisation XML de Ktor, qui a été corrigé en 2023.
Voici une manière détaillée dont j'ai reproduit le problème.
Premièrement, nous avons besoin d'un serveur qui va traiter les fichiers XML. Nous créons un projet Kotlin depuis IntelliJ IDEA et modifions le fichier build.gradle.kts afin d'utiliser les dépendances Ktor dont nous avons besoin et le plugin de sérialisation. io.ktor:ktor-serialization-kotlinx-xml est la dépendance qui nous intéresse. La version 2.3.4 est la version vulnérable, et la version 2.3.5 est celle corrigée.
Ensuite, nous ajoutons à la racine du projet un fichier nommé sensitive_infos.txt qui est destiné à être privé et non accessible depuis l'extérieur du serveur. Le contenu de ce fichier est "Ces informations devraient être secrètes et inaccessibles en envoyant un fichier .xmf.".
Ensuite, nous implémentons le serveur dans le fichier Main.kt. Il est conçu pour traiter le XML envoyé par le client en le sérialisant en une chaîne (name) de la classe Person. Le serveur répond ensuite en confirmant le nom que le client vient d'envoyer. Après avoir démarré le serveur, nous pouvons essayer l'utilisation normale et l'utilisation malveillante :
Le client envoie un fichier XML avec son nom et reçoit une confirmation avec le nom qu'il vient d'envoyer. Nous pouvons tester cela avec le fichier XML suivant :
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns="http://example.com/">
<name>Clément</name>
</manifest>
et la commande :
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @data.xml
Le client définit une entité en fournissant une chaîne de substitution sous forme d'URI et envoie le fichier XML malveillant, puis reçoit le contenu d'un fichier secret accessible par le serveur. Je montre ci-dessous un exemple avec un fichier (sensitive_infos.txt) situé à la racine du serveur, mais notez que vous pourriez également atteindre d'autres fichiers (si l'analyseur XML peut accéder à leur contenu) avec par exemple file:/// si le serveur tourne sous 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>
et la commande
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @xxe.xml
Le serveur répond avec "Name sent: Ces informations devraient être secrètes et inaccessibles en envoyant un fichier .xmf.", ce qui prouve que nous avons bien accédé aux informations secrètes et qu'il existe donc une vulnérabilité.
D'ailleurs, changer la version de 2.3.4 à 2.3.5 dans le fichier build.gradle.kts résout le problème et le serveur ne répond plus que "Name sent" pour l'entrée malveillante, tout en conservant une réponse normale pour l'entrée normale, ce qui nous confirme que le problème de sécurité a été résolu dans la version 2.3.5.
Ne jamais faire confiance à l'utilisateur ! L'analyseur Ktor pourrait assainir les entrées en, par exemple, rejetant tous les fichiers XML d'entrée qui contiennent une entité.
Moins restrictif pour l'utilisateur, Ktor pourrait désactiver les entités externes par défaut en réglant les fonctionnalités external-general-entities et external-parameter-entities à false, de sorte que l'utilisateur puisse toujours déclarer une entité dans son fichier XML, mais cette entité ne peut plus accéder à aucune ressource externe.
Inclure des tests d'attaque XXE dans le CI/CD de Ktor afin d'être sûr que le code n'y est pas vulnérable.