Important
The Template section must be removed after you have created a repository from this template.
This section serves only to inform you on how to use this template.
This repository serves as a template for creating new challenge repositories in the CTF Pilot ecosystem.
It includes the necessary structure, workflows, and tools to streamline challenge development and deployment.
-
Create a New Repository:
- Click the "Use this template" button on the repository page.
- Name your new repository and configure its visibility.
-
Allow pipeline to create pull requests:
- Go to the "Settings" tab of your new repository.
- Select "Actions" > "General".
- Check the box for "Allow GitHub Actions to create and approve pull requests".
-
Clone the New Repository:
- Clone your newly created repository to your local machine using Git.
-
Remove the Template Section:
- Open the
README.mdfile in your new repository. - Remove the entire
Templatesection to avoid confusion.
- Open the
-
Insert repository name (
owner/repo) in the README.md file:- In the
README.mdfile, replace all instances ofctfpilot/challenges-templatewith your new repository's name in the formatowner/repo. (Use find and replace feature of your text editor).
- In the
-
Update GitHub project link:
-
In the
README.mdfile, update the link to the GitHub project board in theProject boardsection to point to your own project board. Link to update:https://github.com/orgs/ctfpilot/projects/1If you do not have a project board, you may remove the entire
Project boardsection, or follow the instructions in the GitHub projects section to create one from the template.
-
- Branch protection rules:
- It is recommended to set up branch protection rules for the
mainbranch to ensure that changes are reviewed before being merged. This may not be applicable if you the repository is private, as branch protection rules may require a paid plan for private repositories.
- It is recommended to set up branch protection rules for the
- Enable
Always suggest updating pull request branches:- In the "Settings" tab, under "General", enable the
Always suggest updating pull request branchesoption to help keep pull requests up to date with the base branch.
- In the "Settings" tab, under "General", enable the
Included in this template are the following tools and configurations:
The tools are configured to work out-of-the-box, enabling you to focus on challenge development rather than setup.
However, for advanced customization, refer to the documentation of each tool.
CTF Pilot's Discord Bot can be integrated with this repository.
However, this README does not provide instructions to challenge developers on how it can be used to do some of the automation.
Refer to the Discord Bot documentation for more information on how to set up and use the bot with your challenge repository.
To manage challenges and track progress, GitHub Projects can be utilized.
A template GitHub project is available in: Challenges Project board Template.
You can create a new project from the template, and link it to your challenge repository.
The template repository is licensed under the EUPL-1.2 License.
The included tools are licensed under their respective licenses.
By contributing to this template repository, you agree to our Contributor License Agreement (CLA).
The CLA can be found in https://github.com/ctfpilot/cla.
You may copy, modify, and distribute this template repository under the terms of the EUPL-1.2 License.
Any content you add to your new repository, that is templated from this repository, is subject to your own licensing terms.
A license file is not included in this template repository to avoid confusion.
This repository contains CTF Pilot's Challenge Toolkit as a Git submodule.
In order to retrieve the submodule, run the following command after cloning the repository:
git submodule update --init --recursiveTip
Challenges are located in the challenges/ directory.
The repository is structured as follows:
.
├── challenge-toolkit/
├── challenges/
│ ├── web
│ ├── forensics
│ ├── rev
│ ├── crypto
│ ├── pwn
│ ├── boot2root
│ ├── osint
│ ├── misc
│ ├── blockchain
│ └── beginner/
│ └── challenge-1
├── pages/
│ └── page-1/
├── template/
└── <other files>Inside the challenges directory, challenges are divided into categories.
Each challenge is stored in its own directory, named identically to the challenge slug.
Tip
Challenge source code is located in the src/ directory.
The main files are challenge.yml, description.md and README.md.
Each challenge is stored in its own directory, named identically to the challenge slug. Within the challenge directory, there are several subdirectories and files that make up the challenge.
The subdirectory structure of a challenge is as follows:
.
├── handout/
├── k8s/
├── solution/
├── src/
├── template/
├── challenge.yml
├── description.md
├── README.md
└── versionhandout/contains the files that are handed out to the user. This may be the binary that needs to be reversed, the pcap file that needs to be analyzed, etc. The files in this directory are automatically zipped and stored in thek8s/files/directory as<category>_<slug>.zip.k8s/contains the kubernetes deployment files for the challenge. This is automatically generated and used for deploying to the CTF platform. This directory should not be modified manually.solution/contains the script that is used to solve the challenge. This is filled out by the challenge creator. No further standard for the content is enforced.src/contains the source code for the challenge. It contains all the code needed for running the challenge. It may also contain any copies that needs to be handed out. Dockerfiles, python scripts, etc. lives here.template/contains the template files for the challenge. For example the kubernetes deployment files, or similar, that are rendered with the data from thechallenge.ymlfile.challenge.ymlcontains the metadata for the challenge. This must be filled out by the challenge creator. Follows a very strict structure, which can be found in the schema file provided in the file.
The file may be replaced by a JSON file, aschallenge.json.description.mdcontains the description of the challenge. This is the text that is shown to the user, when they open the challenge. It should be written in markdown.README.mdcontains the base idea and information of the challenge. May contain inspiration or other internal notes about the challenge. May also contain solution steps.versioncontains the version of the challenge. This is automatically updated by the CI pipeline, when a new version is released.
To learn more about the challenge.yml file, see the CTF Pilot's Challenge Schema.
Tip
When developing a challenge, it is recommended to create a new branch for the challenge.
The flow for a challenge will look as such: develop -> challenge/<challenge-slug> -> develop -> main.
The project uses Git and Github til manage the challenges.
The repository uses two primary branches, main and develop.
develop is the default branch, and are open for all to push to. However, we recommend that you branch out into your own branch, to make your challenge.
main is the branch that is used for the live CTF, and should only be updated by the maintainers of the CTF. Data stored here, will be synced into the CTF platform.
Flow visualization:
gitGraph
commit id: "Initial commit"
branch develop
checkout develop
commit
branch challenge-1
checkout challenge-1
commit id: "Create challenge 1"
checkout develop
branch challenge-2
checkout challenge-2
commit id: "Create challenge 2"
checkout develop
merge challenge-2 id: "Updated challenge 1"
merge challenge-1 id: "Updated challenge 2"
checkout main
merge develop id: "Deploy to platform"
checkout develop
commit id: "Update challenge"
Tip
The development process can be broken down into the following steps:
- Create a new challenge using the Create challenge tool.
- Develop the challenge in the
challenge/<challenge-slug>branch. - Push the changes to the branch.
- Request a review of the PR.
- Merge the PR into
developwhen a review has been done. - Merge
developintomainwhen the challenge is ready for the CTF platform.
All challenges must fit into the structure described in the Challenge structure section.
If it is your first time developing a challenge, please read the entire section before starting the development process.
The challenge development process is as follows:
- Create a new challenge based on the Create challenge section.
- TL;DR: Use the Create challenge Github action to create a new challenge.
- Update the generated issue with the challenge information.
- The description of the issue with relevant information about the challenge.
- Checkout the branch created by the Github action locally
- Clone the repository and switch branch to the new branch:
git clone https://github.com/ctfpilot/challenges-templatecd ctfpilot/challenges-templategit checkout challenge/<challenge-slug>
- Develop the challenge.
- Develop your challenge, by adding the files needed in the
src/andhandout/directory. - Update challenge metadata in the
challenge.yml. - Write the challenge description in
description.md. - Write the general information about the challenge in
README.md. - Write a solvescript and document steps to solve the challenge in
solution/ - If the challenge is a shared og instanced challenge, customize the deployment files in the
template/directory.
- Develop your challenge, by adding the files needed in the
- Push the changes to the branch.
- It is recommended to this regularly, to ensure that the data is not lost.
- Request a review of the PR.
- If the challenge is either shared og instanced, coordinate with the infrastructure team to get a review of the challenge.
- Merge the PR into
develop.- This should be done, when you feel comfortable with the challenge, and a review has been done.
- You have done it! Challenge is now at a stage, where it is ready to come on the CTF platform.
- The challenge can now be deployed to staging (if applicable), and later to production.
- To release the challenge to production, merge
developintomain.- This should be done by the maintainers of the infrastructure.
If you want to update the challenge, you can do so by repeating the process descriped above, but instead of creating a new challenge, you should create a new branch for the challenge based on the develop branch.
Read more about this in the Git: Branch flow section.
Challenges are automatically versioned to allow for easy updates and tracking of changes.
Large files should never be commited to the repository. If you need to add a large file, please reach out to the infrastructure team, so that they can help you with the process.
Caution
Large files should never be commited to the repository.
If a large file is commited to the repository, it needs to be downloaded by everyone that clones the repository, regardless of it being deleted in the future.
If you have no experience with Git, please reach out to the infra team for help.
The infra team may also be able to stuff your challenge into the format, if you have developed outside of the structure. But give it a try yourself first.
To create a new challenge, you can use the provided Github action workflow: Create challange.
This workflow can be found in the Actions tab of the repository.
The workflow automatically creates a new challenge, with the necessary structure and files, including a branch, pull request and issue for tracking the challenge development.
To create a new challenge, follow these steps:
- Go to the
Actionstab of the repository. - Select the
Create challangeworkflow from the left sidebar. - Click the
Run workflowbutton. - Fill out the required inputs:
Existing issue(optional): If you have already created an issue for the challenge, you can provide the issue number here. Otherwise, leave it blank to create a new issue.Name: The name of the challenge.Author: The author of the challenge. This can be your name or alias.Category: The category of the challenge. A dropdown provides the available categories.Difficulty: The difficulty of the challenge. A dropdown provides the available difficulties.Type: The type of the challenge. Possible values are:
static: Challenge may have a handout but requires no remote.
shared: Challenge is hosted on a shared instance, which is shared among all players.
instanced: Challenge is hosted on an individual instance per team/player.Instaced type(optional): If the challenge type isinstanced, you can provide the type of instance, such as web or tcp.Flag: The flag for the challenge. Remember to follow the flag format.Minimum points: The minimum points for the challenge. This is used for dynamic scoring.Maximum points: The maximum points for the challenge. This is used for dynamic scoring.
- Click the
Run workflowbutton to create the challenge. - Wait for the workflow to complete. This may take a few moments.
- Once the workflow is complete, a new branch, pull request, and issue will be created for the challenge.
If errors occur during the workflow execution, please reach out to the infrastructure team for assistance. Logs from the workflow can be found in the Actions tab of the repository.
A project board is available to track the progress of challenges.
This can be found at: Challenges Project board