Ce projet est une plateforme de Capture The Flag basée sur CTFd, avec instanciation dynamique des challenges via CTFd-Whale et un reverse-proxy FRP pour exposer chaque instance de challenge.
Note : Un compte utilisateur a été pré-configuré sur la plateforme pour faciliter votre évaluation.
Pour accéder à la plateforme déjà déployée sur notre VPS, vous devez utiliser le tunnel VPN Wireguard fourni.
- URL de la plateforme CTF :
http://10.66.66.1:8000/ - Identifiants de test :
- Mail :
lchiron3@myges.fr - Mot de passe :
motdepasse
- Mail :
- Téléchargez le fichier de configuration fourni.
- Activez l'interface :
sudo apt install wireguard-tools sudo wg-quick up /chemin/vers/votre/config.conf
- Téléchargez et installez le client officiel Wireguard.
- Importez le fichier de configuration et cliquez sur "Activer".
| Composant | Rôle |
|---|---|
docker-compose.yml |
Stack principale : CTFd, MariaDB, Redis, proxy Docker filtré (Tecnativa), FRP (frps/frpc) |
docker-compose.lan.yml |
Override pour exposer CTFd sur toutes les interfaces (déploiement LAN local) |
docker-compose.monitoring.yml |
Stack d'observabilité (Prometheus, Grafana, exporters) |
ctfd-whale-plugin/ |
Plugin CTFd-Whale (vendored), instancie chaque challenge comme service Swarm mono-nœud sur le réseau overlay ctfd_containers |
challenges/ |
Sources des challenges à instances dynamiques (voir plus bas) |
scripts/ |
Bring-up résilient, sauvegarde/restauration, service systemd, durcissement OS |
CTFd tourne sans le socket Docker monté directement : seul le conteneur dockerproxy (proxy Docker filtré) y a accès, en lecture seule, et n'expose qu'un sous-ensemble d'API (ping/version/info/networks/services), suffisant pour Whale.
- Docker et Docker Compose installés.
- Make installé (
sudo apt install make).
-
Clonage du dépôt :
Note : Le dépôt étant privé, veuillez nous fournir votre adresse mail pour obtenir l'accès.
git clone https://github.com/xAMA0x/Plateforme-CTF.git cd Plateforme-CTF -
Configuration de l'environnement :
cp .env.example .env
Contenu du
.envà remplir :CTFD_SECRET_KEY=change_me CTFD_DB_NAME=ctfd CTFD_DB_USER=ctfd CTFD_DB_PASSWORD=change_me CTFD_DB_ROOT_PASSWORD=change_me FRP_TOKEN=change_me REDIS_PASSWORD=change_me
Pour générer des valeurs sécurisées aléatoirement :
echo "CTFD_SECRET_KEY=$(openssl rand -hex 32)" echo "CTFD_DB_PASSWORD=$(openssl rand -hex 16)" echo "CTFD_DB_ROOT_PASSWORD=$(openssl rand -hex 16)" echo "FRP_TOKEN=$(openssl rand -hex 24)" echo "REDIS_PASSWORD=$(openssl rand -hex 16)"
Remplacez ensuite les
change_medans votre.envpar les valeurs générées. -
Lancement de l'infrastructure :
sudo make up
(
make upappellescripts/start.sh, qui crée l'overlay Swarm des challenges si besoin et fiabilise le démarrage defrpc.) -
Accès local :
Une fois le déploiement terminé, la plateforme est accessible à l'adresse suivante :
http://127.0.0.1:8000
| Commande | Effet |
|---|---|
make up / make down / make restart |
Démarrer / arrêter / redémarrer la stack |
make logs / make ps / make config |
Logs, état des conteneurs, config résolue |
make lan-up / make lan-down |
Déploiement avec CTFd exposé sur toutes les interfaces (override docker-compose.lan.yml) |
make backup |
Sauvegarde le dump SQL et les uploads dans backups/ |
make restore SQL=<fichier.sql> UPLOADS=<archive.tar.gz> |
Restaure une sauvegarde (écrase la base et les uploads courants, confirmation demandée) |
Ces challenges sont packagés en image Docker et instanciés dynamiquement par CTFd-Whale (un conteneur par joueur, flag unique injecté via la variable d'environnement FLAG) :
| Dossier | Catégorie | Vulnérabilité |
|---|---|---|
challenges/sqli-basic |
SQLi | Injection SQL basique dans un formulaire de connexion |
challenges/sqli-blind-waf |
SQLi | Injection SQL avec contournement de WAF |
challenges/sqli-union |
SQLi | Injection SQL par UNION SELECT |
challenges/web-easy-cookie |
Web | Contrôle d'accès basé sur un cookie modifiable |
challenges/web-medium-sqli |
Web | Injection SQL dans une authentification PHP/SQLite |
challenges/web-hard-nullbyte |
Web | Path traversal + poison null byte |
challenges/RE (keygen.py) |
Reverse Engineering | Génération de serial (script de référence) |
D'autres catégories existent sur la plateforme CTFd déployée (Code Review, Osint, un second challenge Reverse Engineering) mais ne sont pas des instances Docker : ce sont des challenges "fichier à télécharger", gérés directement via l'interface d'administration CTFd et stockés dans data/ctfd/uploads/ (hors dépôt git, comme toute donnée d'exécution). Ce n'est pas un oubli — seuls les challenges à instances dynamiques ont besoin d'être versionnés ici.
Stack d'observabilité optionnelle : Prometheus, Grafana, node-exporter, cAdvisor, mysqld-exporter, redis-exporter, blackbox-exporter (probe HTTP sur CTFd).
cp .env.monitoring.example .env.monitoring
docker compose -f docker-compose.monitoring.yml --env-file .env.monitoring up -dREDIS_PASSWORD doit avoir la même valeur dans .env et .env.monitoring (redis-exporter a besoin de s'authentifier sur la même instance Redis que CTFd).
Grafana et Prometheus sont bindés sur 127.0.0.1 uniquement (pas d'exposition publique) ; depuis un poste distant, y accéder via un tunnel SSH :
ssh -L 3000:localhost:3000 <user>@<serveur>Détails complets (dashboards, exporters, dépannage) dans docs/MONITORING.md (non versionné, fourni en local).
scripts/harden-debian13.sh : installation de Docker Engine si absent (dépôt officiel + docker-compose-plugin, ajout de l'utilisateur au groupe docker), SSH par clé uniquement, pare-feu ufw (default-deny), fail2ban.
Ce script est livré prêt à l'emploi mais non exécuté automatiquement. Avant de le lancer :
- Renseignez votre clé publique SSH dans la variable
SSH_PUBLIC_KEYen tête de script. - Relisez-le (il désactive l'authentification par mot de passe SSH).
- Exécutez-le avec
sudo— il vous demandera de confirmer, depuis un second terminal, qu'une connexion par clé fonctionne avant de couper le mot de passe.
Sur une machine Debian 13 fraîche, scripts/deploy-all.sh enchaîne les trois étapes dans l'ordre (durcissement → plateforme → challenges) :
sudo ./scripts/deploy-all.shscripts/harden-debian13.sh(nécessiteSSH_PUBLIC_KEYrenseigné au préalable, voir ci-dessus)scripts/start.sh(bring-up de la stack CTFd + Whale + FRP)- Build des 6 images des challenges à instances dynamiques, avec les tags exacts attendus par la configuration CTFd
scripts/verify-install.sh vérifie ensuite, dans le même ordre, que tout est effectivement en place (SSH/ufw/fail2ban, conteneurs de la plateforme + CTFd joignable, images des challenges présentes) :
sudo ./scripts/verify-install.shmake backup # crée backups/ctfd-<date>.sql et backups/uploads-<date>.tar.gz
make restore SQL=backups/ctfd-....sql UPLOADS=backups/uploads-....tar.gzmake restore écrase la base et les uploads courants ; une confirmation est demandée avant toute action.
Pour une exécution planifiée, un service systemd est fourni (scripts/ctfd-stack.service) afin que la stack redémarre proprement après un reboot de l'hôte.
Le pipeline GitHub Actions (.github/workflows/ci.yml) valide, à chaque push/PR sur main : la présence des fichiers requis, la config Docker Compose (stack principale, override LAN, override monitoring), les permissions d'exécution et le lint (shellcheck) des scripts.
L'objectif est de proposer une solution "clé en main" permettant de répliquer des environnements de compétition cyber en quelques minutes, garantissant une portabilité totale entre différents hébergeurs ou infrastructures locales.