Deploying Challenges

Automatic challenge deployment is only available to Hosted and Enterprise installations of CTFd

Automatic Challenge Deployment allows CTFd to manage and deploy Capture The Flag challenges in the form of challenge containers. Challenge containers are typical applications packaged using Docker into Docker images.

However challenge containers/services must have certain properties.

  • Challenge containers must EXPOSE a port (e.g. EXPOSE 8000) in their Dockerfile/image.
  • Challenge containers should be as small as possible
  • Challenge containers should not be comprised of multiple applications
  • Challenge containers are not made with docker-compose

It’s worth noting as well that Hosted CTFd instances do not need to use our challenge deployment infrastructure. If you have very specific requirements, you’re free to run your application on seperate servers. For example those provided by DigitalOcean, Amazon Web Services, Google Cloud Platform, or Microsoft Azure.

Creating Services

To create a service based challenge:

  1. Login as an administrator and navigate to the Admin Panel.
  2. Click on the “Services” link on the top right
  3. Click the plus icon to go to the create service page
  4. Give your service a title in lowercase only and click the “Create” button
  5. Build your docker image
  6. After building the docker image, run the commands listed on the service page
    • docker login [registry.ctfd.io]
    • Login with your CTFd username as <username>@<subdomain.ctfd.io> and account password.
    • docker tag [your built image] [registry.ctfd.io//]
    • docker push [registry.ctfd.io//]
  7. The service page will then update with the deployed domain name of the challenge (You may need to manually refresh the page). You should receive an email every time the challenge is deployed.

Below is a hypothetical example using the demo.ctfd.io hosted CTFd instance.

$ docker login registry.ctfd.io
Username: admin@demo.ctfd.io
Password: password
Login Succeeded

$ docker tag <image> registry.ctfd.io/demo/<challenge-name>

$ docker push registry.ctfd.io/demo/<challenge-name>
The push refers to repository [registry.ctfd.io/demo/<challenge-name>]
d331a460b7f1: Pushed
b826215d4ea3: Pushed
0987a4ff6d69: Pushed
d7a1c1d656bd: Pushed
2c77720cf318: Pushed
1f6b6c7dc482: Pushed
c8dbbe73b68c: Pushed
2fb7bfc6145d: Pushed
latest: digest: sha256:... size: 12345

As a reminder, your Docker image must have a port exposed. Most images do, but if you happen to be writing something custom, here’s the reference in the Docker documentation.

Common examples are EXPOSE 80 or EXPOSE 8000.

Once the docker image succeeds, the services page should show:

Current Status: deployed

Deployed On: demo-challenge.chals.io

Internal Port: 8000

This is persistent link that participants can use to access your challenge.

Connecting to Services

Hosted CTFd instances uses an improved customized infrastructure based on SNI multiplexing to host challenge services. Our infrastructure automatically encrypts all communication to a challenge service and all communication happens over a single well known port (443). You can read more about the this design on our blog at https://blog.ctfd.io/hosted-challenge-deployment-improvements/.

If the underlying application you’ve deployed is a web server, you can simply open the URL in a browser and it will work seamlessly (e.g. https://demo-challenge.chals.io).

However, if your underlying application communicates directly over TCP you have a few options:

  1. You may use an SSL/TLS aware client software such as our snicat (sc) tool.

  2. Or you can “Request a TCP port” from our infrastructure and use a tool such as netcat. Keep in mind that this will forego any security or vanity benefits provided by using our encrypted connections.

snicat

snicat is designed to be very similar to netcat whilst providing vanity urls and encrypted connections. snicat can also be downloaded for Mac, Linux, and Windows.

For example:

❯ sc demo-challenge.chals.io
(connected to demo-challenge.chals.io:443 and reading from stdin)
...

For Linux and Mac the following commands should download snicat for you:

wget "https://github.com/CTFd/snicat/releases/latest/download/sc_`uname`_`uname -m`" -O sc
chmod +x sc

For Mac, you may need to remove the quarantine attribute by running:

xattr -d com.apple.quarantine sc

For Windows, you can download the x64 exe here and then run it from the command prompt.

Please refer to https://github.com/CTFd/snicat for full details and documentation

netcat / Requesting a TCP port

If you’d like users to use netcat, you can, however keep in mind that connections will be unencrypted.

  1. Browse to your deployed service and select the TCP connection tab

  1. Click on “Request TCP Port”. Confirm that you’d like to request a port.

  1. Refresh the page if it does not automatically refresh

  2. You should receive a hostname and port as shown below:

Once you’ve been allocated a hostname and port, share it with your users for them to be able to connect to the service via tools like netcat.

Alternatively you can also leverage our fallback proxy service that allows netcat to connect to challenge services without requesting a port.

For example:

❯ nc cloud.chals.io 23
Host: demo-challenge.chals.io
...

Others

If none of the above options work for you, you can take a look at some of the other options here.

Questions/Feedback

If you have any questions or any feedback, please feel free to contact us.