mercure
Server-Side Template Injection im Benachrichtigungssystem
mercure kann eine Benachrichtigung (Webhook oder E-Mail) senden, wenn eine DICOM-Serie zu einer Routing-Regel passt. Der Benachrichtigungstext ist ein vom Administrator konfiguriertes Template, das mit einer ungesicherten Jinja2-Engine ohne Validierung gerendert wird. In dieses Feld eingefügte Template-Syntax bricht zu beliebiger Codeausführung aus, und da Benachrichtigungen bei jeder passenden Serie ausgelöst werden, läuft der Code dauerhaft, während Bilddaten durchlaufen.
SandboxedEnvironment statt des nackten Template().CVEAusstehendGHSAAusstehendBeschreibung
mercure ist eine quelloffene DICOM-Orchestrierungsplattform; wir schätzen die schnelle, konstruktive Reaktion der Maintainer auf diesen Bericht. Wenn eine DICOM-Serie zu einer Routing-Regel passt, kann mercure eine Benachrichtigung auslösen, deren Text ein vom Administrator konfiguriertes Template ist.
Dieser Text wird mit Jinja2s nacktem Template() gerendert, ohne SandboxedEnvironment, ohne Autoescape und ohne Validierung des Template-Inhalts:
app/common/notification.py:60-85
from jinja2 import Template
def parse_payload(payload, event, rule_name, task_id, details="", context={}, *, task=None, tags_list=None): payload_parsed = payload payload_parsed = payload_parsed.replace("@rule@", rule_name) payload_parsed = payload_parsed.replace("@task_id@", task_id) payload_parsed = payload_parsed.replace("@event@", event.name) # ... Kontext-Setup ... return Template(payload_parsed).render(context) # ungesichertes Jinja2Jinja2s Standardumgebung erlaubt Attributzugriff, sodass dieselbe Objekt-Traversierung greift, die auch die eval()-Sandbox der Routing-Regeln aushebelt: Von einem String-Literal aus wird die Basisklasse object erreicht, ihre Subklassen aufgezählt und __import__ für beliebige Befehlsausführung zurückgewonnen. Die 0.4.1-Release-Notes des Herstellers bestätigen, dass die Templates "rendered without sandboxing, allowing arbitrary code execution on every matching DICOM series" wurden. Wir veröffentlichen keinen funktionsfähigen Payload.
Die Benachrichtigungs-Template-Felder erhalten keine Bereinigung. strip_untrusted() wird auf das Feld tags angewandt, nicht auf einen Benachrichtigungstext:
app/webinterface/rules.py:217-218
notification_payload_body=form.get("notification_payload_body", ""), # keine Bereinigungnotification_email_body=form.get("notification_email_body", ""), # keine BereinigungEinen Benachrichtigungstext an einer Regel zu hinterlegen, den Webhook auf eine beliebige URL zu setzen und den Empfangs-Trigger aktiviert zu lassen (Standard für neue Regeln) genügt: Der Router rendert das Template bei jeder passenden Serie, bevor der Webhook gesendet wird, sodass der eingeschleuste Code im Router-Prozess läuft. Dieser Prozess erreicht das gemeinsame Dateisystem, Redis, die durchlaufenden DICOM-Daten und weitere Container, was den Scope-Wechsel ausmacht. Der Payload bleibt in mercure.json bestehen und ist gültiges Jinja2, ähnelt also einem normalen Template.
Die Befehlsausführung als Benutzer mercure im Router wird durch die 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 ein Benachrichtigungs-Template hinterlegen, das beliebigen Code im Router-Prozess ausführt. Es läuft bei jeder zur Regel passenden DICOM-Serie, sodass die Ausführung dauerhaft ist und automatisch beim Durchlauf von Bilddaten ausgelöst wird.
- Der Router-Prozess erreicht das gemeinsame Dateisystem, Redis, die durchlaufenden DICOM-Daten und weitere Container im Docker-Netzwerk. Befehlsausgaben können zudem über den Webhook-Text selbst zurückgegeben werden.
- Der Payload bleibt in
mercure.jsonbestehen und ist syntaktisch gültiges Jinja2, sodass er sich kaum von einem legitimen Template unterscheiden lässt.
Abhilfe
Aktualisieren Sie auf mercure 0.4.1, das Benachrichtigungen und andere benutzerkonfigurierte Templates mit jinja2s SandboxedEnvironment statt des nackten Template() rendert; die Sandbox blockiert den Attributzugriff, auf den der Ausbruch angewiesen ist. Als zusätzliche Schutzmaßnahme den Template-Inhalt beim Speichern validieren und Attributzugriffsmuster wie __class__, __subclasses__ und __import__ ablehnen.
Checkliste für Betreiber
Auf 0.4.1 oder neuer aktualisieren
Das gepatchte Release ausrollen, das Templates mit
SandboxedEnvironmentrendert.Benachrichtigungs-Templates prüfen
Benachrichtigungstext-Felder in
mercure.jsonauf Attributzugriffsmuster (__class__,__subclasses__,__import__) prüfen; diese sollten in einem normalen Template nicht vorkommen.Administrator-Zugriff einschränken
Begrenzen, wer Administrator-Anmeldedaten besitzt, und sicherstellen, dass das Standard-Admin-Passwort geändert wurde.
Bewertung im Detail
Referenzen
So können wir helfen
Wer wir sind
Die Sicherheitsforscher hinter diesem Sicherheitshinweis.

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

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.
