Alle Sicherheitshinweise

mercure

Code Injection durch eval()-Sandbox-Ausbruch in den Routing-Regeln

Die Routing-Engine von mercure entscheidet anhand vom Administrator definierter Regelausdrücke, wohin eingehende DICOM-Serien geleitet werden, und wertet diese mit Python-eval() aus, das nur durch ein leeres builtins-Mapping abgesichert ist. Diese Sandbox wird mit einer gängigen Objekt-Traversierungstechnik umgangen, sodass ein Administrator (oder wer eine Admin-Sitzung erlangt) beliebigen Code ausführen kann. Eine gespeicherte Regel läuft bei jeder vom Router ausgewerteten DICOM-Serie.

Verfasst vonVolker Schönefeld, Simon Weber2026-05-30
SchweregradKritischCVSS 9.1CVSS-3.1-VektorAV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:HCWECWE-94 (Improper Control of Generation of Code (Code Injection))ProduktmercureBetroffene VersionenAlle Releases von 0.2.0-beta.1 bis 0.4.0-beta.9.Behoben in0.4.1. Die Regelauswertung nutzt nun standardmäßig asteval mit geleerter Symboltabelle; der frühere eval()-Pfad läuft nur, wenn die Umgebungsvariable MERCURE_UNSAFE_RULE_EVALUATION gesetzt ist.CVEAusstehendGHSAAusstehend

Beschreibung

mercure ist eine quelloffene DICOM-Orchestrierungsplattform; wir schätzen die schnelle, konstruktive Reaktion der Maintainer auf diesen Bericht. Die Routing-Engine entscheidet anhand vom Administrator definierter Regelausdrücke, wohin jede eingehende DICOM-Serie geleitet wird.

Diese Ausdrücke werden mit Pythons eval() ausgewertet, das nur durch ein leeres builtins-Mapping abgesichert ist:

app/common/rule_evaluation.py:49-71

safe_eval_cmds = {"float": float, "int": int, "str": str, "len": len, "bool": bool,
"sum": sum, "round": round, "max": max, "min": min, "abs": abs,
"pow": pow, "chr": chr, "ord": ord}
def eval_rule(rule: str, tags_dict: Dict[str, str]) -> Any:
# ...
rule = replace_tags(rule, tags_dict)
# ...
tags_obj = Tags(tags_dict)
result = eval(rule, {"__builtins__": {}}, {**safe_eval_cmds, "tags": tags_obj})
# ...
return result, tags_obj.tags_accessed()

View source →

Ein leeres __builtins__ entfernt den direkten Zugriff auf eingebaute Funktionen, verhindert aber keine Objekt-Traversierung: Von einem beliebigen Literal aus lässt sich die Basisklasse object erreichen, ihre Subklassen aufzählen und eine Klasse finden, die die echte Import-Maschinerie freilegt, womit __import__ und beliebige Befehlsausführung zurückgewonnen werden. Die 0.4.1-Release-Notes des Herstellers beschreiben dies als "trivially bypassed via MRO class traversal". Wir veröffentlichen keinen funktionsfähigen Payload.

Das Feld rule erreicht die Auswertung ohne Validierung. HTML-Bereinigung wird auf das Feld tags angewandt, nicht auf rule:

app/webinterface/rules.py:269

testrule = form["rule"] # rohe Formulareingabe, keine Validierung
testvalues = json.loads(form["testvalues"])
result, attrs_accessed = rule_evaluation.eval_rule(testrule, testvalues)

View source →

Zwei Pfade erreichen die Senke. /rules/test wertet den Ausdruck sofort aus und gibt das Ergebnis in der HTTP-Antwort zurück, sodass Befehlsausgaben und Dateiinhalte direkt an den Aufrufer zurückfließen. Eine über /rules/edit/{rule} gespeicherte Regel wird in mercure.json persistiert und läuft bei jeder vom Router ausgewerteten DICOM-Serie, was persistente Ausführung ergibt.

Die Auswertung läuft im Prozess der Weboberfläche (Sofort-Pfad) oder im Router-Prozess (gespeicherter Pfad), sodass die Ausführung das gemeinsame Dateisystem, Redis und das übrige Docker-Netzwerk erreicht. Die Scope-Change-Metrik spiegelt das wider.

Die Befehlsausführung als Benutzer mercure wird durch die zurückgegebene Ausgabe eines eingeschleusten id-Kommandos bestätigt:

Proof-of-Concept-Ausgabe

uid=1000(mercure) gid=1000(mercure) groups=1000(mercure)

Auswirkung

  • Ein Angreifer mit Administrator-Sitzung kann beliebigen Code auf dem mercure-Host ausführen. Der Endpunkt /rules/test gibt das Ergebnis inline zurück, sodass Dateien, Umgebungsvariablen und Anmeldedaten direkt über die Weboberfläche gelesen werden können.
  • Eine vom Angreifer gespeicherte Routing-Regel läuft bei jeder vom Router ausgewerteten DICOM-Serie und ermöglicht persistente Codeausführung, die automatisch beim Durchlauf von Bilddaten ausgelöst wird.
  • Da die Auswertung im Prozess der Weboberfläche oder des Routers läuft, erreicht der Angreifer das gemeinsame Dateisystem, Redis und weitere Container im Docker-Netzwerk.

Abhilfe

Aktualisieren Sie auf mercure 0.4.1, das Regeln standardmäßig mit asteval und geleerter Symboltabelle auswertet; der frühere eval()-Pfad läuft nur, wenn MERCURE_UNSAFE_RULE_EVALUATION gesetzt ist, was nicht aktiviert werden sollte. Für jeden Code dieser Art gilt: eval() nicht auf benutzergelieferte Ausdrücke anwenden, sondern einen spezialisierten sicheren Evaluator (etwa asteval) oder eine kleine geparste Vergleichs-DSL verwenden und Attributzugriffe auf Dunder- oder private Namen ablehnen.

Checkliste für Betreiber

  • Auf 0.4.1 oder neuer aktualisieren

    Das gepatchte Release ausrollen und sicherstellen, dass MERCURE_UNSAFE_RULE_EVALUATION in keiner Umgebung gesetzt ist.

  • Gespeicherte Routing-Regeln prüfen

    mercure.json auf Regelausdrücke prüfen, die Attributzugriffe oder Funktionsaufrufe über einfache Tag-Vergleiche hinaus enthalten; solche sollten nicht vorhanden sein.

  • Administrator-Zugriff einschränken

    Begrenzen, wer Administrator-Anmeldedaten besitzt, und sicherstellen, dass das Standard-Admin-Passwort geändert wurde.

Bewertung im Detail

AV:NSowohl der Sofort-Pfad (/rules/test) als auch der persistente Pfad (gespeicherte Regel) werden über das Netzwerk über die Weboberfläche erreicht.AC:LEine einzige Anfrage mit einem präparierten Ausdruck genügt.PR:HDie Regel-Endpunkte erfordern eine Administrator-Sitzung.UI:NDer Sofort-Pfad gibt das Ergebnis direkt zurück; gespeicherte Regeln werden bei der automatischen Serienauswertung ohne Benutzerinteraktion ausgelöst.S:CDie Auswertung im Prozess der Weboberfläche oder des Routers erreicht Ressourcen jenseits dieser Komponente: das gemeinsame Dateisystem, Redis und weitere Container.C/I/A:HBeliebige Codeausführung gewährt vollständigen Lese-, Änderungs- und Verweigerungszugriff auf erreichbare Daten und Dienste.

Referenzen

So können wir helfen

Wer wir sind

Die Sicherheitsforscher hinter diesem Sicherheitshinweis.

Dr. Simon Weber Profile

Dr. rer. nat. Simon Weber

Senior Pentester & MedSec-Forscher

Ich evaluiere Ihr SaMD mit derselben branchenprägenden Sicherheitsexpertise, die ich dem BAK MV für die Überarbeitung des B3S-Standards beigetragen habe.

  • Promotion über Krankenhaus-Cybersicherheit
  • Kritische Schwachstellen in Krankenhaussystemen gefunden
  • Alumni der THB MedSec-Forschungsgruppe
  • gematik Security Hero
Volker Schönefeld Profile

Dipl.-Inf. Volker Schönefeld

Senior Application Security Expert

Als ehemaliger CTO und Entwickler, der zum Pentester wurde, arbeite ich mit Ihrem Team zusammen, um Schwachstellen aufzudecken und Lösungen zu finden, die zu Ihrer Architektur passen.

  • 20+ Jahre als CTO, 50+ Mio. App-Downloads
  • Architektur und Absicherung großer IoT-Flotten
  • Certified Web Exploitation Specialist
  • gematik Security Hero

Penetrationstest gesucht?

Machine Spirits ist spezialisiert auf Sicherheitsbewertungen für Medizinprodukte und Gesundheits-IT. Von MDR-Penetrationstests bis C5-Cloud-Compliance helfen wir MedTech-Unternehmen, regulatorische Anforderungen zu erfüllen.