Skip to content

Generate cryptographically unique, less predictable flags per lab #84

@madebygps

Description

@madebygps

Goal

Make every lab instance use flags that are effectively unique and harder to predict, while keeping the learner-facing CTF{...} format.

Current observations

  • setup/flags.py uses one random secrets.token_hex(4) suffix for most challenge flags. That is 32 bits of randomness shared across challenges.
  • Challenge 12 currently uses only the first 4 hex characters, which is 16 bits of randomness.
  • Flag bases such as hidden_files, file_search, and log_analysis reveal the challenge identity.
  • MASTER_SECRET is hard-coded in the repo and is used for completion-token signing through derive_verification_secret.

Proposed direction

Use a per-instance random secret and derive each challenge flag with HMAC-SHA256 or another standard keyed derivation. For example, derive each flag from instance_secret, challenge number, and purpose string, then encode a sufficiently long prefix into CTF{...}. This gives each challenge its own value and avoids a shared suffix pattern.

Questions to answer

  1. Should flags include challenge numbers for supportability, for example CTF{01_<random>}, or should they contain no challenge hint at all?
  2. What entropy target should each flag have? A practical target could be at least 96 or 128 bits per flag.
  3. Should the completion-token signing secret be generated per lab instead of derived from a hard-coded repository constant?
  4. How should test tooling retrieve expected answers without reintroducing predictable flags?

Acceptance criteria

  • Every non-example challenge flag has independent cryptographic randomness.
  • No challenge uses a very short suffix such as 16 bits.
  • Flag values no longer expose challenge names unless we intentionally keep a small challenge number prefix.
  • Verify still stores only hashes for flag checking.
  • Completion-token signing does not rely on a repository hard-coded production secret.
  • The ctf-testing suite still solves flags from the VM artifacts, not from checked-in answer strings.

Links

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestpythonPython-related workquestionFurther information is requested

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions