Automating CTF Challenge Deployment

Over time CTFd has been used by many different CTFs and many different projects. These projects provide insight into how CTFd is being used and where it can improve.

The 1.2.0 release of CTFd is informed almost entirely by community feedback and analyzing how large competitions like CSAW make use of CTFd.

While there aren’t a lot of changes in how CTFd operates to the end user, there are a variety of changes that improve the reach and ability of CTFd plugins. These changes allow large scale projects to handle literally hundreds of challenges and better customize how challenges look to users. Sitting atop these changes, we are releasing a new feature to managed CTFd instances.

Automated Challenge Deployment

One of the longest term projects for CTFd has been to manage the orchestration of challenges.

EDIT: Hosted CTFd instances now utilize a docker push scheme instead of git push. For more details see our website.

In the past CTFd attempted challenge orchestration by allowing users to upload Dockerfiles. This turned out to be a complicated and rarely utilized feature. It was simply too difficult to pass the build context up to CTFd.

Unfortunately, without managing challenges themselves, it’s easy to begin to look at CTFd as little more than a scoreboard. However our new challenge deployment workflow changes that.

Heavily inspired by Heroku’s, git-based style of deployment, all CTFs hosted on ctfd.io will be able to deploy Docker based challenges with the simple:

git push ctf master

Once the challenge repo is received by our servers, build and deploy bots build the Dockerfile within the repo, automatically allocate a port, and deploy the challenge. In addition, deploy bots monitor for edge cases and automatically attempt to maintain uptime so organizers don’t always need to manually restart challenges.

Deployment Example

Let’s take a simple challenge that simply gives you the flag when you connect to the service.

print "flag{that_was_easy!}"

And we run it with a small Dockerfile:

FROM ubuntu:16.04
RUN apt-get update && apt-get -y install python socat
COPY challenge.py .
EXPOSE 12345
CMD socat TCP-LISTEN:12345,reuseaddr,fork EXEC:"python challenge.py"

Next we create a git repo out of the challenge folder and push the challenge up:

git init
git add -A
git commit -m "Add files"
git remote add ctf https://demo.ctfd.io/services/demo.git
git push ctf master
# Login as any CTFd instance admin user

CTFd will iterate through the build steps and automatically allocate a port and deploy the challenge.

The center blue button allows one-click challenge restarts in case of failures

Finally we can verify that the challenge is working by connecting to it:

~
❯ nc challenges.ctfd.io 30000
flag{that_was_easy!}

Hosted CTF Challenges

Managed CTFs at https://ctfd.io/ will automatically have this feature installed and you can access “Services” from the Admin Panel to begin deploying your challenges.

This feature has taken quite awhile to prepare and we’re quite proud of it.

We hope that you’ll make good use of it and feel free to contact us with any feedback or questions!