This guide will walk you through the necessary steps to set up and validate a
sanity problem with cmgr.
A sanity problem is a straightforward task used in Capture the Flag (CTF) competitions. It serves as a preliminary check to ensure that your internet connection is stable and all other system assumptions are correctly configured.
This sanity challenge is a simple download of the flag in the file flag.txt.
- You have
cmgrinstalled.- Refer to the setup page if this is not the case for you.
We're starting with a sanity problem because it is the simplest challenge that
exists in every CTF. We will demonstrate creating a very simple Docker container
that just copies in flag.txt and makes it a downloadable artifact for cmgr and
sets the flag for the challenge appropriately.
The following walkthrough has 3 parts:
-
File listing. We will go over every file in the challenge directory.
-
Deployment. We will demonstrate deploying this challenge for testing.
-
Testing. We will demonstrate a good place to start with testing any challenge.
- Dockerfile builds the container used for the challenge. A container is required for every challenge with cmgr. This file is heavily commented to explain what each Docker command does. Please refer to the file itself for further explanation.
- problem.md specifies the
name of the problem, the description, and other metadata about the
problem. Though this is a Markdown file, it is actually parsed by cmgr.
Here is the
specification
for this file in general. We will go over some specifics here:
- The first heading is the name of your problem as it will appear on the platform.
- The first block contains important cmgr metadata and some
problem-specific values.
Namespacethis is the namespace in cmgr that your problem will be named under. Please use:Namespace: picoctfIDthis is the actual name of the problem for cmgr. If not specified, it will be the first heading converted to all lowercase and hyphens, but we like to specify it directly.Typethis should always beType: customCategorythis should probably be "General Skills," "Forensics," "Reverse Engineering," "Cryptography," "Binary Exploitation," or "Web Exploitation" but we might entertain other categories in the future.Pointsthis should bePoints: 1. We won't know the points for any given challenge until we can calibrate them with the rest of the challenges in a competition.Templatablethis is a bookkeeping value (which means it serves no functional purpose, it only exposes the intentions of the challenge developer) which indicates whether a challenge has a static or dynamic flag. We try to keep as many flags dynamic as possible as it helps us catch cheaters and allows us to regenerate the instance flags if we need.MaxUsersis another bookkeeping value which indicates whether instances of the challenge will be shared (MaxUsers: 0) or whether each user will get their own container (MaxUsers: 1). We call challenges where every user gets their own container "On-Demand". Indicate On-Demand if your container or service has mutable state. Any challenge that makes it to the Gym becomes On-Demand, because these are less expensive to host in the long-run.
- The
Descriptionsection is where you can explain your problem at a high level or provide flavor. Please put artifact download links here as the Details section is not visible for On-Demand challenges until after the container(s) start. - The
Detailssection is where you can put instance connection information. See the spec for more details. It can be empty if there is nothing relevant to include. - The
Hintssection should contain an unordered list of hints, but on the picoCTF platform these hints will be numbered in the order that they appear. This section can be empty. In our Gym, hints range from a mini-walkthrough for more pedagogical problems to frustratingly obscure references that don't really help until after you solve the challenge. - The
Solution Overviewis technically optional but we rely heavily on it to determine difficulty, and to verify working instances so please include it in reasonable detail. - The
Challenge Optionsare actual container options that are applied to your container(s). These are used to limit the amount of resources that any given container can consume. The default options given are sort of a minimum starting point. These options only apply to containers that the players actually interact with. If everything seems good, but your services won't start, you might have to bump up these challenge options. However, they can't be too high, otherwise we won't be able to support this challenge for the thousands of users that we see in competitions. See this page for more detailed explanation. - The
Learning Objectiveis also optional but is very useful to us as a one sentence statement about what a challenge aims to teach. - The
Attributessection can mostly be ignored by challenge authors, but please include the author line you want to be published with your challenge.
- flag.txt. This is what
everyone is trying to get! We pass it into our container, and it creates a
tarball out of it called
artifacts.tar.gzwhich cmgr looks for so it can provide links in the Description or Details of problem.md.
Follow these steps to deploy the sanity check problem.
Testing of problems involves at least 3 things:
- Testing that an incorrect flag is incorrect
- Testing that a correct flag is correct
- Testing that the correct flag can be found by using the materials given for the problem.
- To test an incorrect flag, try submitting
aaaas a flag to the problem.- Expected output:
That is not the correct flag
- Expected output:
- To test the correct flag and that the correct flag can be found using the
given materials, download the flag from the problem and submit it
- Expected output:
Correct
- Expected output:
These steps ensure that /challenge/metadata.json was created correctly. This
is just basic, functional testing of your problem. A lot of testing goes into
appropriately adjusting the difficulty of a problem and making it challenging
enough to be interesting, but still accessible.
With this guide, we saw everything that goes into creating a simple sanity problem. Besides the challenge files, the Dockerfile and problem.md are the most important files.
We also demonstrated some basic testing practices by proving that an incorrect flag is incorrect, a correct flag is correct, and that the player can get the correct flag from the materials given.
This is the simplest challenge in a series designed to familiarize new authors with the cmgr format for picoCTF problems. Other guides here will demonstrate generating a dynamic flag, creating challenges for other traditional CTF categories and more!
Check out forensics grep to learn how to create and use dynamic flags!