GithubHelp home page GithubHelp logo

gerrit0 / ctfd_unique_challenges Goto Github PK

View Code? Open in Web Editor NEW
4.0 3.0 1.0 144 KB

A CTFd plugin that adds challenges which have a unique flag per user/team

Python 40.24% HTML 13.54% JavaScript 43.68% CSS 2.54%

ctfd_unique_challenges's Introduction

Unique Challenges for CTFd

This plugin was developed as part of an independent study at UCCS.

Compatible with CTFd v2.2.3

When using CTF challenges in an academic environment, it provides some benefit to give each student a unique flag. This makes sharing answers easily detectable while still allowing students to work together in learning the material.

When using this plugin, challenge visibility must be set to Private or Admins Only.

This plugin provides a new challenge type - unique. This challenge type lets the content author use placeholders like !flag_8! to insert a dynamic value for each CTF user/team in the challenge description or downloadable text file. It also allows administrators to write Python 3 scripts that will be passed the placeholders to generate a downloadable text file.

Installation

cd /path/to/CTFd/plugins
git clone [email protected]:Gerrit0/CTFd_unique_challenges.git unique_challenges

Setup Script

To quickly set up a CTFd development server with this plugin installed, run the following commands

python3 -m venv env
source env/bin/activate
git clone https://github.com/CTFd/CTFd.git
cd CTFd
pip install -r requirements.txt
git clone [email protected]:Gerrit0/CTFd_unique_challenges.git CTFd/plugins/unique_challenges
python serve.py

ctfd_unique_challenges's People

Contributors

gerrit0 avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ctfd_unique_challenges's Issues

Programmable flags

The professional instance of CTFd ($100/month) allows administrators to write custom logic in order to determine if a submitted flag is valid. This shouldn't be difficult to replicate, and would enable much more flexible authoring capability.

image

Support for calling a program to generate a custom file

With #2, it will be possible to replace a !placeholder! within an uploaded file. Most of the time, I expect this to be sufficient, but it should also be possible to take the placeholders as input to a administrator-provided script and use the output of that script as the unique file for that user.

As an example of why this could be useful, if a user is supposed to Caesar cipher their file to get the flag, a unique flag could be produced with a script like this:

# PLACEHOLDERS is provided by the unique_challenges plugin when evaling this code
# PLACHOLDERS = dict(flag_8='a'*8, flag_16='b'*16, flag_32='c'*32, name='name')
import string
def caesar(plaintext, shift):
    alphabet = string.ascii_lowercase
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    table = str.maketrans(alphabet, shifted_alphabet)
    return plaintext.translate(table)

print(caesar(PLACEHOLDERS['flag_8'], 13))

Now when a user caesar decodes the flag and submits it, it will be accepted.

I'm not sure if there is any value in extending this to also let the description be generated programatically. I don't think there is.

Allow unique challenges to also replace placeholders in uploaded files

Currently, the unique challenges plugin only supports replacing the !placeholder! values within the challenge description. This isn't sufficient for challenges that need more space for the challenge description.

For example, a challenge that explains how to use grep -v would ideally be able to upload a file created with something like this:

yes not this line | head -1231
echo '!flag_8!'
yes not this line | head -2347

Then tell participants to run grep -v "not this line" on the downloaded file to find their unique flag.

Plugin architecture documentation

While the existing CTFd documentation for plugins was helpful when developing, it was not complete, there were still several questions left unanswered that I had to spend time reading the source to answer.

To make modifying this plugin as easy as possible, create a document describing the overall architecture of the plugin and go through the source to ensure methods are properly documented.

images

Apparently you can't paste images into wiki pages, so I'm using this as a workaround.

image

Handle users submitting placeholders as flags

Right now, the unique challenges plugin makes a half-hearted effort to prevent users from submitting placeholders as flags.

"""Normalizes the submission so that static flags can include the placeholders.
Note that to avoid participants being able to submit placeholders to complete
challenges we also have to replace the placeholders in the submission with an invalid
value. Currently, this is set to the empty string.
"""
replacements = {
"!name!": "",
"!flag_8!": "",
"!flag_16": "",
"!flag_32": "",
username: "!user!",
unique_flags.flag_8: "!flag_8!",
unique_flags.flag_16: "!flag_16!",
unique_flags.flag_32: "!flag_32!"
}
regex = re.compile("|".join(map(re.escape, replacements)))
return regex.sub(lambda match: replacements[match.group(0)], submission)

This... doesn't work.

If the static flag for the challenge is !flag_8! and the user submits !flag_8!, it will be collapsed to the empty string. But if they submit !flag_!flag_8!8! it will be collapsed to !flag_8! and the user will have completed the challenge without having actually done the work.

This is detectable, the user's original input is saved as the correct submission, but it ideally should be prevented altogether.

There are a couple options:

  1. Replace the placeholder with a specific non-empty string that administrators are informed of
  2. Immediately reject any submission that contains a placeholder

The second option will completely prevent this issue. I think it is the best solution for the problem.

Challenge requirements design

As it turns out, CTFd already has a "Requirements" tab that handles challenges depending on other challenges. Furthermore, the CTF as a whole can be time locked. However, this isn't sufficient for the stated goals.

Further, this doesn't support creating criteria on a section/individual basis. This is... tricky. I know architecture like Canvas that was built with this in mind has the capability, but doing it in such a way that it doesn't tank performance when you get more challenges is tricky. Ideally, I'd like to avoid making an extra database query for every challenge when viewing the challenges list. This might be unavoidable.

Unlike Canvas, CTFd doesn't have a concept of "sections". Everyone who registers for a CTF is competing in the same CTF. If different sections should have different challenges available at different times, it doesn't really make sense to put them all into the same CTF with the same leaderboard.

This could be done by creating "base" challenges which all other challenges depend on for each section, and giving out the flag to the base challenge in class the first day, but this feels like a hack. I think it makes more sense for the CTFd architecture if each class gets its own instance... unfortunately, this means that if a teacher is teaching multiple sections of the same class that have slightly different due dates, there will be a ton of duplication...

I am having some difficulty envisioning how this user interface should look... I could just provide a basic lisp-like interface (for ease of parsing) and a few functions, but while this would be usable for some administrators, it would be difficult for others to use.... If this is the chosen route, I think it should only be run when attempting to complete a challenge since it is potentially expensive to evaluate (6 database queries for the below condition)

(and
  (after "2019-02-20")
  (completed (find-challenge "Name"))
  (or
    (completed (find-challenge "Prereq"))
    (completed (find-challenge "alt-prereq"))))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.