Skip to content

atgreen/ctfg

Repository files navigation

ctfg

This is a simple Capture-The-Flag game engine.

alt text

Building and Running

You will need to install a few dependencies first. If you are running homebrew, run...

brew install make sbcl ocicl gcc@11

Otherwise, install sbcl from your OS distribution, and then ocicl from source at https://github.com/ocicl/ocicl.

Once ocicl is available, run ocicl install to download the Common Lisp dependencies.

And then...

  • To build ctfg: make
  • To test ctfg: make check
  • To run ctfg: ctfg --help
NAME:
  ctfg - A Capture-The-Flag Game Engine

USAGE:
  ctfg

OPTIONS:
      --help                   display usage information and exit
      --version                display version and exit
  -b, --dbdir <VALUE>          database directory [default: .]
  -d, --developer-mode         enable developer mode
  -p, --port <INT>             port [default: 8080]
  -s, --slynk-port <INT>       slynk-port
  -w, --websocket-url <VALUE>  websocket-url [default: ws://localhost:12345/scorestream]

EXAMPLES:

  Run web service on port 9090:

    ctfg -p 9090

AUTHORS:
  Anthony Green

LICENSE:
  MIT

The --developer-mode option disables caching of static content, and reloads the challenges.json every time the Challenge page is rendered. This allows you view your changes in real time as you are developing content.

Client browsers must establish websocket connections back to the game engine on the /scorestream endpoint. Use the --websocket-url option to tell those clients what the URL is. For instance, if you are hosting ctfg on an OpenShift kubernetes cluster, you might create a TLS terminated route for your ctfg service and connect to it thusly: -w wss://scorestream-ctfg.apps.ocp.example.com:443/scorestream

Configuring your Game

  1. Player credentials should live in a file called credentials.csv. It's a simple username,password csv file.

  2. Challenges are in challenges.json. This should be a json array containing objects like this:

        {
            "id": 5,
            "title": "SQL Injection Login",
            "category": "Web",
            "difficulty": "Easy",
            "points": 150,
            "description": "This is an HTML description of the challenge. Put whatever you want in here.",
            "flag": "^regexp flag goes here$",
            "requirements": [2, 3]
        },

Each challenge needs a unique id. All of the other fields are self-explanatory. The requirements field is optional. It should be a list of challenges that must be solved before this challenge appears on the board.

  1. Replace images/banner.png with your own content.

  2. Edit game-clusters.yaml to point at the cluster hosting this app, as well as the list of player clusters (all possibly the same). Users are assigned to the different player clusters in a round-robin format as they join.

API

Most REST endpoints in ctfg are intended for use by the browser client. However, ctfg does provide one endpoint intended for use by an external non-browser client.

Posting to the /api/award endpoint emulates a successful flag submission for a specific username and challenge id. Use this API for any automated flag submission by an external judge process. For example, posting the following json will tell ctfg to behave as through player player1 had submitted the correct flag for challenge number 5.

{
  "username": "player1",
  "id": "5"
}

An AUTHORIZATION token must be provided in the http header for this API. Specify this token when you launch ctfg by setting the CTFG_API_TOKEN environment variable.

Author and License

ctfg was written by Anthony Green and is distributed under the terms of the MIT license.