Alle Sicherheitshinweise

Orthanc DICOM Server

Heap-Buffer-Overflow in der PAM-Bildpuffer-Allokation

Der PAM-Bildparser von Orthanc berechnet den Puffer-Pitch mit 32-Bit-Integer-Arithmetik. Manipulierte Bildmaße lassen die Multiplikation überlaufen, sodass eine winzige Allokation entsteht, in die die nachfolgende Byte-Swap-Schleife unter Verwendung der ursprünglichen (nicht überlaufenen) Breite weit hinausschreibt.

Verfasst vonVolker Schönefeld, Simon WeberErstveröffentlichung 2026-04-02Vollständige Offenlegung 2026-04-28
SchweregradHochCVSS 7.1CVSS-3.1-VektorAV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:HCWECWE-787 (Out-of-bounds Write)ProduktOrthanc DICOM ServerBetroffene VersionenOrthanc <= 1.12.10Behoben in1.12.11CVECVE-2026-5444CERT/CCVU#536588.1

Beschreibung

Orthanc nimmt PAM-Bilder (Portable Arbitrary Map) in POST /tools/create-dicom-Requests entgegen, wobei der PAM-Payload base64-kodiert im JSON-Feld Content angeliefert wird. Der PAM-Parser in PamReader.cpp liest die Felder WIDTH, HEIGHT, DEPTH und MAXVAL aus dem textuellen PAM-Header und berechnet daraus Zeilen-Pitch und Gesamtgröße des Puffers vor der Allokation.

Die Pitch-Berechnung multipliziert drei unsigned int-Werte ohne Überlaufschutz:

OrthancFramework/Sources/Images/PamReader.cpp:188

// width, channelCount, bytesPerChannel sind alle unsigned int (32 Bit).
// z. B. WIDTH=715827883, DEPTH=3, MAXVAL=65535 (bytesPerChannel=2):
// 715827883 * 3 * 2 = 4294967298 (0x100000002)
// Trunkiert auf uint32: 2
unsigned int pitch = width * channelCount * bytesPerChannel;

View source →

Der trunkierte pitch-Wert bestimmt anschließend die Allokation:

OrthancFramework/Sources/Images/PamReader.cpp:214

// allokiert pitch * height = 2 * 1 = 2 Bytes
alignedImageBuffer_ = malloc(pitch * height);

View source →

Die bestehende Längenprüfung in PamReader.cpp:190 (content_.size() != header.size() + headerDelimiter.size() + pitch * height) erkennt den Überlauf nicht, da die PAM-Dateigröße ebenfalls vom Angreifer kontrolliert wird und passend zum trunkierten Wert gewählt werden kann.

Die Byte-Swap-Schleife iteriert anschließend mit der ursprünglichen (nicht trunkierten) width und schreibt pro Iteration zwei Bytes weit hinter die kleine Allokation:

OrthancFramework/Sources/Images/PamReader.cpp:240-272

// Schleife durchläuft `width` Iterationen (z. B. 715827883).
// Jede Iteration verschiebt einen uint16_t-Zeiger und schreibt
// an Offsets 0, 2, 4, ... über ~1,4 GB Heap hinter den Puffer.
for (unsigned int w = 0; w < width; ++w, ++pixel) {
uint8_t* srcdst = reinterpret_cast<uint8_t*>(pixel);
uint8_t tmp = srcdst[0]; // Out-of-Bounds-Lesezugriff
srcdst[0] = srcdst[1]; // Out-of-Bounds-Schreibzugriff
srcdst[1] = tmp; // Out-of-Bounds-Schreibzugriff
}

View source →

Der gesamte Payload umfasst 71 Bytes (PAM-Header plus zwei Bytes Pixeldaten), base64-kodiert im JSON-Request-Body. AddressSanitizer verortet den ersten Out-of-Bounds-Zugriff in PamReader.cpp:268, unmittelbar hinter der 2-Byte-Allokation aus PamReader.cpp:214:

AddressSanitizer-Trace

==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xffffabc81372
READ of size 1 at 0xffffabc81372 thread T16
#0 in Orthanc::PamReader::ParseContent() PamReader.cpp:268
#1 in Orthanc::PamReader::ReadFromMemory() PamReader.cpp:295
#2 in Orthanc::ParsedDicomFile::EmbedImage() ParsedDicomFile.cpp:1300
#3 in Orthanc::ParsedDicomFile::EmbedContent() ParsedDicomFile.cpp:1262
#4 in CreateDicomV2 OrthancRestAnonymizeModify.cpp:1029
#5 in CreateDicom OrthancRestAnonymizeModify.cpp:1108
0xffffabc81372 is located 0 bytes to the right of 2-byte region [0xffffabc81370,0xffffabc81372)
allocated by thread T16 here:
#0 in __interceptor_malloc
#1 in Orthanc::PamReader::ParseContent() PamReader.cpp:214

Auf einem Standard-Build ohne ASAN läuft die Byte-Swap-Schleife in nicht gemappten Speicher, und der Prozess terminiert innerhalb von Millisekunden nach Behandlung des Requests mit SIGSEGV (Exit-Code 139).

Auswirkung

  • Denial-of-Service: Ein einzelner authentisierter POST /tools/create-dicom-Request mit einem 71 Byte großen PAM-Payload beendet den Orthanc-Prozess mit SIGSEGV. Der Server muss nach jedem Request neu gestartet werden und ist anschließend sofort wieder angreifbar.
  • Heap-Write-Primitive: Die Schleife führt sequenzielle 2-Byte-Swaps über rund 1,4 GB Heap hinter der Allokation durch. Ein Ausführen von beliebigem Programmcode wurde nicht nachgewiesen; die Form der Primitive (kontrollierte Offsets, vom Angreifer beeinflusste Bytes) macht sie zu einem plausiblen Ziel für weitere Exploitation-Forschung.
  • Das Angriffsmodell hängt von der Orthanc-Konfiguration ab: Bei aktivem AuthenticationEnabled handelt es sich um einen authentisierten Angreifer mit Rechten zum Hochladen oder Modifizieren von Studien; ohne HTTP-Authentifizierung (eine zulässige Orthanc-Konfiguration) ist der Endpunkt für jeden netzseitig erreichbaren Aufrufer offen.

Abhilfe

Aktualisieren Sie Orthanc auf Version 1.12.11 oder höher. Der Patch führt sowohl eine Validierung der Header-Werte zur Parse-Zeit als auch 64-Bit-Arithmetik mit expliziten Überlaufprüfungen vor der Allokation durch. Ergänzend lässt sich POST /tools/create-dicom per Pro-Route-Autorisierung in orthanc.json weiter einschränken.

Checkliste für Betreiber

  • Version prüfen.

    curl -u <user>:<pass> http://<orthanc>:8042/system | jq .Version — der gepatchte Bereich beginnt bei 1.12.11.

  • Betroffenen Endpunkt einschränken.

    Sperren oder beschränken Sie POST /tools/create-dicom an Ihrem Reverse-Proxy (nginx, Traefik etc.) für alle Rollen, die DICOM-Dateien nicht programmatisch erstellen müssen.

  • Zugangsdaten überprüfen.

    Die Schwachstelle erfordert einen authentisierten Benutzer. Prüfen Sie RegisteredUsers in orthanc.json sowie ein externes Authentifizierungsbackend auf Konten, die keine create-dicom-Rechte benötigen.

  • Logs auf verdächtige Aktivität prüfen.

    Suchen Sie nach früheren POST /tools/create-dicom-Aufrufen mit ungewöhnlich kleinen Request-Bodies (unter ~200 Bytes) sowie nach unerwarteten Prozessneustarts in Ihrer Service-Überwachung (z. B. journalctl -u orthanc | grep -E 'SIGSEGV|killed').

  • Crash-Recovery konfigurieren.

    Ein erfolgreicher Denial-of-Service sollte auf die Neustartzeit Ihrer Service-Überwachung begrenzt sein (systemd, Kubernetes Liveness Probes, Docker --restart). Recovery behebt die Schwachstelle nicht, begrenzt aber die Auswirkungen.

Bewertung im Detail

AV:LDer publizierte Vektor behandelt den Pfad als Local-Vector: Eine Person liefert einen manipulierten PAM-Payload, den die Anwendung verarbeitet. Hinweis: Die Schwachstelle ist auch netzseitig über POST /tools/create-dicom erreichbar.AC:LEin einzelner 71 Byte großer PAM-Payload mit überlaufenen Bildmaßen; keine Timing-, Race- oder Umgebungsvorbedingungen.PR:NDer publizierte Vektor spiegelt Deployments wider, in denen POST /tools/create-dicom ohne HTTP-Authentifizierung exponiert ist, was Orthanc per Konfiguration erlaubt.UI:REin Aufrufer (derselbe oder ein anderer) muss den manipulierten PAM-Payload per POST /tools/create-dicom einreichen, damit Allokation und Byte-Swap-Schleife ausgelöst werden.S:UNur der Orthanc-Prozess ist betroffen; über diese Primitive sind keine prozessübergreifenden Ressourcen erreichbar.C:NDer publizierte Vektor schreibt der Heap-Write-Primitive keine Vertraulichkeitsauswirkung zu. Die Byte-Swap-Schleife ist eine Schreib-Primitive; ein Lesezugriff auf Prozessspeicher wäre eine nachgelagerte Folge plausiblen Ausführens von Programmcode und ist nicht direkt nachgewiesen.I:HPlausibles Ausführen von beliebigem Programmcode innerhalb der Sicherheitsautorität des Orthanc-Prozesses erlaubt eine Modifikation von In-Memory-Zuständen und aller Daten, die der Prozess schreiben kann. Nicht nachgewiesen.A:HEin einzelner Request beendet den Prozess mit SIGSEGV.

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.