6.7 KiB
6.7 KiB
Environnement Système CTF
Il faut impérativement une VM pour que Docker soit fluide
Installation de Docker
apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
apt-get update
apt-get install docker-ce
Mise en place de l'environement système
La restauration des challenges actuels est expliquée à la fin.
Procédure pour la création d'un nouveau challenge
Placer les Dockerfile est la source du challenge dans /home/systeme/SystemeChall/ Le Dockerfile doit idéalement être fait à partir de debmod, créer un utilisateur systemeXX et contenir
USER systemeXX
WORKDIR /home/systemeXX
Installation et création de l'utilisateur administrateur non root
apt-get install python3-pip
pip3 install --upgrade docker
pip3 install --upgrade argcomplete
adduser systeme
adduser systeme sudo
adduser systeme docker
su systeme
/usr/local/bin/dockersh
#!/usr/bin/env python3
# PYTHON_ARGCOMPLETE_OK
import os
os.environ['TERM'] = 'xterm'
import argparse
from configparser import ConfigParser, ExtendedInterpolation
import docker
import random
import string
import sys
from pwd import getpwnam
prog = 'dockersh'
config_file = "/etc/dockertempsh.ini"
import os
user = os.getlogin()
host = os.uname()[1]
cli = docker.APIClient()
def containers(image_filter='', container_filter='', sort_by='Created', all=True):
cs = cli.containers(all=all, filters={'label': "user="+user})
cs.sort(key=lambda c: c[sort_by])
cs = [c for c in cs if str(c['Image']+':latest').startswith(image_filter)]
cs = [c for c in cs if c['Names'][0][1:].startswith(container_filter)]
return cs
def random_string(length):
def random_char():
return random.choice(string.ascii_uppercase + string.digits)
return ''.join(random_char() for _ in range(length))
def strip(s, suffix=''):
for c in ['/', ':', '.', ' ']:
s = s.replace(c, '')
if s.endswith(suffix):
s = s[:len(s)-len(suffix)]
return s
def image_split(s):
sp = s.split(':')
if len(sp) == 1:
return sp[0], 'latest'
else:
return sp[0], sp[1]
#Chargement du fichier de configuration
config_envir = {
"USER": user,
"HOME": os.environ['HOME']
}
cfg = ConfigParser(config_envir, interpolation=ExtendedInterpolation())
cfg.read(config_file)
ini = cfg[user] if cfg.has_section(user) else cfg['DEFAULT']
#Spécification particulière
post_cmd = ""
name = ""
image = ""
home = ini['homedir']
suffix = ini['suffix']
#Vérification des spécifications
name_passed = (name != "")
image_passed = (image != "")
#Génération du conteneur temporaire
#Création du nom random
if not image_passed:
image = ini['image']
image_base, image_tag = image_split(image)
image = image_base + ':' + image_tag
name = strip(image) + '_tmp' + random_string(4)
full_name = name + suffix
#Création
if len(containers(container_filter=name)) == 0:
volumes = []
if "volumes" in ini:
volumes = volumes + ini["volumes"].split(",")
volumes = [v.split(":") for v in volumes]
binds = {v[0].strip():{"bind":v[1].strip(),"mode":v[2].strip()} for v in volumes}
volumes = [v[1] for v in volumes]
host_config = cli.create_host_config(
binds=binds,
restart_policy={'Name' : 'unless-stopped'},
cap_add='SYS_PTRACE', #GDB
security_opt=['seccomp:unconfined']) #GDB
userpwd = getpwnam(user)
cli.create_container(image,
stdin_open=True,
tty=True,
name=full_name,
hostname='systemekrkn',
labels={'group': prog, 'user': user},
volumes=volumes,
working_dir=home,
environment={
"HOST_USER_ID": userpwd.pw_uid,
"HOST_USER_GID": userpwd.pw_gid,
"HOST_USER_NAME": user
},
host_config=host_config
)
#Lancement et attach
cli.start(full_name)
os.popen('docker exec '+full_name + ' echo Initialization finished.').read().split(":")[-1]
user_bash = "/bin/bash" #Path par défaut
cmd = post_cmd if post_cmd else user_bash #Donne la posibilité de spécifié le path dans le .ini
os.system('docker exec -u '+user+" " + "-it" +' '+ full_name + ' ' + cmd)
#Arrêt à la fin
cli.remove_container(full_name, v=True, force=True)
cli.close()
chmod +x /usr/local/bin/dockersh
Création d'une image docker de base
Dockerfile
FROM debian:latest
RUN dpkg --add-architecture i386
RUN apt update && apt install -y gdb elfutils binutils python-minimal perl zip pwgen nano gcc
Création de l'image de base debmod
docker built -t debmod .
Script pour la création des images Docker à partir des Dockerfile
Usage : ./createImg
#!/bin/bash
if [ "$#" -lt "2" ]
then
echo "Usage : ./createImg <systemeXX> <dockerfile>"
else
if [ -f "$2" ];then
docker build -t $1 $2
else
echo "Usage : ./createImg <systemeXX> <dockerfile>"
exit 0
fi
fi
Script pour la création d'un utilisateur et son ajout à DockerTemp
Usage ./deployEnv
#!/bin/bash
if [ "$#" -eq "0" ]
then
echo "Usage : ./deployEnv <systemeXX>"
else
if grep -q "$1" /etc/dockertempsh.ini
then
echo "Utilisateur déjà crée dans /etc/dockertempsh.ini ECHEC"
exit 1
else
useradd -m -p $1 -s /usr/local/bin/dockersh $1
echo "$1:$1" | chpasswd
adduser $1 docker
echo -e "[$1]
image = $1
suffix = _$1
homedir = /home/$1
volumes = /globalinfo:/globalinfo:ro" >> /etc/dockertempsh.ini
fi
fi
Une fois le programme mis au bon endroit et les deux scripts exécutés avec succès tout est prêt. Pour personnaliser le message d'accueil, il faut modifier le /etc/motd de la VM et non celui des conteneurs Docker.
Restauration des challenges déjà existants
Voilà la correspondance utilisateur / challenge
systeme1 -> easyshell
systeme2 -> pwn_my_home
systeme3 -> overflow
systeme4 -> shellcode1
systeme5 -> shellcode3
systeme6 -> shellcode3
systeme7 -> history
Extraire l'archive des challenge dans /home/systeme/SystemeChall/
Script qui utilisera les deux autres pour tout déployer
#!/bin/bash
declare -a path=(easyshell pwn_my_home overflow shellcode1 shellcode2 shellcode3 history)
for i in `seq 0 6`;
do
./createImg.sh systeme$(($i+1)) "/home/systeme/SystemeChall/${path[${i}]}"
./deployEnv.sh systeme$(($i+1))
done