This page addresses a reported vulnerability in the preamble defined by the DICOM file format. The vulnerability could allow DICOM files stored on media to have executable malware inserted.

Background

DICOM files on media include a 128-byte preamble at the start of the file. The 4 bytes following the preamble contain the characters “DICM” to indicate the body of the file contains DICOM information.

The intended purpose of the preamble is to allow both DICOM software and non-DICOM software to process the same file in different ways:

  • A DICOM viewer will ignore the preamble, observe the DICM string, process the DICOM content, and display the DICOM images.
  • A TIFF viewer could use offset information in the preamble to access and display the image pixel data in the file while ignoring the rest of the DICOM content.

Risk assessment

DicomObjects based applications will not be affected by this vulnerability.

Workstation/Reading applications

When reading a DICOM instance from file on disk, from stream or from a byte array, DicomObjects ignores the preamble, as should any DICOM software do. And when writing the DICOM instance back out, DicomObjects creates an empty 128 bytes for the preamble. This read-write operation can be an effective way to clean up any infected DICOM instances.

Router and Server applications

The vulnerability does not exist when images are transmitted via standard DICOM C-STORE/C-GET/C-MOVE as DICOM network transmissions do not include this preamble. If images imported from media contain a preamble, it is stripped off before being sent.

STOW-RS and WADO-RS applications

DICOM instances received via STOW-RS request or WADO-RS response may contain the preamble and therefore instance receiver must take care of the preamble. As soon as the received instance is written out by DicomObjects, the preamble gets reset and any potential risk is removed.


Detection and mitigation

To help our users (and more importantly their users) detect infected DICOM instances, we have updated the API to check for a predefined list which is modifiable to support user defined file signatures as shown below:

.NET

//  Set Up
/*
* Enable detection of any suspicious non-Zero preamble, disabled by default
* A warning message will be logged (DicomObjects log must be enabled) if any file signature is matched
*/
DicomGlobal.FailOnSuspiciousPreamble = true;

//  Add user defined file signature to the pre-defined list to search
DicomGlobal.PreambleFileSignatures.Add(new FileSignature(0x44, 0x55, 0x66));

/*  Read in
*/

COM

'   Enable detection of any suspicious non-Zero preamble, disabled by default
'   A warning message will be logged (DicomObjects log must be enabled) if any file signature is matched
Dim dg As New DicomGlobal
dg.FailOnSuspiciousPreamble = True

'   Add user defined magic number and file signature to the pre-defined list to search
Dim byteFormat(4) As Byte
byteFormat(0) = &HDE
byteFormat(1) = &HAD
byteFormat(2) = &HBE
byteFormat(3) = &HEF

Dim fs As New FileSignature
fs.MagicNumber = byteFormat

'   Add user defined file signature to the pre-defined list to search
dg.AddFileSignature fs

'   Read in
'   To remove from list
Dim result As Boolean
result = dg.RemoveFileSignature(fs)

DicomGlobal.PreambleFileSignatures

A pre-defined list of file signatures that DicomObjects will check against the preamble.

File Signature list:

MZ
ZM
ELF
PE
Hunk
Zip
Rar
Bz2
JavaClass
MachO_32
MachO_64
MachOReverse_32
MachOReverse_64
Tar
Zip_7z
Xar
Xz
MSCabinet
Deb
Lua
Zst

DicomGlobal.FailOnSuspiciousPreamble

If set to true, and DicomObjects spots bytes that match any of the file signatures listed in DicomGlobal.PreambleFileSignatures property, an exception “Potentially malicious preamble found” will be thrown when trying to read such DICOM instance to alert the user.

As mentioned above, the easiest way to reset the preamble with the help of DicomObjects is read the instance in and write it back out (overwrite the original file on disk if you want):

.NET

DicomGlobal.CloseFilesAfterReading = true;
DicomDataSet ds = new DicomDataSet(filePath);
ds.Write(filePath, ds.OriginalTS);

COM

dg.RegWord("DisableMemoryMapping") = 1
Set im = ims.ReadFile(filePath)
im.WriteFile filePath, True, im.ReceivedSyntax