Skip to content

Commit

Permalink
Sample configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicceboy committed Jul 7, 2024
1 parent 69310eb commit be4cd12
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 1 deletion.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ Ideally, we want to have two places for rules for configuring courses and tasks;

* On higher level, there is single configuration file per course. It should be human readable.
* Good candidate is [TOML](https://toml.io/en/) - human readable and easy to parse with computers (unambiguously maps to hash table)
* Overall configurations for the whole course (includes at least UUIDv7 identifier, short description, single secret and section of custom key-value pairs )
* Overall configurations for the whole course (includes at least UUIDv7 identifier, short description, section of custom key-value pairs )
* Course might have secret values, which are used to generate flags. These should be stored elsewhere. Identifier to each secret could be marked in the configuration file, and the secret is stored in other secure place.
* Secret should be in the flag configuration section
* Configuration for every task
* Directory for the task which is used as context for building the task. Contains build files.
* What kind of build system task requires (Whether Nix Flake package or shell script is being used)
Expand Down Expand Up @@ -241,3 +242,31 @@ src/
- cli.rs
```

## Sample configuration (what it could be, it is not needed to be exactly like this, modify this if changed!)

See [course.toml](course.toml) as an example.

General, when reading the configuration file, the reader should validate the syntax that necessary fields for each components are there. Extra, unspecified fields can be noted as warnings and ignored. If the week is defined, it must have tasks with minimal requirements.
Error messages should be clear.

The sample configuration file should be self-descriptive, but here are some highlights below.
No comprehensive if even something more is required.

Especially, as *a major considerable thing*, it is entirely possible that single build might need multiple flags to be embedded at once.
This means that task description that builder receives, can have list of flags to build.
In that case, there is a subtasks definition section, where the flags are linked to correct tasks and correct grading is based on that.


If task is specified for a week, then task must have ID, points and name to be set.
* Task must have build configuration and flag type
* Build types
* nix
* shell
* Overall task configuration must have at least one flag with type and identifier. Identifier must be linked to specific task and there must be flag for every task and no unused flags.

If the task has many subparts but all the flags must be embedded at once during build, then subtasks configuration format is used as seen from the example file.




175 changes: 175 additions & 0 deletions course.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Course Configuration

# UUIDv7
identifier = "01908498-ac98-708d-b886-b6f2747ef785"
name = "Cybersecurity"
description = "A comprehensive course covering various aspects of cybersecurity"
# We likely need to think this further. If some task is changed, this should be changed as well.
version = "0.0.1"

# Weeks Configuration
[[weeks]]
number = 1
theme = "Introduction to Cybersecurity"

[[weeks.tasks]]
# Tasks can be a single whole task or tasks with sub-parts (a, b c)
# As long as identifier is unique on course level, we need to use something which reminds us about the actual task relation
# Overall ID is used as flag prefix. Maybe further obfuscation needed for that but maybe not necessary
# If the task includes subtasks, embed subtask IDs as suffix
id = "task001"
name = "Challenge 1"
description = "Exploit few buffer overflow vulnerabilities"
# Note the float type here
points = 1.0
# Same build can embed many flags at once
# As a result, it is more clear to introduce list here instead of repeating multiple tasks without build
# `id` is used to make order explicit and tie flag into task
# E.g. consider a scenario where we build exploitable binary with many vulnerabilities. We need to build it once.

flags = [
{ type = "user_derived", id = "A" },
{ type = "pure_random", id = "B" },
{ type = "rng_seed", id = "C" }
]
# If subtasks are present, (list not empty) then the "parent" taskid does not have correlating flags

# Raise error if subtasks total points is more than above definition
# We only need subtasks feature here if the same build should embed many flags at once
# For subtasks, think `id` as suffix, appended to base id above
# Overal identifier for Task 1A is then task001A
subtasks = [
{ id = "A", name = "Subpart A", description = "", subpoints = 0.33},
{ id = "B", name = "Subpart B", description = "", subpoints = 0.33},
{ id = "C", name = "Subpart C", description = "", subpoints = 0.34},
]

[weeks.tasks.build]
directory = "tasks/week1/buffer_overflow"
entrypoint = "build.sh"
builder = "shell"

[[weeks.tasks.build.output_files]]
name = "exploitable.bin"
# Resource means that it is provided for the end-user
type = "resource"

[[weeks.tasks.build.output_files]]
name = "vulnerable_server.py"
# Internal use to provide the challenge from cloud, for example
# Might be rare use case
# We might need to design tasks in mind that there is just a single server, but connection variable changes behaviour
type = "internal"

[[weeks.tasks.build.output_files]]
# Specific kind of resource; instruction for the assignment and should be used as it is
# It includes something that is expected to be different for every user doing the tasks, and as so it is needed here
# Probably optionally generate file or as string from the builder
name = "readme.txt"
type = "readme"

[[weeks.tasks.build.output_files]]
# Mechanic to provide embedded metadata for the task descriptions (e.g. Moodle exam), e.g. URL, docker image name
# Something that is expected to be different for every user doing the tasks
# Maybe not needed as "file", rather data returned by the build system
# Should be likely key-value storage, with some predefined keys. Custom keys allowed.
name = "meta.json"
type = "meta"

[[weeks.tasks]]
id = "task002"
name = "Challenge 2"
description = "Previous exploit was trivial. Try harder."
points = 2.0
flags = [
{ type = "pure_random", id = "task002" },
]

[weeks.tasks.build]
directory = "tasks/week1/basic_crypto"
entrypoint = "flake.nix"
builder = "nix"

[[weeks.tasks.build.output_files]]
name = "exploitable.bin"
type = "resource"

[[weeks.tasks.build.output_files]]
name = "vulnerable_server.py"
type = "internal"

[[weeks.tasks.build.output_files]]
# Instruction for the assignment, should be used as it is
name = "readme.txt"
type = "readme"

[[weeks]]
number = 2
theme = "Network Security Fundamentals"

[[weeks.tasks]]
id = "task003"
name = "SQL Injection Attack"
description = "Perform a SQL injection attack on a vulnerable web application"
points = 1.0
flags = [
{ type = "pure_random", id = "task003" },
]

[weeks.tasks.build]
directory = "tasks/week2/sql_injection"
entrypoint = "setup.sh"
builder = "shell"

[[weeks.tasks.build.output_files]]
name = "vulnerable_server.py"
type = "internal"

[[weeks.tasks.build.output_files]]
name = "readme.txt"
type = "readme"

[[weeks.tasks]]

id = "task004"
name = "Network Packet Analysis"
description = "Analyze network packets to identify a security breach"
points = 1.0
flags = [
{ type = "rng_seed", id = "task004" },
]

[weeks.tasks.build]
directory = "tasks/week2/packet_analysis"
entrypoint = "generate_pcap.sh"
builder = "shell"

[[weeks.tasks.build.output_files]]
name = "my_traffic.pcap"
type = "resource"

[[weeks.tasks.build.output_files]]
name = "readme.txt"
type = "readme"

# Flag Types Configuration
# TOML reader must raise an error if selected one is not one of these
[flag_types]
pure_random = { length = 32 }
# Secret is required so that the flag can be deterministic based on the user, but it should not be possible to guess
# Secret in here should be identifier for secret in vault software, instead of storing it directly here...
# Key must be 32 bytes at least, NOTE that in concatenation!
# Too long key has diminishing returns, note that SHA3-256 internal bit rate aka block size is 1088 bits
user_derived = { algorithm = "HMAC_SHA3_256", secret = "6b2c0c4535ea5b7c7f4fc603a738840fce80e0c8e2632f139f1aa9d27f540f15" }
# Rng seed derived from the user and possibly from secret, provided for the build system in case the required answer is something
# which cannot be represented with random-looking flag
rng_seed = { secret = "You must know me to predict the seed of the other users" }


[build]
default_timeout = 300 # seconds

# Build-type specific confs
# If entrypoint is not provided, it is assumed to be the default_filename
nix = { default_filename = "flake.nix" }
shell = { default_filename = "build.sh" }

0 comments on commit be4cd12

Please sign in to comment.