rCTF Docs
Overview

Challenge design

Guidelines for planning, authoring, and testing CTF challenges, including difficulty distribution, flag formats, and quality assurance.

Before you start authoring challenges, settle on the general format and scope of the competition. A well-organized CTF usually shares a few traits:

  • The event should last for either 24 or 48 hours and be held on a weekend or Friday night.

  • Challenges should conform to standard CTF categories.

  • Each category should contain approximately 2-6 challenges, with a similar number of challenges across all categories.

  • Challenge difficulty should be distributed across a range from easy to hard, accommodating participants of varying skill levels. A common distribution is 1-2 easy, 2-3 medium, and 1-2 hard.

Challenge authoring#

Good challenges are what make a CTF worth playing. Keep these guidelines in mind during development.

General principles#

  • Avoid recycling challenges from other CTFs or online resources. Participants can often identify reused challenges.

  • Avoid making challenges overly difficult, contrived, or reliant on “guessing.” A “guessy” challenge is one where the solution is unclear, so solvers fall back on arbitrary or brute-force approaches instead of reasoning from the given information. Good challenges have enough clues to make logical progress possible and reward problem-solving over brute persistence. If no one solves a challenge, the issue is usually design, not difficulty.

  • Challenges should be solvable within a reasonable timeframe given the event duration.

  • Challenge descriptions should not include red herrings.

  • Ideally, each challenge teaches or reinforces a concept or technique.

Challenge components#

Each challenge should include the following:

ComponentCommentsNecessity
TitleA memorable name. The typical convention is to use Kebab case for titles. Please be fun with the title rather than calling it keygen or pwnme or warmup or crackme.Required
DescriptionContext and necessary information for the challenge. Descriptions are often themed and playful.Required
HintsAvoid actually using the “Hints” field, but rather use hints reactively during the CTF for unsolved challenges (e.g., after gauging progress at the 24-hour mark). See Hint policy for more information.Optional, uncommon
CategoryThe primary category (the one most aligned with the challenge, for challenges that fit multiple categories).Required
AuthorThe challenge author. Meta challenges, such as survey or sanity checks, should be authored by “Team” or some other umbrella name.Optional, common
TagsAdditional categorizations. Tags are often used for bounties, challenges part of a series, or challenges that fit into multiple categories.Optional, common
DifficultyRelative difficulty level. This is a contentious topic due to the subjective nature of difficulty ratings, so this is sometimes excluded.Optional, uncommon
FlagThe solution in the established format.Required
AttachmentsAny downloadable attachments. Attachments should be nicely zipped and uniquely named to avoid issues like dist(4).tar.gz. (konata helps with this!)Optional, common
RemoteConnection information for hosted challenges (if applicable). They should be placed in a one-line <pre> rather than a <code>. rCTF provides a custom [!CONNECTION] callout for this purpose.Optional, common
InstancerConfiguration for instancer challenges (if applicable). This should not be public but rather documented internally, and open-sourced after the CTF.Optional, uncommon
SolutionA working solve script or writeup. This should be referenced internally during playtesting and released after the CTF.Optional, recommended

Dockerization#

For challenges that need a remote component, Docker is the recommended way to ship them. Containers give you reproducible builds, easy deployment, and isolation between challenges.

Best practices#

  • Keep one challenge per container so each challenge stays self-contained. If a challenge requires multiple services (e.g., a web app and a database), use Docker Compose.
  • Reach for minimal base images like alpine or debian-slim to reduce build times and attack surface.
  • Build artifacts separately with multi-stage builds, compiling binaries in one stage and copying only the final artifact into the runtime image.
  • Run challenge services as non-root users inside the container to limit the impact of container escapes.
  • Use a read-only filesystem where possible by mounting the root filesystem as read-only (readOnly: true or --read-only) and using a tmpfs for writable directories.

Security defaults#

When deploying challenges, apply the following security settings:

  • cap_drop: ALL drops all Linux capabilities.
  • no-new-privileges: true prevents privilege escalation.
  • Memory and PID limits prevent resource exhaustion (e.g., fork bombs).
  • Network isolation uses internal networks for multi-container challenges where services should not be directly reachable.

Example Dockerfile#

Dockerfile
FROM python:3.12-slim
RUN useradd -m ctf
WORKDIR /home/ctf
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py flag.txt ./
RUN chmod 444 flag.txt
USER ctf
EXPOSE 5000
CMD ["python", "app.py"]

Using with rCTF instancer#

If you’re using rCTF’s docker instancer integration, define the Docker Compose-like configuration in the challenge’s instancerConfig field. The instancer handles container lifecycle, networking, and cleanup automatically.

Pre-event checklist#

Before the event, verify the following for each challenge:

  • The challenge is solvable with the provided materials. Where it fits, ship a single solve.py that outputs the flag.
  • The challenge has been playtested internally. Two playtesters per challenge is the safer bet.
  • The flag is correct and matches the expected format.
  • The files are correctly packaged and downloadable. Double-check that the files are the right versions, since authors sometimes update source code without re-packaging the distribution zip.
  • The remote services are accessible and stable.
  • The Docker containers build and run correctly.
  • The solution or writeup is documented internally and accessible to the support team.
Tip (Recommended reading)

For additional guidance on challenge design, refer to the CTF Design Guideline.

Esc

Start typing to search the docs.