diff --git a/README.md b/README.md index 1bf0c36..a46acb9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,42 @@ Plateforme CTF open-source pour étudiants et professionnels cybersécurité. Challenges progressifs Blue/Red Team, conteneurisés et isolés par équipe. +> **Projet Annuel — ESGI** · Mastère Sécurité Informatique · 4ᵉ année (M1) · 2025-2026 +> Équipe de 4 étudiants. Ce dépôt est la **face technique** (jury/mainteneurs) ; le dépôt +> [**RootMeUp-CTF**](https://github.com/Jacob-dot-bit/RootMeUp-CTF) est destiné aux **joueurs** +> (guides uniquement, sans solutions ni flags). + +## Sommaire +- [Contexte](#contexte) +- [Objectif](#objectif) +- [Architecture](#architecture) +- [Prérequis](#prérequis) +- [Accès à la plateforme](#accès-à-la-plateforme) +- [Lancement d'un challenge](#lancement-dun-challenge) +- [Challenges disponibles](#challenges-disponibles) +- [Ajout d'un challenge sur le serveur](#ajout-dun-challenge-sur-le-serveur) +- [Sécurité](#sécurité) +- [Durcissement du serveur](#durcissement-du-serveur) +- [Supervision](#supervision) +- [Équipe projet](#équipe-projet) +- [Liens utiles](#liens-utiles) +- [Licence](#licence) + +## Contexte + +RootMeUp est une plateforme de *Capture The Flag* pédagogique développée dans le cadre +du Projet Annuel ESGI. Objectif : offrir un environnement d'entraînement cybersécurité +**Blue Team / Red Team**, gratuit et francophone, où chaque équipe dispose d'instances +de challenges **isolées**. + +Le projet a connu deux phases : +- **T2** — première version hébergée sur une VM mutualisée de l'école. Ressources + insuffisantes : le disque se remplissait et faisait **crasher CTFd**. +- **T3** — migration vers un **Proxmox dédié** (VM Debian durcie CIS), déploiement des + challenges conteneurisés, puis mise en place d'une **supervision** (Grafana + Prometheus, + alertes Discord) pour *anticiper* les incidents comme la saturation disque plutôt que + de les subir. + ## Objectif - Challenges pratiques isolés par équipe (3 participants) - Visualisation des scores et saisie des flags via l'interface CTFd @@ -30,7 +66,7 @@ flowchart LR ``` Le serveur est une VM Debian durcie selon le benchmark CIS, qui héberge : -- **CTFd** : géré comme un service systemd, accessible sur le port 8000 +- **CTFd** : service systemd (gunicorn en local sur `127.0.0.1:8000`), exposé aux joueurs par **Apache** (reverse-proxy sur le port `80`) - **Docker** : utilisé pour construire et stocker les images des challenges - **containerd** : runtime de conteneurs qui exécute effectivement les instances de challenges ; sert de lien entre CTFd et les conteneurs lancés - **CTFdDockerContainersPlugin** : plugin CTFd qui déclenche via containerd la création d'une instance par équipe lors du lancement d'un challenge @@ -55,14 +91,19 @@ L'accès à la plateforme se fait via **Tailscale** (réseau privé virtuel), ce 1. Installer Tailscale sur votre poste et se connecter 2. Rejoindre le réseau via le lien d'invitation fourni 3. Récupérer l'IP Tailscale de la VM sur https://login.tailscale.com/admin/machines -4. Accéder à CTFd dans le navigateur : +4. Accéder à CTFd dans le navigateur (Apache écoute sur le port `80`) : ``` -http://:8000 +http:/// ``` 5. Créer un compte, rejoindre ou créer une équipe (3 participants max) +![Interface CTFd — liste des challenges](docs/img/ctfd-challenges.png) + +> ℹ️ **Vous êtes joueur ?** Les guides pas-à-pas (sans solutions) sont dans le dépôt +> dédié [**RootMeUp-CTF**](https://github.com/Jacob-dot-bit/RootMeUp-CTF). + ## Lancement d'un challenge 1. Ouvrir la liste des challenges dans CTFd @@ -71,6 +112,8 @@ http://:8000 4. Se connecter à l'instance via l'URL/port indiqués 5. Soumettre le flag dans l'interface CTFd +![Instance de challenge lancée dans CTFd](docs/img/ctfd-instance.png) + ## Challenges disponibles Numérotation par équipe (`N-Blue-Team-*` / `N-Red-Team-*`). @@ -107,6 +150,22 @@ docker images | grep mon-challenge Puis créer le challenge dans CTFd (`Admin Panel > Challenges > Create Challenge > Type: container`) en renseignant l'image, le port et la commande de démarrage. +## Sécurité + +Bonnes pratiques appliquées au dépôt et à la plateforme : + +- **Aucun secret dans le dépôt** — bien que public (pour le jury), les **vrais flags n'y + figurent pas** : ils sont lus au build depuis un fichier `setup/challenge.env` **gitignoré** + et **rotés** par rapport à toute valeur ayant pu être exposée (voir + [`docs/DEPLOIEMENT.md`](docs/DEPLOIEMENT.md)). +- **Séparation des publics** — les solutions/exploits restent dans ce dépôt technique ; les + joueurs n'ont accès qu'au dépôt [RootMeUp-CTF](https://github.com/Jacob-dot-bit/RootMeUp-CTF) + (guides sans réponses). +- **Isolation** — un conteneur par équipe et par challenge, réseau dédié. +- **Pas d'exposition Internet** — l'accès à la plateforme et à la supervision passe + uniquement par **Tailscale** ; la supervision (Grafana) est servie en **HTTPS** + (TLS terminé par Tailscale, cf. [`docs/SUPERVISION.md`](docs/SUPERVISION.md)). + ## Durcissement du serveur Mesures appliquées conformément au benchmark CIS Debian : @@ -122,6 +181,8 @@ Mesures appliquées conformément au benchmark CIS Debian : Le serveur CTFd est supervisé (métriques temps réel + alertes Discord) via une VM Grafana + Prometheus dédiée. Détail : **[`docs/SUPERVISION.md`](docs/SUPERVISION.md)**. +![Dashboard Grafana — Node Exporter Full (VM CTFd)](docs/img/grafana-dashboard.png) + ## Équipe projet | Membre | Rôle | @@ -133,8 +194,9 @@ Grafana + Prometheus dédiée. Détail : **[`docs/SUPERVISION.md`](docs/SUPERVIS ## Liens utiles +- Dépôt technique (ce dépôt) : https://github.com/Jacob-dot-bit/RootMeUp +- Dépôt joueurs (guides) : https://github.com/Jacob-dot-bit/RootMeUp-CTF - Suivi des tâches (Trello) : https://trello.com/b/noVfLRlC/rootmeup -- Dépôt GitHub : https://github.com/Jacob-dot-bit/RootMeUp - Plugin CTFd : https://github.com/Bigyls/CTFdDockerContainersPlugin ## Licence diff --git a/docs/SUPERVISION.md b/docs/SUPERVISION.md index 2ded5be..a7d8eb2 100644 --- a/docs/SUPERVISION.md +++ b/docs/SUPERVISION.md @@ -96,15 +96,31 @@ remplacer `${DS_PROMETHEUS}` par `prometheus`). ## Accès -- **Grafana** : `http://100.84.158.83:3000` (via Tailscale). Changer le mot de passe admin par défaut. -- **Prometheus** : `http://100.84.158.83:9090`. +- **Grafana** : **`https://grafana.tail2f7520.ts.net`** (HTTPS via Tailscale, cert Let's Encrypt auto). +- **Prometheus** : `http://100.84.158.83:9090` (tailnet). - Dashboard : *Dashboards → Node Exporter Full*, sélectionner le job `ctf-vm`. +### HTTPS via Tailscale (`tailscale serve`) +Grafana n'écoute qu'en local (`127.0.0.1:3000`) ; **Tailscale termine le TLS** sur `:443` +et proxifie vers Grafana. Le certificat Let's Encrypt est provisionné et renouvelé +automatiquement pour le nom MagicDNS. Prérequis : *HTTPS Certificates* activé dans la +console admin Tailscale (`login.tailscale.com/admin/dns`). + +```bash +# sur la VM Grafana +tailscale serve --bg 3000 # https://.ts.net/ -> http://127.0.0.1:3000 +tailscale serve status # vérifier le mapping +# désactiver si besoin : tailscale serve --https=443 off +``` +Côté Grafana (`/etc/grafana/grafana.ini`, section `[server]`) : `domain` et `root_url` +pointent sur `https://grafana.tail2f7520.ts.net/` pour que les liens générés soient corrects. + ## Sécurité - Le **webhook Discord** est un secret : il n'existe **que** dans `/etc/grafana/provisioning/alerting/discord.yaml` sur la VM Grafana, **jamais dans git**. - Grafana/Prometheus ne sont pas exposés sur Internet (accès uniquement via Tailscale). +- **Grafana en HTTPS** (TLS terminé par Tailscale, cert Let's Encrypt) — plus de trafic en clair. - Changer les identifiants Grafana par défaut (`admin`/`admin`). ## Évolutions possibles diff --git a/docs/img/ctfd-challenges.png b/docs/img/ctfd-challenges.png new file mode 100644 index 0000000..5205cf1 Binary files /dev/null and b/docs/img/ctfd-challenges.png differ diff --git a/docs/img/ctfd-instance.png b/docs/img/ctfd-instance.png new file mode 100644 index 0000000..917ddb3 Binary files /dev/null and b/docs/img/ctfd-instance.png differ diff --git a/docs/img/grafana-dashboard.png b/docs/img/grafana-dashboard.png new file mode 100644 index 0000000..8786290 Binary files /dev/null and b/docs/img/grafana-dashboard.png differ