A lightweight CTF (Capture The Flag) platform built with Node.js, Express, and Docker
This platform allows admins to dynamically add challenges and manages interactive environments using Docker
The platform handles high-concurrency environments through Docker orchestration.
- Unique Instances: When multiple users connect to the same challenge port simultaneously, the system spawns independent containers with different ids
limitation: planning to constraint containers to a fixed amount of ressources and auto-cleanup after a certain time of inactivity in the future
- Port Consistency: Users connect via a single designated port (e.g.,
8001), but their session is isolated from others
note that each challenge has only one port for it, but that one port forks new processes
- Dynamic Insertion: Add challenges on the fly without restarting the Node.js server.
- Automated Validation: Depending whether the challenge is selected to be interactive or not in the admin panel, the challenge directory is checked to see if the required minimal files exist or not, otherwise the challenge isn't approved to be added
here the filesystem is the source of the truth, adding a challenge requires the following steps:
Place your challenge files in the appropriate category folder. For an Interactive (Docker) challenge:
- Path:
challenges/[category]/[name]/ - Required Files:
Dockerfileentrypoint.shstart_instance.shchallenge_files/flag.txt(The platform reads this to sync the DB flag)
Note that for a non Interactive Challenge, only
challenge_files/flag.txtis required to exist
The orchestrator.sh script manages all the interactive challenges, builds the images once, and listens and forwards data bidirectionally to the correspondant challenge by relying on a challenge_configs.json to map a given port to a certain challenge
Then [category]/[challenge_name]/start_instance.sh runs a new independent container with a random id and communicates with entrypoint.sh
entrypoint.sh is simply responsible of forwarding in and out traffic inside the container only
- Backend: Node.js & Express
- Database: SQLite3 (Local file-based)
- Containerization: Docker & Bash Orchestration
- Templating: EJS (Embedded JavaScript)
Ensure you have the following installed on your Linux/WSL environment:
- Node.js (v18+)
- Docker & Build-essential (for SQLite)
- jq (for JSON parsing in scripts)
To launch the platform and verify that the "Spawn-on-Connection" isolation is working correctly, follow these steps:
- A. Start the CTF Engine Ensure your scripts have the correct permissions and launch the main entry point:
# Set execution bits
chmod +x start_ctf.sh
# Launch Web Server + Orchestrator
./start_ctf.shTo confirm that the orchestrator is correctly spawning independent, isolated environments for every connection, perform a "Parallel Connection Test":
- Open Terminal Window A: Run
nc localhost 8001 - Open Terminal Window B: Run
nc localhost 8001