Orthanc DICOM Server
Out-of-Bounds-Lesezugriff im DICOM-Bilddecoder (DecodeLookupTable)
Der PALETTE-COLOR-Bilddecoder von Orthanc validiert, dass die LUT-Arrays zur deklarierten Palettengröße passen, prüft aber nicht, dass die als LUT-Indizes verwendeten Pixelwerte innerhalb dieses Bereichs bleiben. Werte außerhalb des Bereichs lesen über die LUT hinaus in angrenzenden Heap-Speicher; die ausgelesenen Bytes werden zu RGB-Werten im Vorschaubild und an den Aufrufer zurückgegeben.
Beschreibung
DICOM-PALETTE-COLOR-Bilder enthalten kanalspezifische Color-Lookup-Tables (Rot, Grün, Blau) und Pixeldaten, deren Werte als Indizes in diese LUTs dienen. Orthancs DecodeLookupTable dekodiert diese Bilder, indem es jedes Pixel durchläuft und drei LUT-Einträge (einen pro Kanal) in das Ausgabe-RGB-Bild liest. Das Framework prüft, dass die LUT-Arrays selbst zur deklarierten paletteSize passen, prüft jedoch nie, ob ein einzelner Pixelwert innerhalb von [0, paletteSize) liegt.
OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp:491-502
for (unsigned int y = 0; y < height; y++){ uint8_t* p = reinterpret_cast<uint8_t*>(target->GetRow(y));
for (unsigned int x = 0; x < width; x++) { // OOB-Lesezugriff falls *source >= paletteSize p[0] = lutRed[*source] >> offsetBits; p[1] = lutGreen[*source] >> offsetBits; p[2] = lutBlue[*source] >> offsetBits; source++; p += 3; }}Bei einer 16-Eintrag-LUT und Pixelwert 200 landet der Lesezugriff 368 Bytes hinter dem LUT-Puffer (jeder LUT-Eintrag ist uint16_t). Die drei OOB-Lesezugriffe pro Pixel zielen auf separate LUT-Allokationen (Rot, Grün, Blau) und liefern jeweils eine eigenständige Heap-Lese-Primitive. Die ausgelesenen Bytes werden in das RGB-Pixeltripel geschrieben und über den Preview-Endpunkt zurückgegeben.
Nur der PixelFormat_RGB24-Pfad ist betroffen. Der PixelFormat_RGB48-Pfad fixiert paletteSize auf 65536 und nutzt uint16_t-Source-Werte, sodass der maximale Index 65535 exakt in die LUT passt.
Im Test wurde ein 8x8-PALETTE-COLOR-DICOM mit paletteSize=16 und Pixelwerten 16-79 verwendet. Die Vorschau lieferte ein 8x8-RGB-Bild zurück, in dem über 50 von 64 Pixeln Werte ungleich Null trugen — ausgelesene Heap-Daten:
Auszug aus der Vorschau (Rot-Kanal, OOB-Lesezugriff aus der lutRed-Heap-Region)
0000: 30 00 00 00 45 00 00 00 30 f9 0f 00 1e 99 bb f3 0...E...0.......0010: 31 34 31 31 37 03 ff 00 08 18 66 62 70 03 ff 00 14117.....fbp...0020: 40 00 00 00 45 00 00 00 20 00 00 00 63 5f 74 69 @...E... ...c_ti0030: 67 00 54 00 21 00 00 00 90 00 ff 00 90 00 ff 00 g.T.!...........Im Hex-Dump erscheinen klare ASCII-Strings — 14117, fbp, c_tig — die internen Orthanc-Identifiern und DICOM-Tag-Daten in benachbarten Heap-Chunks entsprechen. Über 21 aufeinanderfolgende Läufe gegen ein Standard-1.12.10-Docker-Image lieferte jeder Lauf 41 bis 53 von 64 Pixeln mit Inhalt zurück, mit zwischen den Läufen variierendem Inhalt entsprechend der wechselnden Heap-Layouts. Repräsentative Lecks umfassten DICOM-UID-Fragmente (038485967947477029570663), interne Klassen-/Methodennamen (PrnPtet, PrnSre, RmtAT), DICOM-Tag-Fragmente (mdl-ain, nsif) und wiederkehrende glibc-Chunk-Header-Pointer-Muster.
AddressSanitizer verortet den ersten Out-of-Bounds-Zugriff in DicomImageDecoder.cpp:497, unmittelbar hinter einer 32-Byte-LUT-Region, die durch DcmElement::newValueField() allokiert wurde:
AddressSanitizer-Trace
==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xffff95c34bf0READ of size 2 at 0xffff95c34bf0 thread T17 #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
0xffff95c34bf0 is located 0 bytes to the right of 32-byte region [0xffff95c34bd0,0xffff95c34bf0)allocated by thread T17 here: #0 in operator new[] #1 in DcmElement::newValueField() dcelem.cc:788Die Schwachstelle ist über zwei unterschiedliche Pfade erreichbar. Erstens als authentisierter HTTP-Upload: POST /instances gefolgt von GET /instances/{id}/preview. Zweitens als gespeicherter Angriff über DICOM C-STORE auf Port 4242. Die Default-Konfiguration von Orthanc (DicomAlwaysAllowStore: true) akzeptiert C-STORE-Requests ohne Authentifizierung, sodass ein Angreifer im Netzwerk ein manipuliertes PALETTE-COLOR-DICOM unauthentifiziert ablegen kann. Jede nachfolgende Vorschau-Anfrage einer authentisierten Person — einschließlich des Angreifers selbst mit reinen Read-Access-Credentials — löst den Out-of-Bounds-Lesezugriff aus und gibt die ausgelesenen Heap-Daten im gerenderten Bild zurück.
Auswirkung
- Offenlegung von Informationen aus beliebigem Heap-Speicher (interne Orthanc-Identifier, DICOM-Tag-Daten, glibc-Chunk-Metadaten) über gerenderte Vorschaubilder.
- Drei eigenständige Heap-Lese-Primitiven pro Pixel (eine pro LUT). Durch Variation der Pixelwerte über manipulierte Dateien hinweg lassen sich unterschiedliche Heap-Offsets abtasten und ein mehrere Bytes umfassender Heap-Dump zusammensetzen.
- In Orthancs Default-Konfiguration (
DicomAlwaysAllowStore: true) ist das Ablegen unauthentifiziert; das Auslösen des Lecks erfordert Read-Level-Authentifizierung. - Erreicht der Out-of-Bounds-Lesezugriff eine nicht gemappte Speicherseite, terminiert der Orthanc-Prozess unerwartet. Auf Standard-Builds mit normalem Heap-Layout ist dies selten.
Abhilfe
Aktualisieren Sie Orthanc auf Version 1.12.11 oder höher. Der Patch fügt eine pixelweise Grenzüberprüfung (*source >= paletteSize → throw) innerhalb der Decode-Schleife ein. Als sofortige Defense-in-Depth-Maßnahme setzen Sie DicomAlwaysAllowStore: false in orthanc.json und konfigurieren eine explizite 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: falseinorthanc.jsonund definieren Sie eine expliziteDicomModalities-Allowlist legitimer AETs. Andernfalls kann jeder Host, der Port 4242 erreicht, das manipulierte DICOM unauthentifiziert ablegen.Vorschau-Endpunkt einschränken.
Wenn Ihr Deployment keine Web-Vorschau benötigt, beschränken Sie
GET /instances/*/previewan Ihrem Reverse-Proxy. Der Out-of-Bounds-Lesezugriff wird erst beobachtbar, wenn das manipulierte Bild gerendert wird.Read-Access-Konten prüfen.
Ein Angreifer benötigt nur Read-Level-Credentials, um die ausgelesenen Heap-Daten zu sehen. Prüfen Sie
RegisteredUsersinorthanc.jsonund ein externes Authentifizierungsbackend auf veraltete oder niedrig privilegierte Konten, die keinen Lesezugriff auf beliebige Studien haben sollten.Auf Abstürze nach Vorschau-Anfragen achten.
Auf Builds mit striktem Heap-Layout kann der Out-of-Bounds-Lesezugriff gelegentlich eine nicht gemappte Seite treffen. Alarmieren Sie auf Orthanc-Prozessneustarts unmittelbar nach
GET /instances/*/preview-Logeinträgen.DICOM-Speicher auf auffällige PALETTE-COLOR-Studien prüfen.
Durchsuchen Sie den Speicher nach Studien mit
PhotometricInterpretation = PALETTE COLORund kleiner Palettengröße (z. B.paletteSize ≤ 16), deren Pixeldaten Werte größer als der Palettenbereich enthalten. Solche bereits vor dem Patch abgelegten Studien wurden möglicherweise bereits zur Speicheroffenlegung genutzt.
Bewertung im Detail
POST /instances + /preview) sowie per DICOM C-STORE auf Port 4242 erreichbar.AC:LDeterministisches Leck. Im Test trugen 41-53 von 64 Pixeln in jedem von 21 aufeinanderfolgenden Läufen gegen einen Standard-Build Heap-Inhalte.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. Beide Schranken sind konfigurierbar; siehe die Checkliste für Betreiber unten.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:HOffenlegung von Heap-Inhalten über mehrere voneinander unabhängige Lesezugriffe pro Pixel. Nachgewiesene Lecks umfassen Orthanc-interne IDs, DICOM-UID-Fragmente und benachbarte Tag-Daten.I:NReine Lese-Primitive; nichts wird modifiziert.A:HAuf Builds mit striktem Heap-Layout kann der Out-of-Bounds-Lesezugriff eine nicht gemappte Speicherseite treffen und den Orthanc-Prozess terminieren.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.
