diff --git a/zone_ctf/env_systeme.md b/zone_ctf/env_systeme.md new file mode 100644 index 0000000..225513d --- /dev/null +++ b/zone_ctf/env_systeme.md @@ -0,0 +1,252 @@ +# Environnement Système CTF + +Il faut impérativement une VM pour que Docker soit fluide + +## Installation de Docker et Docker-Compose +``` +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 actuel est expliqué à la fin. + +### Procédure pour la création d'un nouveau challenge + +Placer les Dockerfile est 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 container 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 " + else + if [ -f "$2" ];then + docker build -t $1 $2 + else + echo "Usage : ./createImg " + exit 0 + fi +fi +``` + +### Script pour la création d'un utilisateurs et son ajout à DockerTemp + +Usage ./deployEnv + +``` +#!/bin/bash +if [ "$#" -eq "0" ] + then + echo "Usage : ./deployEnv " + 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 executés avec succès tout est prêt. Pour personnaliser le message d'acceuil il faut modifié le /etc/motd de la VM et non celui des containers Docker. + +## Restauration des challenges déjà existant +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 déployer l'environnement actuel + +``` +#!/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 +``` +