Alle Sicherheitshinweise

Orthanc DICOM Server

Out-of-Bounds-Lesezugriff im DicomStreamReader Meta-Header-Parser

Der DICOM-Stream-Parser von Orthanc allokiert einen Meta-Header-Block, dessen Größe aus dem Group-Length-Tag stammt, liest dann die deklarierte Wertlänge jedes Tags und kopiert entsprechend viele Bytes aus dem Block. Die Schleifenbedingung prüft, ob der 8/12-Byte-Header in den Block passt, jedoch nicht die Wertlänge — ein verkürzter Group-Length-Wert lässt den Parser über die Allokationsgrenze hinaus lesen.

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

Beschreibung

Der POST /instances-Handler von Orthanc streamt hochgeladene DICOM-Daten durch DicomStreamReader::HandleMetaHeader. Der Parser allokiert einen Heap-Block, dessen Größe aus dem Group-Length-Tag (0002,0000) stammt, und iteriert dann über die Meta-Header-Tags innerhalb dieses Blocks. Jede Iteration prüft, ob der 8-Byte- (Short-Form) bzw. 12-Byte- (Long-Form) Header des Tags in die Allokation passt, bevor die Wertlänge gelesen wird.

Der Short-Form-Pfad liest eine 16-Bit-Wertlänge und kopiert entsprechend viele Bytes aus dem Block — ohne zuvor zu prüfen, ob pos + 8 + length innerhalb von block.size() bleibt:

OrthancFramework/Sources/DicomFormat/DicomStreamReader.cpp:197-228

while (pos + 8 <= block.size()) // prüft 8 Byte verfügbar
{
DicomTag tag = ReadTag(p + pos, true);
ValueRepresentation vr = StringToValueRepresentation(
std::string(p + pos + 4, 2), true);
if (IsShortExplicitTag(vr))
{
uint16_t length = ReadUnsignedInteger16(p + pos + 6, true); // nicht vertrauenswürdige Länge
std::string value;
value.assign(p + pos + 8, length); // KEINE PRÜFUNG: pos+8+length <= block.size()
pos += length + 8;
}

View source →

Der Long-Form-Pfad nutzt eine 32-Bit-Wertlänge und weist dieselbe Lücke auf:

OrthancFramework/Sources/DicomFormat/DicomStreamReader.cpp:230-248

else if (pos + 12 <= block.size())
{
uint32_t length = ReadUnsignedInteger32(p + pos + 8, true); // nicht vertrauenswürdige 32-Bit-Länge
if (tag.GetGroup() == 0x0002)
{
std::string value;
value.assign(p + pos + 12, length); // KEINE PRÜFUNG: pos+12+length <= block.size()
}
pos += length + 12;
}

View source →

Dieselbe Parsing-Logik in DicomMap::ReadNextTag enthält die entsprechende Grenzüberprüfung:

OrthancFramework/Sources/DicomFormat/DicomMap.cpp:1096

uint16_t length = ReadLittleEndianUint16(dicom + position + 6);
if (position + 8 + length > size) // DIESE PRÜFUNG FEHLT IM DicomStreamReader
{
return false;
}
value.assign(dicom + position + 8, length);

View source →

Wird das Group-Length-Tag (0002,0000) so klein gepatcht, dass der 8-Byte-Header eines Ziel-Tags noch innerhalb des Blocks liegt, dessen Wert-Bytes aber über die Allokation hinausreichen, liest value.assign() über das Ende der Heap-Allokation hinaus. AddressSanitizer verortet den Out-of-Bounds-Zugriff in DicomStreamReader.cpp:208, unmittelbar hinter einer 157 Byte großen Allokation aus StreamBlockReader::Schedule:

AddressSanitizer-Trace

==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xffff9423cebd
READ of size 64 at 0xffff9423cebd thread T16
#0 in __interceptor_memcpy
#3 in std::__cxx11::basic_string::assign() basic_string.h:1443
#4 in Orthanc::DicomStreamReader::HandleMetaHeader() DicomStreamReader.cpp:208
#8 in Orthanc::DicomStreamReader::LookupPixelDataOffset() DicomStreamReader.cpp:740
#9 in Orthanc::ServerContext::StoreAfterTranscoding() ServerContext.cpp:683
#13 in UploadDicomFile OrthancRestApi.cpp:246
0xffff9423cebd is located 0 bytes to the right of 157-byte region [0xffff9423ce20,0xffff9423cebd)
allocated by thread T16 here:
#4 in Orthanc::StreamBlockReader::Schedule() DicomStreamReader.cpp:49

Zwei strukturelle Faktoren begrenzen die praktische Auswirkung. Erstens validiert DCMTK die DICOM-Datei vor, bevor DicomStreamReader läuft; auf große Werte (z. B. 0xFFFF) aufgeblähte Tag-Wertlängen führen zur sofortigen Ablehnung der Datei und beschränken den Out-of-Bounds-Lesezugriff auf etwa die ursprüngliche Tag-Wertlänge (~64 Bytes). Zweitens werden die Wert-Bytes in einen temporären std::string geschrieben, den VisitMetaHeaderTag() lediglich auf die Transfer Syntax UID prüft — bei jedem anderen Tag wird der String beim Stack-Unwind zerstört, ohne dass im untersuchten Pfad ein Exfiltrationskanal existiert.

Das C-STORE-Netzwerkprotokoll überträgt keine Datei-Meta-Header (Orthanc erzeugt für per C-STORE empfangene Instanzen einen eigenen, korrekten Meta-Header), sodass dieser Angriffsvektor ausschließlich über HTTP erreichbar ist.

Auswirkung

  • Out-of-Bounds-Heap-Lesezugriff von etwa 64 Bytes während eines DICOM-Datei-Uploads über POST /instances.
  • Im untersuchten Pfad existiert kein Exfiltrationskanal: Der Wert des betroffenen Tags wird von VisitMetaHeaderTag() ausschließlich auf die Transfer Syntax UID geprüft und anschließend verworfen. Eine Offenlegung von Informationen ist theoretischer Natur.
  • Der 64-Byte-Lesezugriff bleibt auf Standard-Builds innerhalb erreichbarer Heap-Seiten; weder Absturz noch Denial-of-Service treten auf.

Abhilfe

Aktualisieren Sie Orthanc auf Version 1.12.11 oder höher. Der Patch fügt die fehlenden Prüfungen pos + 8 + length <= block.size() und pos + 12 + length <= block.size() vor den value.assign()-Aufrufen ein und gleicht damit die bestehende Logik in DicomMap::ReadNextTag an.

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.

    Beschränken Sie POST /instances an Ihrem Reverse-Proxy auf die IP-Bereiche der Bildgebungsmodalitäten und Integrationsdienste, die Studien legitim hochladen.

  • Zugangsdaten überprüfen.

    Auch wenn der publizierte CVSS-Vektor PR:N verwendet, erfordern Deployments mit HTTP-Authentifizierung auf /instances einen authentisierten Benutzer. Prüfen Sie RegisteredUsers in orthanc.json und ein externes Authentifizierungsbackend auf veraltete oder überprivilegierte Konten.

  • Upload-Logs auf manipulierte DICOM prüfen.

    Suchen Sie nach POST /instances-Aufrufen mit ungewöhnlichen Antworten und nach Parser-Fehlerlogs, die das Meta-Header-Parsing referenzieren.

  • ASAN-instrumentierten Test-Build planen.

    In hochkritischen Umgebungen empfiehlt sich, den gepatchten Build mit modalitätsherstellerspezifischen DICOM-Beispielen gegen eine AddressSanitizer-instrumentierte Orthanc-Instanz zu validieren, um Regressionen und verbleibende Out-of-Bounds-Lesezugriffe in benachbarten Meta-Header-Pfaden auszuschließen.

Bewertung im Detail

AV:NÜber das Netzwerk per HTTP-REST-API von Orthanc auf POST /instances erreichbar.AC:LEine einzelne manipulierte DICOM-Datei mit verkürztem Meta-Header. Keine Timing- oder Umgebungsvorbedingungen.PR:NDer publizierte Vektor spiegelt Deployments wider, in denen POST /instances ohne HTTP-Authentifizierung exponiert ist, was Orthanc per Konfiguration erlaubt.UI:NKeine Interaktion durch eine zweite Person erforderlich.S:UNur der Orthanc-Prozess ist betroffen; über diese Primitive sind keine prozessübergreifenden Ressourcen erreichbar.C:NIm untersuchten Aufrufpfad werden die ausgelesenen Bytes ausschließlich für die Transfer-Syntax-UID-Prüfung verwendet und anschließend verworfen; ein Exfiltrationskanal existiert nicht.I:NReine Lese-Primitive in einen verworfenen Puffer; 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.

Auf Standard-Builds von 1.12.10 mit Default-glibc bleibt der 64-Byte-Lesezugriff typischerweise innerhalb erreichbarer Heap-Seiten und führt nicht zum Absturz; das publizierte A:H spiegelt den Worst Case auf gehärteten oder restriktiven Heap-Deployments wider.

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.