Plateforme de Capture The Flag légère, écrite en Flask, conçue pour animer une initiation à la cybersécurité en classe. Authentification par équipes, 21 défis répartis en six catégories, scoreboard en temps réel et distribution des fichiers de défi.
Ce dépôt contient la plateforme, les défis et les solutions commentées. Il a servi à des élèves de spécialité NSI en première et terminale.
Python 3.7 ou supérieur est requis.
git clone https://github.com/tibo-develop/ctf-platform.git
cd ctf-platform
pip install -r requirements.txtpython app.py # crée la base et lance le serveur sur le port 5000Puis, dans un second terminal :
python add_challenges.py # peuple la base avec les 21 défisLe script crée également une équipe de test (admin / admin). Si la base contient déjà des défis, il demande confirmation avant de les remplacer.
L'application écoute sur 0.0.0.0:5000, donc les postes du réseau local y accèdent via http://IP_DU_SERVEUR:5000. Pour connaître cette adresse : ip addr sous Linux, ipconfig sous Windows.
.
├── app.py # application Flask
├── add_challenges.py # peuplement de la base (défis + flags)
├── re-initialisation_equipes.py
├── requirements.txt
├── static/
│ ├── css/style.css
│ └── downloads/ # fichiers téléchargeables par les équipes
├── templates/ # vues Jinja2
└── solutions/ # solutions commentées, une par défi
La base ctf.db est générée au premier lancement et n'est pas versionnée : elle contient les flags en clair et se reconstruit intégralement depuis add_challenges.py.
| Catégorie | Défi | Points |
|---|---|---|
| Web | Inspection basique | 50 |
| Web | Cookie Monster | 100 |
| Web | Find CSS | 100 |
| Cryptographie | Base64 facile | 50 |
| Cryptographie | Hex facile | 50 |
| Cryptographie | César antique | 100 |
| Cryptographie | Xor facile | 250 |
| Cryptographie | Xor difficile | 400 |
| Stéganographie | Méta audio | 150 |
| Reverse | Python simple | 150 |
| Reverse | md5 hash | 200 |
| OSINT | Recherche basique | 50 |
| OSINT | Localisation | 100 |
| OSINT | Who is... | 100 |
| OSINT | Cinema in Paris | 200 |
| Divers | QR Code | 100 |
| Divers | Petite somme | 100 |
| Divers | Somme de 1 à n | 100 |
| Divers | Objectif Lune | 150 |
| Divers | Récursivité | 200 |
| Divers | Décompresse | 100 |
Les flags suivent le format FLAG{contenu}, sensible à la casse, accolades comprises.
Attention — le dossier
solutions/contient les réponses. Si vous réutilisez ces défis avec des élèves, changez les flags dansadd_challenges.py: ce dépôt étant public, les solutions sont accessibles à qui les cherche.
Tout se passe dans la liste challenges de add_challenges.py :
{
'title': 'Titre du défi',
'description': 'Énoncé, avec le format de flag attendu.',
'category': 'Web', # Web, Cryptographie, Steganography, Reverse, OSINT, Divers
'points': 100,
'flag': 'FLAG{reponse}',
'file_path': 'fichier.zip' # ou None
}Les fichiers référencés par file_path vont dans static/downloads/. Relancez ensuite python add_challenges.py.
python re-initialisation_equipes.py # supprime équipes et résolutionssqlite3 ctf.db "SELECT title, flag, points FROM challenges ORDER BY category, points"Cette plateforme est prévue pour un usage local en salle de classe. Elle n'est pas durcie pour un déploiement exposé sur Internet, et plusieurs choix la rendent délibérément simple à lire pour des élèves plutôt que robuste :
- les mots de passe sont hachés en SHA256 sans sel, là où bcrypt ou argon2 seraient de rigueur ;
- le serveur tourne avec
debug=Truesur0.0.0.0, ce qui expose le débogueur Werkzeug au réseau ; - la clé de session est codée en dur dans
app.py; - aucune limitation du nombre de tentatives de soumission.
Ces points constituent d'ailleurs un bon support d'exercice : demander aux élèves de les identifier est un prolongement naturel du CTF.
« Address already in use » — le port 5000 est occupé. Changez-le en dernière ligne de app.py.
Un fichier de défi ne se télécharge pas — vérifiez qu'il existe bien dans static/downloads/ et que son nom correspond au file_path en base.
Erreur 500 à la soumission — la base est probablement absente ou incomplète. Supprimez ctf.db, relancez app.py puis add_challenges.py.
Les ressources tierces (texte de Jules Verne, jeu de données de la Ville de Paris, photographie sous licence Creative Commons) sont détaillées dans CREDITS.md.
Le code est distribué sous licence MIT — voir LICENSE.
Les énoncés et les solutions sont mis à disposition sous CC BY-SA 4.0. Les ressources tierces conservent leur licence d'origine.