-
You have
cmgr
installed and configured.- Refer to the setup page if this is not the case for you.
-
You have done the Reversing Python Problem Creation Walkthrough. The Reversing Python walkthrough is a more basic example of using a single container for cmgr problem development. The file changes presented here will be as compared to Reversing Python.
This problem uses a container as a ssh server and has 3 files scattered around the filesystem that together compose the flag.
The new thing about this challenge is that it uses multiple build stages in the Dockerfile to make use of multiple containers instead of just one.
In General SSH, we spin up an Ubuntu container called "builder" and use it to
make the flag and store it in separate files and in /challenge/metadata.json
.
We spin up another container which we call "ssh_host". This is the container
that becomes the main focal point of the challenge. We copy the separate parts
of the flag to ssh_host and configure it to accept ssh connections.
It's a good practice to separate the work associated with building the
challenge from the actual challenge itself. That's why we make a "builder"
container and "ssh_host" container. If we made the "builder" container accept
ssh connections competitors might stumble across metadata.json
! This can be
mitigated with good permissions on the folder, but we consider best practice to
be separate containers, not just secure permissions.
-
instructions-to-Xof3.txt's contain verbal instructions on how to find the next part of the flag. The Dockerfile copies these into the "ssh_host" container.
-
profile is a bash profile that places the newly logged in user into a different folder than their home directory. This is done so that returning home from the root directory yields the last part of the flag instead of the first.
-
start.sh starts a listener that receives ssh connections. This script is ran as the last step in the Dockerfile.
-
Dockerfile, the first line is different for this file. It's the "LAUNCH" directive which tells cmgr which containers should be actively running for the challenge. For our challenge, we don't need "builder" running, but we do need "ssh_host" running. The next line of code is the "FROM" statement. We've appended "AS builder_base" to the end of this line to indicate that the following instructions are for the builder container. "builder" is actually a special name to cmgr, it's the container that it always expects to find
/challenge/metadata.json
and/challenge/artifacts.tar.gz
if applicable. The rest of "builder" is similar to Reversing Python. "ssh_host" isn't too different either, but notice the COPY instructions that grab files from "builder", such as line 36. This is a critical ability to connect your containers and your other containers are likely to need to know things from the "builder" container. We copy all of the flag parts in the Dockerfile since it can access them easily withCOPY --from=builder ...
. -
config-builder.py, this script generates the password from the seed and puts it in the file for the "ssh_host" to use. Then it generates the flag and splits it into 3 parts and writes a file for each, also for the "ssh_host" container. Finally, it writes the whole flag into
/challenge/metadata.json
, as needed by cmgr. It also puts the "password" into this file, so that the problem description can give the password to the competitor. -
config-sshhost.py, this script creates the "ctf-player" user and the needed directories and also changes the password of the account to be that which was generated by the "builder" container.
With this walkthrough, we created an advanced problem that used a Dockerfile to create multiple containers to separate building the challenge from actually playing it. The result is an ssh host container that has no challenge metadata present on it and never had any on it.