Alle Sicherheitshinweise

Orthanc DICOM Server

Heap-Buffer-Overflow im DICOM-Bilddecoder (Palette-Color-Decodierung)

Der PALETTE-COLOR-Bilddecodierungspfad von Orthanc führt die Pixeldatenlängen-Validierung und die Allokation des Zielpuffers mit 32-Bit-Arithmetik durch. Manipulierte DICOM-Bildmaße lassen beide Multiplikationen auf einen kleinen Wert überlaufen, die Validierung gelingt gegen das überlaufene Resultat, und die Decode-Schleife iteriert anschließend mit den ursprünglichen (nicht überlaufenen) Bildmaßen — wobei sie über den Pixelpuffer hinaus liest und über den Zielpuffer hinaus schreibt.

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

Beschreibung

Beim Dekodieren eines PALETTE-COLOR-Bildes prüft Orthanc zunächst, ob die gelieferte Pixeldatenlänge dem erwarteten width * height entspricht, und allokiert anschließend einen RGB24-Zielpuffer mit derselben Arithmetik. Beide Berechnungen verwenden unsigned int (32 Bit). Mit Cols=1431655766 und Rows=3 läuft die Multiplikation über:

OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp:463

// alle Operanden sind unsigned int (32 Bit)
// Mit Cols=1431655766, Rows=3: 1431655766 * 3 = 4294967298 → uint32: 2
// pixelLength=2 passt zum überlaufenen Resultat → Validierung gelingt
if (pixelLength != target->GetWidth() * target->GetHeight())

View source →

Ein Angreifer, der die Pixeldatenlänge kontrolliert, kann sie auf den überlaufenen Wert (2 Bytes) abstimmen, sodass die Validierung gelingt. Derselbe Überlauf bestimmt anschließend die Allokation des Zielpuffers. Für RGB24 ist der Pitch 3 * width; mit width=1431655766 läuft auch dieser auf 2 über, was eine winzige Allokation von 6 Bytes (pitch * height = 2 * 3) ergibt:

OrthancFramework/Sources/Images/ImageBuffer.cpp:49

// RGB24-Pitch: 3 * 1431655766 → uint32: 2
pitch_ = GetBytesPerPixel() * width_;
// Gesamtallokation: 2 * 3 = 6 Bytes (sollten ~4 GB für RGB24 sein)

View source →

Die Decode-Schleife läuft anschließend mit den ursprünglichen (nicht überlaufenen) Bildmaßen: 1,4 Milliarden Pixel-Iterationen gegen einen 2-Byte-Pixelpuffer (Out-of-Bounds-Lesezugriff) und einen 6-Byte-Zielpuffer (Out-of-Bounds-Schreibzugriff). Bereits die erste Iteration jenseits des dritten Pixels löst beide Primitiven aus:

OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp:491-503

// iteriert 1431655766 * 3 mal
// Bei Pixel #3: source liest über den 2-Byte-Pixelpuffer hinaus (OOB-Lesezugriff)
// Bei Pixel #3: p schreibt über den 6-Byte-Zielpuffer hinaus (OOB-Schreibzugriff)
for (unsigned int x = 0; x < width; x++)
{
p[0] = lutRed[*source] >> offsetBits; // OOB-Lesezugriff via *source
p[1] = lutGreen[*source] >> offsetBits;
p[2] = lutBlue[*source] >> offsetBits; // OOB-Schreibzugriff via p[2]
source++;
p += 3;
}

View source →

Der Auslöser ist derselbe VR-UL-Dimensions-Bypass wie bei CVE-2026-5442: DICOM definiert Rows/Columns als VR US (max. 65535), DCMTK liest die VR jedoch in der Explicit-VR-Little-Endian-Transfer-Syntax direkt aus der Datei. Eine Kodierung von Rows/Columns mit VR UL erlaubt beliebige 32-Bit-Werte, die Orthanc ohne Validierung akzeptiert. Mit Standard-VR-US-Werten kann die Multiplikation nicht überlaufen (max. 65535*65535 = 4.294.836.225 < uint32-Maximum), sodass der VR-UL-Bypass essenziell ist.

AddressSanitizer verortet den ersten Out-of-Bounds-Zugriff in DicomImageDecoder.cpp:497, unmittelbar hinter einer 2-Byte-Heap-Region:

AddressSanitizer-Trace

==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xffffa6887072
READ of size 1 at 0xffffa6887072 thread T18
#0 in DecodeLookupTable DicomImageDecoder.cpp:497
#1 in Orthanc::DicomImageDecoder::DecodeUncompressedImage() DicomImageDecoder.cpp:575
#2 in Orthanc::DicomImageDecoder::Decode() DicomImageDecoder.cpp:827
#3 in Orthanc::ParsedDicomFile::DecodeFrame() ParsedDicomFile.cpp:1823
#4 in Orthanc::ServerContext::DecodeDicomFrame() ServerContext.cpp:1921
0xffffa6887072 is located 0 bytes to the right of 2-byte region [0xffffa6887070,0xffffa6887072)
allocated by thread T18 here:
#0 in operator new[]
#1 in DcmElement::newValueField() dcelem.cc:788

Auf einem Standard-Build läuft die Schleife über die kleine Heap-Region hinaus, bis sie eine nicht gemappte Seite trifft; der Orthanc-Prozess terminiert. Die Erreichbarkeit entspricht CVE-2026-5445: authentisierter HTTP-Upload + Vorschau, oder unauthentifizierte C-STORE-Ablage auf Port 4242 unter dem Default DicomAlwaysAllowStore: true. Sobald das manipulierte DICOM gespeichert ist, lässt jede Vorschau-Anfrage durch eine beliebige Person den Server abstürzen — das manipulierte DICOM ist persistent und reproduziert den Absturz bei jedem Render-Vorgang.

Auswirkung

  • Persistenter Denial-of-Service: Eine einzelne gespeicherte DICOM-Datei lässt den Orthanc-Prozess bei jeder Vorschau-Anfrage durch eine beliebige Person abstürzen. Ein Neustart stellt den Dienst wieder her, doch das manipulierte DICOM verbleibt; jede nachfolgende Vorschau lässt den Server erneut abstürzen.
  • Heap-Write-Primitive: Die Schleife schreibt sequenzielle RGB-Tripel (3 Bytes pro Pixel) über einen 6-Byte-Zielpuffer hinaus mit kontrollierten, aus den Pixeldaten abgeleiteten Bytes. Ein Ausführen von beliebigem Programmcode innerhalb der Sicherheitsautorität des Orthanc-Prozesses wurde nicht nachgewiesen; die Form der Primitive (sequenziell, kontrollierte Bytes, mehrere Gigabyte Spanne) macht sie zu einem plausiblen Ziel für weitere Exploitation-Forschung.
  • In Orthancs Default-Konfiguration (DicomAlwaysAllowStore: true) ist das Ablegen unauthentifiziert; der Auslöser benötigt nur eine Vorschau-Anfrage einer beliebigen Read-Level-Person.

Abhilfe

Aktualisieren Sie Orthanc auf Version 1.12.11 oder höher. Der Patch verwendet 64-Bit-Arithmetik für jede Pixeldatenlängen-Validierung und kombiniert sie mit der Ablehnung von Rows/Columns-Werten jenseits des VR-US-Bereichs (65535) zur Parse-Zeit — dieselbe Dimensionsvalidierung, die auch CVE-2026-5442 mitigiert. Als sofortige Defense-in-Depth-Maßnahme setzen Sie DicomAlwaysAllowStore: false in orthanc.json und konfigurieren eine AET-Allowlist, was den unauthentifizierten Ablegevektor schließt.

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.

  • Unauthentifizierten C-STORE-Ablegevektor schließen.

    Setzen Sie DicomAlwaysAllowStore: false in orthanc.json und definieren Sie eine explizite DicomModalities-Allowlist legitimer AETs. Andernfalls kann jeder Host, der Port 4242 erreicht, die persistent abstürzende DICOM-Datei unauthentifiziert ablegen.

  • DICOM-Speicher vor dem Patch in Quarantäne und prüfen.

    Durchsuchen Sie den Speicher nach Studien, deren Rows oder Columns 65535 überschreiten (nur mit VR-UL-Kodierung möglich). Solche Studien sind konstruktionsbedingt manipuliert, da DICOM diese Tags als VR US (max. 65535) definiert. Vor dem Patch in Quarantäne geben, da die nächste Vorschau-Anfrage den Server abstürzen lässt.

  • Vorschau-Berechtigungen prüfen.

    Sobald eine manipulierte Studie gespeichert ist, lässt jede Read-Level-Person, die GET /instances/*/preview aufruft, den Prozess abstürzen. Beschränken Sie den Vorschau-Zugriff am Reverse-Proxy auf die IPs der Integrationspunkte und Viewer, die ihn benötigen.

  • Auf Crash-Restart-Zyklen nach Vorschau-Anfragen achten.

    Alarmieren Sie auf Orthanc-Neustarts (journalctl -u orthanc | grep -E 'SIGSEGV|killed'), die unmittelbar GET /instances/*/preview-Logeinträgen folgen. Wiederholte Abstürze derselben Study-ID deuten auf einen gespeicherten Angriff statt auf einen vorübergehenden Fehler hin.

  • Crash-Recovery konfigurieren.

    Bis der Speicher von der manipulierten Studie bereinigt ist, lässt jede Vorschau den Prozess abstürzen. Eine enge Service-Überwachung (systemd, Kubernetes Liveness Probes, Docker --restart) hält den Dienst zwischen den Anfragen verfügbar, behebt die Schwachstelle aber nicht.

Bewertung im Detail

AV:NÜber das Netzwerk per HTTP-REST-API von Orthanc sowie per DICOM C-STORE auf Port 4242 erreichbar.AC:LEine einzelne manipulierte DICOM-Datei mit VR-UL-Bildmaßen und 2 Byte Pixeldaten. Keine Timing- oder Umgebungsvorbedingungen.PR:NDer publizierte Vektor spiegelt Deployments wider, in denen die Vorschau-Wiedergabe ohne HTTP-Authentifizierung exponiert ist und der C-STORE-Listener unter dem Default DicomAlwaysAllowStore: true unauthentifizierte Requests akzeptiert.UI:NKeine Interaktion durch eine zweite Person erforderlich; Ablegen und Auslösen können von derselben Person durchgeführt werden.S:UNur der Orthanc-Prozess ist betroffen; über diese Primitive sind keine prozessübergreifenden Ressourcen erreichbar.C:HPlausibles Ausführen von beliebigem Programmcode innerhalb der Sicherheitsautorität des Orthanc-Prozesses legt Prozessspeicher und alle vom Prozess lesbaren Daten offen. Nicht nachgewiesen.I:HDieselbe Primitive innerhalb derselben Autorität erlaubt eine Modifikation von In-Memory-Zuständen und aller Daten, die der Prozess schreiben kann. Nicht nachgewiesen.A:HPersistenter Absturz: Das gespeicherte DICOM lässt den Prozess bei jeder Vorschau-Anfrage durch beliebige Personen abstürzen.

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.