Alle Sicherheitshinweise

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.

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-1336 (Improper Neutralization of Special Elements Used in a Template Engine)ProduktmercureBetroffene VersionenAlle Releases von 0.2.0-beta.1 bis 0.4.0-beta.9.Behoben in0.4.1. Das Rendern von Benachrichtigungen und Templates nutzt nun jinja2s SandboxedEnvironment statt des nackten Template().CVEAusstehendGHSAAusstehend

Beschreibung

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 Jinja2

View source →

Jinja2s 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 Bereinigung
notification_email_body=form.get("notification_email_body", ""), # keine Bereinigung

View source →

Einen 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.json bestehen 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 SandboxedEnvironment rendert.

  • Benachrichtigungs-Templates prüfen

    Benachrichtigungstext-Felder in mercure.json auf 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

AV:NDas Template wird über das Netzwerk über die Weboberfläche konfiguriert und bei über das Netzwerk gelieferten DICOM-Serien ausgelöst.AC:LDas einmalige Hinterlegen des Templates genügt; danach wird es automatisch ausgelöst.PR:HDas Bearbeiten von Routing-Regeln und Benachrichtigungs-Templates erfordert eine Administrator-Sitzung.UI:NDas Rendern erfolgt automatisch beim Empfang einer passenden Serie; keine Benutzerinteraktion.S:CDas Rendern im Router-Prozess erreicht das gemeinsame Dateisystem, Redis und weitere Container jenseits der Komponente.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.