mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-18 06:24:23 +01:00
3.0.0b1 (#1544)
* CTFd v3 beta * Documentation extracted into its own repo * Fix for dynamic challenge flag submission
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,3 +1,15 @@
|
||||
# 3.0.0b1 / 2020-07-15
|
||||
|
||||
**General**
|
||||
|
||||
- Fix an issue where dynamic challenge solutions could not be submitted
|
||||
|
||||
**Documentation**
|
||||
|
||||
- Documentation has been seperated out into a seperate repo (https://github.com/CTFd/docs).
|
||||
- Documentation hosting has moved from ReadTheDocs to Netlify
|
||||
- Any links in the codebase to help.ctfd.io have been changed to docs.ctfd.io.
|
||||
|
||||
# 3.0.0a2 / 2020-07-09
|
||||
|
||||
**General**
|
||||
|
||||
@@ -26,7 +26,7 @@ from CTFd.utils.migrations import create_database, migrations, stamp_latest_revi
|
||||
from CTFd.utils.sessions import CachingSessionInterface
|
||||
from CTFd.utils.updates import update_check
|
||||
|
||||
__version__ = "3.0.0a2"
|
||||
__version__ = "3.0.0b1"
|
||||
|
||||
|
||||
class CTFdRequest(Request):
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://help.ctfd.io/" target="_blank">
|
||||
<a class="nav-link" href="https://docs.ctfd.io/" target="_blank">
|
||||
<i class="far fa-question-circle"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<form method="POST" autocomplete="off" class="w-100">
|
||||
<h5>Email Content</h5>
|
||||
<small class="form-text text-muted">
|
||||
Customize CTFd emails with <a href="https://help.ctfd.io/configuration/emails/#email-content" target="_blank">predefined variables</a> and custom content
|
||||
Customize CTFd emails with <a href="https://docs.ctfd.io/docs/settings/emails/#email-content" target="_blank">predefined variables</a> and custom content
|
||||
</small>
|
||||
<ul class="nav nav-tabs mt-3" role="tablist">
|
||||
<li class="nav-item active">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://travis-ci.org/CTFd/CTFd)
|
||||
[](https://community.majorleaguecyber.org/)
|
||||
[](https://docs.ctfd.io/en/latest/?badge=latest)
|
||||
[](https://docs.ctfd.io)
|
||||
|
||||
## What is CTFd?
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -1,2 +0,0 @@
|
||||
API
|
||||
===
|
||||
189
docs/conf.py
189
docs/conf.py
@@ -1,189 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = u"CTFd"
|
||||
copyright = u"2020, CTFd LLC"
|
||||
author = u"Kevin Chung"
|
||||
|
||||
# The short X.Y version
|
||||
version = u""
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u"3.0.0a2"
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.imgmath",
|
||||
"sphinx.ext.viewcode",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = "index"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = [u"_build", "Thumbs.db", ".DS_Store"]
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = None
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = "CTFddoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, "CTFd.tex", u"CTFd Documentation", u"Kevin Chung", "manual")
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [(master_doc, "ctfd", u"CTFd Documentation", [author], 1)]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(
|
||||
master_doc,
|
||||
"CTFd",
|
||||
u"CTFd Documentation",
|
||||
author,
|
||||
"CTFd",
|
||||
"A Capture The Flag framework focusing on ease of use and customizability.",
|
||||
"Miscellaneous",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#
|
||||
# epub_uid = ''
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ["search.html"]
|
||||
|
||||
|
||||
# -- Extension configuration -------------------------------------------------
|
||||
|
||||
# -- Options for intersphinx extension ---------------------------------------
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {"https://docs.python.org/": None}
|
||||
|
||||
# -- Options for todo extension ----------------------------------------------
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
@@ -1,151 +0,0 @@
|
||||
Configuration
|
||||
=============
|
||||
|
||||
CTFd provides a number of configuration options which are used to configure server behavior. CTFd makes a distinction between configuration values which can be configured only with server-level access and values which can be configured by those with administrative priveleges on CTFd.
|
||||
|
||||
Server Level Configuration
|
||||
--------------------------
|
||||
Server level configuration can be modified from the ``config.py`` file in CTFd.
|
||||
|
||||
SECRET_KEY
|
||||
~~~~~~~~~~
|
||||
The secret value used to creation sessions and sign strings. This should be set to a random string. In the
|
||||
interest of ease, CTFd will automatically create a secret key file for you. If you wish to add this secret key
|
||||
to your instance you should hard code this value to a random static value.
|
||||
|
||||
You can also remove .ctfd_secret_key from the .gitignore file and commit this file into whatever repository
|
||||
you are using.
|
||||
|
||||
http://flask.pocoo.org/docs/latest/quickstart/#sessions
|
||||
|
||||
|
||||
DATABASE_URL
|
||||
~~~~~~~~~~~~
|
||||
The URI that specifies the username, password, hostname, port, and database of the server
|
||||
used to hold the CTFd database.
|
||||
|
||||
e.g. ``mysql+pymysql://root:<YOUR_PASSWORD_HERE>@localhost/ctfd``
|
||||
|
||||
REDIS_URL
|
||||
~~~~~~~~~
|
||||
The URI to connect to a Redis server.
|
||||
|
||||
e.g. ``redis://user:password@localhost:6379``
|
||||
|
||||
http://pythonhosted.org/Flask-Caching/#configuring-flask-caching
|
||||
|
||||
|
||||
MAILFROM_ADDR
|
||||
~~~~~~~~~~~~~
|
||||
The email address that emails are sent from if not overridden in the configuration panel.
|
||||
|
||||
MAIL_SERVER
|
||||
~~~~~~~~~~~
|
||||
The mail server that emails are sent from if not overriden in the configuration panel.
|
||||
|
||||
MAIL_PORT
|
||||
~~~~~~~~~
|
||||
The mail port that emails are sent from if not overriden in the configuration panel.
|
||||
|
||||
MAIL_USEAUTH
|
||||
~~~~~~~~~~~~
|
||||
Whether or not to use username and password to authenticate to the SMTP server
|
||||
|
||||
MAIL_USERNAME
|
||||
~~~~~~~~~~~~~
|
||||
The username used to authenticate to the SMTP server if MAIL_USEAUTH is defined
|
||||
|
||||
MAIL_PASSWORD
|
||||
~~~~~~~~~~~~~
|
||||
The password used to authenticate to the SMTP server if MAIL_USEAUTH is defined
|
||||
|
||||
MAIL_TLS
|
||||
~~~~~~~~
|
||||
Whether to connect to the SMTP server over TLS
|
||||
|
||||
MAIL_SSL
|
||||
~~~~~~~~
|
||||
Whether to connect to the SMTP server over SSL
|
||||
|
||||
MAILGUN_API_KEY
|
||||
~~~~~~~~~~~~~~~
|
||||
Mailgun API key to send email over Mailgun. As of CTFd v3, Mailgun integration is deprecated. Installations using the Mailgun API should migrate over to SMTP settings.
|
||||
|
||||
MAILGUN_BASE_URL
|
||||
~~~~~~~~~~~~~~~~
|
||||
Mailgun base url to send email over Mailgun. As of CTFd v3, Mailgun integration is deprecated. Installations using the Mailgun API should migrate over to SMTP settings.
|
||||
|
||||
LOG_FOLDER
|
||||
~~~~~~~~~~
|
||||
The location where logs are written. These are the logs for CTFd key submissions, registrations, and logins.
|
||||
The default location is the CTFd/logs folder.
|
||||
|
||||
UPLOAD_PROVIDER
|
||||
~~~~~~~~~~~~~~~
|
||||
Specifies the service that CTFd should use to store files.
|
||||
|
||||
UPLOAD_FOLDER
|
||||
~~~~~~~~~~~~~
|
||||
The location where files are uploaded. The default destination is the CTFd/uploads folder.
|
||||
|
||||
AWS_ACCESS_KEY_ID
|
||||
~~~~~~~~~~~~~~~~~
|
||||
AWS access token used to authenticate to the S3 bucket.
|
||||
|
||||
AWS_SECRET_ACCESS_KEY
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
AWS secret token used to authenticate to the S3 bucket.
|
||||
|
||||
AWS_S3_BUCKET
|
||||
~~~~~~~~~~~~~
|
||||
The unique identifier for your S3 bucket.
|
||||
|
||||
AWS_S3_ENDPOINT_URL
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
A URL pointing to a custom S3 implementation.
|
||||
|
||||
|
||||
REVERSE_PROXY
|
||||
~~~~~~~~~~~~~
|
||||
Specifies whether CTFd is behind a reverse proxy or not. Set to ``True`` if using a reverse proxy like nginx.
|
||||
|
||||
See `Flask documentation <https://werkzeug.palletsprojects.com/en/0.15.x/middleware/proxy_fix/#werkzeug.middleware.proxy_fix.ProxyFix.>`_ for full details.
|
||||
|
||||
.. Tip::
|
||||
You can also specify a comma seperated set of numbers specifying the reverse proxy configuration settings. For example to configure `x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1` specify `1,1,1,1,1`. By setting the value to ``True``, CTFd will default to the above behavior with all proxy settings set to 1.
|
||||
|
||||
TEMPLATES_AUTO_RELOAD
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Specifies whether Flask should check for modifications to templates and reload them automatically.
|
||||
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Automatically disabled to suppress warnings and save memory. You should only enable this if you need it.
|
||||
|
||||
SWAGGER_UI
|
||||
~~~~~~~~~~
|
||||
Enable the Swagger UI endpoint at ``/api/v1/``
|
||||
|
||||
UPDATE_CHECK
|
||||
~~~~~~~~~~~~
|
||||
Specifies whether or not CTFd will check whether or not there is a new version of CTFd
|
||||
|
||||
APPLICATION_ROOT
|
||||
~~~~~~~~~~~~~~~~
|
||||
Specifies what path CTFd is mounted under. It can be used to run CTFd in a subdirectory.
|
||||
Example: /ctfd
|
||||
|
||||
SERVER_SENT_EVENTS
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Specifies whether or not to enable to server-sent events based Notifications system.
|
||||
|
||||
OAUTH_CLIENT_ID
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
OAUTH_CLIENT_SECRET
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
Application Level Configuration
|
||||
-------------------------------
|
||||
@@ -1,86 +0,0 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
Developing on CTFd
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Developing new code for CTFd is easy and fun! CTFd is organized into components which each serve a distinct purpose.
|
||||
|
||||
|
||||
Core Routes/Controllers
|
||||
-----------------------
|
||||
The core routes are identified in blueprints in the main CTFd folder for user facing routes and in the CTFd/admin folder for the admin panel. These core routes are used to display theme content and render the main server response that the user will receive.
|
||||
|
||||
API Routes/Controllers
|
||||
----------------------
|
||||
The API routes are implemented in the ``CTFd/api`` folder as seperate blueprints for each type of resource used in CTFd. Most behavior that manipulates data should be implemented at the API level and seperated by method and resource level. The most common API methods are ``GET``, ``POST``, ``PATCH``, ``DELETE``.
|
||||
|
||||
Models
|
||||
------
|
||||
CTFd makes heavy usage of the SQLAlchemy ORM to access database contents. The core CTFd models are defined here. Plugins are however capable of adding their own models.
|
||||
|
||||
CTFd makes use of ``alembic`` and ``Flask-Migrate`` to perform database migrations between versions.
|
||||
|
||||
Schemas
|
||||
-------
|
||||
Schemas provide an abstraction layer on top of the database models for permissioning and filtering of data. Schemas and the API work together to make distinctions about what data to show users and what data a user can edit.
|
||||
|
||||
Jinja2
|
||||
------
|
||||
Jinja2 is used by the CTFd server to render HTML content with data. In some cases (i.e. JavaScript challenge rendering), Mozilla Nunjucks templates are used as a mostly compatible alternative. Any templates written in Nunjucks must still be compatible with Jinja2.
|
||||
|
||||
JavaScript & CSS
|
||||
----------------
|
||||
JavaScript & CSS are used to style the front end of CTFd.
|
||||
|
||||
|
||||
Linting
|
||||
~~~~~~~
|
||||
|
||||
Python
|
||||
------
|
||||
Python code in CTFd is linted with `flake8` and `black`.
|
||||
|
||||
Javascript & CSS
|
||||
----------------
|
||||
JavaScript and CSS are linted with `prettier`.
|
||||
|
||||
.. Tip::
|
||||
The recommendation is to integrate all linters into your editor as your changes will fail to pass if the lint checks fail. See the ``Makefile`` for ``make lint``
|
||||
|
||||
|
||||
Testing
|
||||
~~~~~~~
|
||||
|
||||
Python
|
||||
------
|
||||
|
||||
Python tests are run using ``pytest`` on Travis. To run the test suite you can run `make test`. By default tests run against sqlite but this can be configured by setting the `TESTING_DATABASE_URL` environment variable.
|
||||
|
||||
CTFd will support both Python 2 and 3 until Python 2's EOL in 2020.
|
||||
|
||||
Tests are run in parallel with ``pytest-xdist`` and each test is run in its own database.
|
||||
|
||||
|
||||
Documentation
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
CTFd's documentation is written using Sphinx and hosted by `Read the Docs <https://readthedocs.org/>`_.
|
||||
|
||||
To build the documentation, you should go into the ``docs`` folder and run `make html`. The content output into the `docs/_build` folder will be the resulting hosted output.
|
||||
|
||||
|
||||
Tips & Tricks
|
||||
~~~~~~~~~~~~~
|
||||
Typically while developing CTFd, developers use the provided ``serve.py`` script or its ``make serve`` wrapper and access CTFd at ``http://localhost:4000``.
|
||||
|
||||
Very often you will need to generate testing data so that you can exercise CTFd's behavior. The included ``populate.py`` script will insert randomized testing data into the CTFd database.
|
||||
|
||||
The ``export.py`` script can be used to create a CTFd export on the command line.
|
||||
|
||||
The ``import.py`` script can be used to load in a CTFd export on the command line.
|
||||
|
||||
If you need to wipe CTFd completely, you should:
|
||||
|
||||
* delete the database (CTFd/ctfd.db by default)
|
||||
* empty the cache. By default it will be stored in the ``.data`` folder if Redis is unavailable
|
||||
* (optional) remove the contents of the `CTFd/uploads` folder
|
||||
@@ -1,111 +0,0 @@
|
||||
Deployment
|
||||
==========
|
||||
|
||||
CTFd is a standard WSGI application so most if not all `Flask documentation`_ on deploying a Flask based application should apply. This page will focus on the recommended ways to deploy CTFd.
|
||||
|
||||
.. Important::
|
||||
Fully managed and maintained CTFd deployments are available at https://ctfd.io.
|
||||
|
||||
Docker
|
||||
------
|
||||
|
||||
CTFd provides automatically generated `Docker images`_ and one of the simplest means of deploying a CTFd instance is to use Docker Compose.
|
||||
|
||||
.. Caution:: While Docker can be a very simple means of deploying CTFd, it can make debugging and receiving support more complicated. Before deploying using Docker, be sure you have a cursory understanding of how Docker works.
|
||||
|
||||
1. Install `Docker`_
|
||||
2. Install `Docker Compose`_
|
||||
3. Clone the CTFd repository with ``git clone https://github.com/CTFd/CTFd.git``
|
||||
4. Modify the ``docker-compose.yml`` file from the repository to specify a ``SECRET_KEY`` environment for the CTFd service. ::
|
||||
|
||||
environment:
|
||||
- SECRET_KEY=<SPECIFY_RANDOM_VALUE>
|
||||
- UPLOAD_FOLDER=/var/uploads
|
||||
- LOG_FOLDER=/var/log/CTFd
|
||||
- DATABASE_URL=mysql+pymysql://root:ctfd@db/ctfd
|
||||
- REDIS_URL=redis://cache:6379
|
||||
- WORKERS=4
|
||||
|
||||
.. Tip::
|
||||
You can also run ``python -c "import os; f=open('.ctfd_secret_key', 'a+'); f.write(os.urandom(64)); f.close()"`` within the CTFd repo to generate a .ctfd_secret_key file.
|
||||
|
||||
5. Run ``docker-compose up``
|
||||
6. You should now be able to access CTFd at http://localhost:8000
|
||||
|
||||
.. Note::
|
||||
The default Docker Compose configuration files do not provide a reverse proxy server or configure SSL/TLS. This is left as an exercise to the reader by design.
|
||||
|
||||
Standard WSGI Deployment
|
||||
------------------------
|
||||
|
||||
As a web application, CTFd has a few dependencies which require installation.
|
||||
|
||||
1. WSGI server
|
||||
2. Database server
|
||||
3. Caching server
|
||||
|
||||
WSGI Server
|
||||
~~~~~~~~~~~
|
||||
|
||||
While CTFd is a standard WSGI application and most WSGI servers (e.g. gunicorn, UWSGI, waitress) will likely suffice, CTFd is most commonly deployed with gunicorn. This is because of its simplicity and reasonable performance. It is installed by default and used by other deployment methods discussed on this page. By default it is configured to use gevent as a worker class.
|
||||
|
||||
|
||||
Database Server
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
CTFd makes use of SQLAlchemy and as such supports a number of SQL databases. The recommended database type is MySQL. CTFd is tested with and has been installed against SQLite, Postgres, and MariaDB.
|
||||
|
||||
By default CTFd will create a SQLite database if no database server has been configured.
|
||||
|
||||
.. Note::
|
||||
CTFd makes use of the JSON data type which your database backend must support.
|
||||
|
||||
.. Note::
|
||||
CTFd is typicaly used with MySQL, MariaDB, or SQLite. Using CTFd with Postgres is uncommon and could be deprecated in any version. Even though Postgres may be part of the CTFd test suite, using Postgres as your database backend is at your own peril. Any issues raised regarding Postgres support will carry the expectation that the issue author write an accompanying pull request to resolve said issue.
|
||||
|
||||
Caching Server
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
CTFd makes heavy use of caching servers to store configuration values, user sessions, and page content. It is important to deploy CTFd with a caching server. The preferred caching server option is Redis.
|
||||
|
||||
By default if no cache server is configured, CTFd will attempt to use the filesystem as a cache and store values in the ``.data`` folder. This type of caching is not very performant thus it is highly recommended that you configure a Redis server.
|
||||
|
||||
Vagrant
|
||||
-------
|
||||
|
||||
CTFd provides a basic Vagrantfile for use with Vagrant. To run using Vagrant run the following commands:
|
||||
|
||||
::
|
||||
|
||||
vagrant up
|
||||
|
||||
Visit http://localhost:8000 where CTFd will be running.
|
||||
|
||||
To access the internal gunicorn terminal session inside Vagrant run:
|
||||
|
||||
::
|
||||
|
||||
vagrant ssh
|
||||
tmux attach ctfd
|
||||
|
||||
.. Note::
|
||||
|
||||
CTFd's Vagrantfile is not commonly used and is only community supported
|
||||
|
||||
Debug Server
|
||||
------------
|
||||
|
||||
The absolute simplest way to deploy CTFd merely involves running `python serve.py` to start Flask's built-in debugging server. This isn't recommended for anything but debugging and should not be used for any kind of load. It is discussed here because the debugging server can make identifying bugs and misconfigurations easier. In addition, development mostly occurs using the debug server.
|
||||
|
||||
.. Important::
|
||||
CTFd makes every effort to be an easy to setup application.
|
||||
However, deploying CTFd for large amounts of users can be difficult.
|
||||
|
||||
Fully managed and maintained CTFd deployments are available at https://ctfd.io. If you're interested in a specialized CTFd deployment with custom features please `contact us <https://ctfd.io/contact/>`_.
|
||||
|
||||
|
||||
.. _Flask documentation: http://flask.pocoo.org/docs/latest/deploying/
|
||||
.. _Docker images: https://hub.docker.com/r/ctfd/ctfd/
|
||||
.. _Docker: https://docs.docker.com/install/
|
||||
.. _Docker Compose: https://docs.docker.com/compose/install/
|
||||
.. _contact us: https://ctfd.io/contact/
|
||||
@@ -1,41 +0,0 @@
|
||||
.. CTFd documentation master file, created by
|
||||
sphinx-quickstart on Tue Apr 9 15:14:45 2019.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
CTFd
|
||||
====
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/CTFd/CTFd/master/CTFd/themes/core/static/img/logo.png
|
||||
:width: 400
|
||||
:alt: CTFd Logo
|
||||
|
||||
CTFd is a Capture The Flag framework focusing on ease of use and customizability.
|
||||
|
||||
CTFd comes with most of the features needed by an event organizer to run a competition or workshop. In addition, if CTFd's feature set is insufficient, CTFd allows for the usage of plugins and themes to control almost every aspect of how it looks and behaves.
|
||||
|
||||
CTFd is used by many different clubs, universities, and companies to host their own Capture The Flags.
|
||||
|
||||
While available as open source, CTFd developers also provide a managed hosting service available at https://ctfd.io/.
|
||||
|
||||
CTFd is written in Python and makes use of the Flask web framework.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
deployment
|
||||
configuration
|
||||
management
|
||||
scoring
|
||||
themes
|
||||
plugins
|
||||
contributing
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
@@ -1,35 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -1,7 +0,0 @@
|
||||
Management
|
||||
==========
|
||||
|
||||
Challenges
|
||||
----------
|
||||
|
||||
The `ctfcli <https://github.com/CTFd/ctfcli>`_ tool can be used to manage challenges and sync them up to a specified CTFd instance via the CTFd API. It can be used as part of a build system or amongst multilpe users collaborating via version control.
|
||||
402
docs/plugins.rst
402
docs/plugins.rst
@@ -1,402 +0,0 @@
|
||||
Plugins
|
||||
=======
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
CTFd features a plugin interface allowing for the modification of CTFd behavior without modifying the core CTFd code. This has a number of benefits over forking and modifying CTFd:
|
||||
|
||||
* Your modifications and plugins can be shared more easily
|
||||
* CTFd can be updated without losing any custom behavior
|
||||
|
||||
The CTFd developers will do their best to not introduce breaking changes but keep in mind that the plugin interface is still under development and could change.
|
||||
|
||||
.. Tip::
|
||||
Official CTFd plugins are available at https://ctfd.io/store. `Contact us <https://ctfd.io/contact/>`_ regarding custom plugins and special projects.
|
||||
|
||||
.. Tip::
|
||||
Community plugins are available at https://github.com/CTFd/plugins.
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
CTFd plugins are implemented as Python modules with some CTFd specific files.
|
||||
|
||||
::
|
||||
|
||||
CTFd
|
||||
└── plugins
|
||||
└── CTFd-plugin
|
||||
├── README.md # README file
|
||||
├── __init__.py # Main code file loaded by CTFd
|
||||
├── requirements.txt # Any requirements that need to be installed
|
||||
└── config.json # Plugin configuration file
|
||||
|
||||
Effectively CTFd will look at every folder in the ``CTFd/plugins`` folder for the ``load()`` function.
|
||||
|
||||
If the ``load()`` function is found, CTFd will call that function with itself (as a Flask app) as a parameter (i.e. ``load(app)``). This is done after CTFd has added all of its internal routes but before CTFd has fully instantiated itself. This allows plugins to modify many aspects of CTFd without having to modify CTFd itself.
|
||||
|
||||
config.json
|
||||
~~~~~~~~~~~
|
||||
|
||||
``config.json`` exists to give plugin developers a way to define attributes about their plugin. It's primary usage within CTFd is to give users a way to access a Configuration or Settings page for the plugin.
|
||||
|
||||
This is an example ``config.json`` file:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"name": "CTFd Plugin",
|
||||
"route": "/admin/custom_plugin_route"
|
||||
}
|
||||
|
||||
This is ultimately rendered to the user with the following template snippet:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
{% if plugins %}
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Plugins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for plugin in plugins %}
|
||||
<li><a href="{{ request.script_root }}{{ plugin.route }}">{{ plugin.name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
config.html
|
||||
~~~~~~~~~~~
|
||||
|
||||
In the past CTFd used a static file known as ``config.html`` which existed to give plugin developers a page that is loaded by the CTFd admin panel. This has been superceded in favor of `config.json` but is still supported for backwards compatability.
|
||||
|
||||
The ``config.html`` file for a plugin is available by CTFd admins at ``/admin/plugins/<plugin-folder-name>``. Thus if ``config.html`` is stored in ``CTFd-S3-plugin``, it would be available at ``/admin/plugins/CTFd-S3-plugin``.
|
||||
|
||||
``config.html`` is loaded as a Jinja template so it has access to all of the same functions and abilities that CTFd exposes to Jinja. Jinja templates are technically also capable of running arbitrary Python code but this is ancillary.
|
||||
|
||||
Adding New Routes
|
||||
-----------------
|
||||
|
||||
Adding new routes in CTFd is effectively just an exercise in writing new Flask routes. Since the plugin itself is passed the entire app, the plugin can leverage the ``app.route`` decorator to add new routes.
|
||||
|
||||
A simple example is as follows:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from flask import render_template
|
||||
|
||||
|
||||
def load(app):
|
||||
@app.route('/faq', methods=['GET'])
|
||||
def view_faq():
|
||||
return render_template('page.html', content="<h1>FAQ Page</h1>")
|
||||
|
||||
Modifying Existing Routes
|
||||
-------------------------
|
||||
|
||||
It is slightly more complicated to override existing routes in CTFd/Flask because it is not strictly supported by Flask. The approach currently used is to modify the ``app.view_functions`` dictionary which contains the mapping of routes to the functions used to handle them.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from flask import render_template
|
||||
|
||||
from CTFd.models import db
|
||||
from CTFd.utils import admins_only, is_admin
|
||||
|
||||
from CTFd import utils
|
||||
|
||||
def load(app):
|
||||
def view_challenges():
|
||||
return render_template('page.html', content="<h1>Challenges are currently closed</h1>")
|
||||
|
||||
# The format used by the view_functions dictionary is blueprint.view_function_name
|
||||
app.view_functions['challenges.challenges_view'] = view_challenges
|
||||
|
||||
If for some reason you wish to add a new method to an existing route you can modify the ``url_map`` as follows:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from werkzeug.routing import Rule
|
||||
|
||||
app.url_map.add(Rule('/challenges', endpoint='challenges.challenges_view', methods=['GET', 'POST']))
|
||||
|
||||
Adding Database Tables
|
||||
----------------------
|
||||
|
||||
Sometimes CTFd doesn't have enough database tables or columns to let you do what you need. In this case you can use a plugin to create a new table and then use the information in the previous two sections to create routes or modify existing routes to access your new table.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from CTFd.models import db
|
||||
|
||||
|
||||
class Avatars(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
team = db.Column(db.Integer, db.ForeignKey('teams.id'))
|
||||
location = db.Column(db.Text)
|
||||
|
||||
def __init__(self, team, location):
|
||||
self.target = team
|
||||
self.location = location
|
||||
|
||||
|
||||
def load(app):
|
||||
app.db.create_all()
|
||||
@app.route('/profile/avatar', methods=['GET', 'POST'])
|
||||
def profile_avatars():
|
||||
raise NotImplementedError
|
||||
|
||||
Replacing Templates
|
||||
-------------------
|
||||
|
||||
In some situations it might make sense for your plugin to replace the logic for a single page template instead of creating an entire theme.
|
||||
|
||||
The ``utils.override_template()`` function allows a plugin to replace the content of a single template within CTFd such that CTFd will use the new content instead of the content in the original file.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from CTFd.utils import override_template
|
||||
import os
|
||||
|
||||
def load(app):
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
template_path = os.path.join(dir_path, 'new-scoreboard.html')
|
||||
override_template('scoreboard.html', open(template_path).read())
|
||||
|
||||
With this code CTFd will use ``new-scoreboard.html`` instead of the ``scoreboard.html`` file it normally would have used.
|
||||
|
||||
|
||||
Registering Assets
|
||||
------------------
|
||||
|
||||
Very often you will want to provide users with static assets (e.g. JS, CSS). Instead of registering handlers for them on your own, you can use the CTFd built in plugin utilities, ``register_plugin_assets_directory`` and ``register_plugin_asset``.
|
||||
|
||||
For example to register an entire assets directory as available to the user:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from CTFd.plugins import register_plugin_assets_directory
|
||||
|
||||
def load(app):
|
||||
# Available at http://ctfd/plugins/test_plugin/assets/
|
||||
register_plugin_assets_directory(app, base_path='/plugins/test_plugin/assets/')
|
||||
|
||||
|
||||
Or to only provide a single file:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from CTFd.plugins import register_plugin_asset
|
||||
|
||||
def load(app):
|
||||
# Available at http://ctfd/plugins/test_plugin/assets/file.js
|
||||
register_plugin_asset(app, asset_path='/plugins/test_plugin/assets/file.js')
|
||||
|
||||
|
||||
Challenge Types
|
||||
---------------
|
||||
|
||||
In CTFd, there is a concept of a type of challenge. Most CTFs only ever provide challenges as a snippet of text alongside some files. CTFd expands upon this and allows developers to create new challenge types which diversify what users will see.
|
||||
|
||||
Ultimately, users will still read some text, and submit some value but CTFd allows you to style and customize this so users can submit data in new ways.
|
||||
|
||||
For example, instead of an input to submit a single flag value, you might require teams to submit multiple flags or you might create some kind of customized UI where teams need to arrange blocks or text in some order.
|
||||
|
||||
The approach used by CTFd here is to give each "type" of challenge an ID and a name.
|
||||
|
||||
.. Tip::
|
||||
You can see how CTFd implements its `default standard challenge here <https://github.com/CTFd/CTFd/blob/master/CTFd/plugins/challenges/__init__.py>`_. You can also see how CTFd implements `dynamic scoring using this feature <https://github.com/CTFd/CTFd/tree/master/CTFd/plugins/dynamic_challenges>`_.
|
||||
|
||||
Each challenge is implemented as a child class of the ``BaseChallenge`` and implements static methods named ``create``, ``read``, ``update``, ``delete``, ``attempt``, ``solve``, and ``fail``.
|
||||
|
||||
When a user attempts to solve a challenge, CTFd will look up the challenge type and then call the ``solve`` method as shown in the following snippet of code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
chal_class = get_chal_class(chal.type)
|
||||
status, message = chal_class.attempt(chal, request)
|
||||
|
||||
if status: # The challenge plugin says the input is right
|
||||
if ctftime() or is_admin():
|
||||
chal_class.solve(team=team, chal=chal, request=request)
|
||||
return jsonify({'status': 1, 'message': message})
|
||||
|
||||
else: # The challenge plugin says the input is wrong
|
||||
if ctftime() or is_admin():
|
||||
chal_class.fail(team=team, chal=chal, request=request)
|
||||
|
||||
This structure allows each Challenge Type to dictate how they are attempted, solved, and marked incorrect.
|
||||
|
||||
The Challenge Type also dictates the database table that it uses to store data. By default this uses the ``type`` column as a ``polymorphic_identity`` to implement `table inheritance <http://docs.sqlalchemy.org/en/latest/orm/inheritance.html#joined-table-inheritance>`_. Effectively each child table will use the Challenges table as a parent. The child table can add whatever columns it wishes but still leverage the existing columns from the parent.
|
||||
|
||||
We can see in the following code that the polymorphic_identity is specified to be ``dynamic`` as well as the ``type`` parameter. We can also see the call to ``create_all()`` which will create the table in our database.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class DynamicChallenge(Challenges):
|
||||
__mapper_args__ = {'polymorphic_identity': 'dynamic'}
|
||||
id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True)
|
||||
initial = db.Column(db.Integer)
|
||||
minimum = db.Column(db.Integer)
|
||||
decay = db.Column(db.Integer)
|
||||
|
||||
def __init__(self, name, description, value, category, type='dynamic', minimum=1, decay=50):
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.value = value
|
||||
self.initial = value
|
||||
self.category = category
|
||||
self.type = type
|
||||
self.minimum = minimum
|
||||
self.decay = decay
|
||||
|
||||
|
||||
def load(app):
|
||||
app.db.create_all()
|
||||
CHALLENGE_CLASSES['dynamic'] = DynamicValueChallenge
|
||||
register_plugin_assets_directory(app, base_path='/plugins/DynamicValueChallenge/assets/')
|
||||
|
||||
This code creates the necessary tables for the Challenge Type plugin which should be used in addition to the staticmethods used to define the challenge's behavior.
|
||||
|
||||
Every challenge type must be added to the global dictionary that specifies all challenge types:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
CHALLENGE_CLASSES = {
|
||||
"standard": CTFdStandardChallenge
|
||||
}
|
||||
|
||||
|
||||
def get_chal_class(class_id):
|
||||
cls = CHALLENGE_CLASSES.get(class_id)
|
||||
if cls is None:
|
||||
raise KeyError
|
||||
return cls
|
||||
|
||||
The `Standard Challenge type <https://github.com/CTFd/CTFd/tree/master/CTFd/plugins/challenges>`_ provided within CTFd can be used as a base from which to build additional Challenge Type plugins.
|
||||
|
||||
Once new challenges are registered, CTFd will provide a dropdown allowing you to choose from all the challenge types you can create.
|
||||
|
||||
Each Challenge Type contains templates and scripts dictionaries which contain the routes for HTML and JS files needed for the operation of the modals used to create and update the challenges.
|
||||
|
||||
**These routes are not automatically defined by CTFd.**
|
||||
|
||||
Each challenge type plugin specifies the location of their own templates and scripts. An example is the built in `standard challenge type plugin <https://github.com/CTFd/CTFd/blob/master/CTFd/plugins/challenges/__init__.py>`_. It specifies the URLs that the assets are located at for the user's browser to load:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
templates = { # Templates used for each aspect of challenge editing & viewing
|
||||
'create': '/plugins/challenges/assets/create.html',
|
||||
'update': '/plugins/challenges/assets/update.html',
|
||||
'view': '/plugins/challenges/assets/view.html',
|
||||
}
|
||||
scripts = { # Scripts that are loaded when a template is loaded
|
||||
'create': '/plugins/challenges/assets/create.js',
|
||||
'update': '/plugins/challenges/assets/update.js',
|
||||
'view': '/plugins/challenges/assets/view.js',
|
||||
}
|
||||
|
||||
These files are registered with Flask with the following code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from CTFd.plugins import register_plugin_assets_directory
|
||||
|
||||
def load(app):
|
||||
register_plugin_assets_directory(app, base_path='/plugins/challenges/assets/')
|
||||
|
||||
|
||||
The aforementioned code handles the Python logic around new challenges but in order to fully integrate with CTFd you will need to create new Nunjucks templates to give admins/teams the ability to modify/update/solve your challenge. The `templates used by the Standard Challenge Type <https://github.com/CTFd/CTFd/tree/master/CTFd/plugins/challenges/assets>`_ should serve as examples.
|
||||
|
||||
Flag Types
|
||||
----------
|
||||
|
||||
Flag types conversely are used to give developers a way to allow teams to submit flags which do not conform to a hardcoded string or a regex-able value.
|
||||
|
||||
The approach is very similar to Challenges with a base Flag/Key class and a global dictionary specifying all the Flag/Key types:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class BaseFlag(object):
|
||||
name = None
|
||||
templates = {}
|
||||
|
||||
@staticmethod
|
||||
def compare(self, saved, provided):
|
||||
return True
|
||||
|
||||
|
||||
class CTFdStaticFlag(BaseFlag):
|
||||
name = "static"
|
||||
templates = { # Nunjucks templates used for key editing & viewing
|
||||
"create": "/plugins/flags/assets/static/create.html",
|
||||
"update": "/plugins/flags/assets/static/edit.html",
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def compare(chal_key_obj, provided):
|
||||
saved = chal_key_obj.content
|
||||
data = chal_key_obj.data
|
||||
|
||||
if len(saved) != len(provided):
|
||||
return False
|
||||
result = 0
|
||||
|
||||
if data == "case_insensitive":
|
||||
for x, y in zip(saved.lower(), provided.lower()):
|
||||
result |= ord(x) ^ ord(y)
|
||||
else:
|
||||
for x, y in zip(saved, provided):
|
||||
result |= ord(x) ^ ord(y)
|
||||
return result == 0
|
||||
|
||||
|
||||
class CTFdRegexFlag(BaseFlag):
|
||||
name = "regex"
|
||||
templates = { # Nunjucks templates used for key editing & viewing
|
||||
"create": "/plugins/flags/assets/regex/create.html",
|
||||
"update": "/plugins/flags/assets/regex/edit.html",
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def compare(chal_key_obj, provided):
|
||||
saved = chal_key_obj.content
|
||||
data = chal_key_obj.data
|
||||
|
||||
if data == "case_insensitive":
|
||||
res = re.match(saved, provided, re.IGNORECASE)
|
||||
else:
|
||||
res = re.match(saved, provided)
|
||||
|
||||
return res and res.group() == provided
|
||||
|
||||
|
||||
FLAG_CLASSES = {"static": CTFdStaticFlag, "regex": CTFdRegexFlag}
|
||||
|
||||
|
||||
def get_flag_class(class_id):
|
||||
cls = FLAG_CLASSES.get(class_id)
|
||||
if cls is None:
|
||||
raise KeyError
|
||||
return cls
|
||||
|
||||
When a challenge solution is submitted, the challenge plugin itself is responsible for:
|
||||
|
||||
1. Loading the appropriate Key class using the ``get_flag_class()`` function.
|
||||
2. Properly calling the static ``compare()`` method defined by each Flag class.
|
||||
3. Returning the correctness boolean and the message displayed to the user.
|
||||
|
||||
This is properly implemented by the following code `copied from the default standard challenge <https://github.com/CTFd/CTFd/blob/master/CTFd/plugins/challenges/__init__.py#L136>`_:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@staticmethod
|
||||
def attempt(challenge, request):
|
||||
data = request.form or request.get_json()
|
||||
submission = data['submission'].strip()
|
||||
flags = Flags.query.filter_by(challenge_id=challenge.id).all()
|
||||
for flag in flags:
|
||||
if get_flag_class(flag.type).compare(flag, submission):
|
||||
return True, 'Correct'
|
||||
return False, 'Incorrect'
|
||||
@@ -1,40 +0,0 @@
|
||||
Scoring
|
||||
=======
|
||||
|
||||
Scoring is central to any CTF. CTFd automatically generates a scoreboard that automatically resolves ties and supports score freezing. CTFd supports two models which can alter the score of a user or team.
|
||||
|
||||
Solves
|
||||
------
|
||||
Solves are what mark a challenge as solved. Solves do not carry a value and defer to the value of their respective Challenge.
|
||||
|
||||
Awards
|
||||
------
|
||||
Awards have a value defined by their creator (usually an admin). They can be used to give a user/team arbitrary (positive or negative) points.
|
||||
|
||||
Tie Breaks
|
||||
----------
|
||||
In CTFd, tie breaks are essentially resolved by time. If two teams have the same score, the team with the lower solve ID in the database will be considered on top. For example Team X and Team Y solve the same challenge five minutes apart and both now have 100 points.
|
||||
|
||||
Team X will have a Solve ID of 1 for their submission and Team Y will have a Solve ID of 2 for their submission.
|
||||
|
||||
Thus Team X will be considered the tie winner.
|
||||
|
||||
Formats
|
||||
-------
|
||||
|
||||
MajorLeagueCyber
|
||||
~~~~~~~~~~~~~~~~
|
||||
MajorLeagueCyber (MLC) is a cyber security event tracker designed and maintained by the developers of CTFd. It provides polling of the CTFd API and can record and aggregate scores between competitions/events. It supports parsing and processing of CTFd's built in scoreboard API format.
|
||||
|
||||
To register your event with MLC:
|
||||
|
||||
1. Register an account at https://www.majorleaguecyber.org/ if you don't already have one.
|
||||
2. Create a new event.
|
||||
3. Edit the event and add the API Scoreboard URL under the Integrations section. For CTFd you should enter ``https://[CTFd Instance URL]/api/v1/scoreboard``
|
||||
4. Access the JSON scoreboard API from MajorLeagueCyber by going to ``https://www.majorleaguecyber.org/events/[EVENT_ID]/[EVENT_NAME]/scoreboard.json``
|
||||
|
||||
CTFTime
|
||||
~~~~~~~
|
||||
In prior versions CTFd supported a CTFTime compatible scoreboard. This is no longer directly supported because the CTFTime scoreboard format is inherently limiting. However, MLC allows for the polling of any JSON scoreboard API and can translate to the CTFTime scoreboard format.
|
||||
|
||||
After registering your event on MLC you can access the legacy scoreboard format by going to ``https://www.majorleaguecyber.org/events/[EVENT_ID]/[EVENT_NAME]/scoreboard.json?format=legacy``.
|
||||
@@ -1,10 +0,0 @@
|
||||
Themes
|
||||
======
|
||||
|
||||
CTFds allows organizers to customize their CTFd instance with custom themes. The CTFd core routes will load templates from the theme folder specified by the theme configuration value. This value can be configured in the admin panel.
|
||||
|
||||
.. Tip::
|
||||
Official CTFd themes are available at https://ctfd.io/store. `Contact us <https://ctfd.io/contact/>`_ regarding custom themes and special projects.
|
||||
|
||||
.. Tip::
|
||||
Community themes are available at https://github.com/CTFd/themes.
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ctfd",
|
||||
"version": "3.0.0a2",
|
||||
"version": "3.0.0b1",
|
||||
"description": "CTFd is a Capture The Flag framework focusing on ease of use and customizability. It comes with everything you need to run a CTF and it's easy to customize with plugins and themes.",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
|
||||
Reference in New Issue
Block a user