Skip to content

Polyvor-Labs/Nexus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NEXUS CTF Engine

NEXUS CTF Engine is a Jeopardy-style CTF platform foundation with ARC category gates, relaxed keyboard-first behavioral verification, adaptive scoring, live scoreboard updates, admin monitoring, Docker-based challenge deployment, shared redeem gateways, and dedicated nc runtime instances.

This README reflects the current deployment model:

  • shared nc redeem for checker-style offline challenges
  • dedicated nc runtime instances for real remote services, especially pwn
  • live web services for web exploitation challenges

Core challenge models

1. Static artifact + shared nc redeem

Best for lightweight offline challenges such as forensics, misc, and checker-based reverse or crypto tasks.

How it works:

  • The downloadable artifact stays static in backend/artifacts/...
  • The platform issues a short-lived redeem token
  • The player connects to the shared redeem gateway with nc
  • The gateway validates the recovered answer
  • The gateway returns a time-windowed dynamic NEXUS{...} flag
  • The backend validates that flag as a redeem-style dynamic flag

Use this when the challenge does not need to run a dedicated remote process per team or user.

2. Static artifact + dedicated nc runtime instance

Best for challenges that need a real remote process, such as:

  • pwn
  • reverse tasks with interactive remote checkers
  • crypto tasks with a live socket service
  • any custom TCP service that should actually run in its own container

How it works:

  • The downloadable artifact stays static in backend/artifacts/...
  • The player launches an isolated nc instance from the challenge page
  • The backend builds the instance image automatically if needed
  • The backend starts a private container for that team or user
  • The challenge page shows the host, port, and short-lived instance access token
  • After the player authenticates with the access token, the real challenge process starts
  • The challenge process returns a stable runtime flag bound to that team or user
  • The backend validates that flag as a runtime flag, not as a short TOTP window flag

This is the correct model for pwn.

3. Live web service

Used for web exploitation challenges.

How it works:

  • The platform launches the challenge with a signed short-lived access token
  • The service returns a dynamic flag that matches backend validation

Repository layout

nexus-ctf-engine/
├── backend/
│   ├── app/
│   └── artifacts/
│       ├── reverse/
│       ├── pwn/
│       ├── crypto/
│       ├── forensics/
│       └── misc/
├── challenge_services/
│   ├── redeem_nc/
│   ├── nc_auth_exec/
│   └── web_ssti_notes/
├── frontend/
├── challenge_sdk/
├── docker-compose.yml
└── .env.example

Important runtime pieces:

  • redeem_nc/ -> shared checker-style nc gateway
  • nc_auth_exec/ -> authenticated wrapper that launches the real runtime command after token verification
  • web_ssti_notes/ -> sample live web challenge

Adding a new challenge

A. Shared nc redeem challenge

Use this for checker-style challenges where the player solves locally, then redeems the answer through the shared nc gateway.

  1. Place the downloadable artifact in:
backend/artifacts/<category>/<artifact>.zip
  1. Add a manifest next to it:
backend/artifacts/<category>/<artifact>.json

Example:

{
  "slug": "forensics-150-lost-tabs",
  "category": "forensics",
  "artifact": "forensics/lost-tabs.zip",
  "answer_prompt": "Recovered token from evidence",
  "normalization": "strip",
  "salt": "forensics-demo-v1",
  "accepted_hashes": ["<sha256(salt:normalized_answer)>"],
  "totp_interval": 120
}
  1. Add the challenge metadata in:
backend/app/services/seed.py

When the player requests redeem info, the platform issues a short-lived token and the shared gateway validates the recovered answer.

B. Dedicated nc runtime instance challenge

Use this for real remote services, especially pwn.

The manifest still sits next to the static artifact, but now it contains a service block with kind = "nc_instance".

B1. Real remote binary or script from artifact files

This is the most important mode for pwn and live socket challenges.

Example real pwn manifest:

{
  "slug": "pwn-200-ret2win-mini",
  "category": "pwn",
  "artifact": "pwn/ret2win-mini.zip",
  "service": {
    "kind": "nc_instance",
    "runtime_mode": "artifact_exec",
    "owner_scope": "team",
    "ttl_seconds": 1800,
    "internal_port": 31337,
    "build": {
      "mode": "artifact_exec",
      "dockerfile": "Dockerfile"
    },
    "template_context": "nc_auth_exec",
    "files": ["ret2win-mini.bin"],
    "notes": "Authenticate, then exploit the real remote binary to make win() print the live flag.",
    "env": {
      "SERVICE_NAME": "ret2win-mini",
      "SERVICE_CATEGORY": "pwn",
      "INSTANCE_BANNER": "[NEXUS pwn] ret2win-mini instance online. After authentication, the real vulnerable binary will start.",
      "POST_AUTH_MESSAGE": "Access granted. Spawning the dedicated ret2win-mini process now...",
      "CHALLENGE_COMMAND": "./ret2win-mini.bin"
    }
  }
}

In this mode:

  • the instance is not a redeem checker
  • after token authentication, it starts the real challenge process
  • for pwn, the player exploits that remote process over nc
  • the remote process prints the live flag from the instance environment

B2. Python runtime service from artifact files

artifact_exec also supports Python challenge services.

If a requirements.txt file exists in the same artifact directory, it is automatically included and installed during image build.

Example:

{
  "slug": "crypto-200-xor-clock",
  "category": "crypto",
  "artifact": "crypto/xor-clock.zip",
  "service": {
    "kind": "nc_instance",
    "runtime_mode": "artifact_exec",
    "owner_scope": "team",
    "ttl_seconds": 1800,
    "internal_port": 31337,
    "build": {
      "mode": "artifact_exec",
      "dockerfile": "Dockerfile"
    },
    "template_context": "nc_auth_exec",
    "files": ["xor_clock_service.py"],
    "notes": "This challenge runs a live Python service for your team.",
    "env": {
      "SERVICE_NAME": "xor-clock",
      "SERVICE_CATEGORY": "crypto",
      "INSTANCE_BANNER": "[NEXUS crypto] xor-clock instance online.",
      "POST_AUTH_MESSAGE": "Access granted. Starting the dedicated Python challenge service...",
      "CHALLENGE_COMMAND": "python3 -u xor_clock_service.py"
    }
  }
}

Directory example:

backend/artifacts/crypto/
  xor-clock.zip
  xor-clock.json
  xor_clock_service.py
  requirements.txt

Notes:

  • requirements.txt does not need to be listed in files
  • it is detected automatically if present
  • use python3 -u ... for cleaner interactive nc output

C. Live web challenge

For web challenges, keep the live service in challenge_services/<name>/, add the challenge metadata in seed.py, and use a launch flow that returns a signed access token.


Authoring rules and best practices

For pwn

Use dedicated nc runtime instances.

Recommended pattern:

  • artifact ZIP for download
  • runtime binary beside the manifest
  • service.kind = "nc_instance"
  • build.mode = "artifact_exec"
  • template_context = "nc_auth_exec"
  • CHALLENGE_COMMAND = "./your_binary.bin"

Do not use redeem-style EXPECTED_ANSWER for pwn.

For reverse and crypto

You can choose either:

  • shared nc redeem, if it is just a solved-answer checker
  • dedicated nc runtime instance, if it should run a real interactive service

For forensics and misc

The default recommendation is:

  • static artifact
  • shared nc redeem

Important API endpoints

Authentication and players:

  • POST /api/v1/auth/register
  • POST /api/v1/auth/login

Challenges:

  • GET /api/v1/challenges
  • GET /api/v1/challenges/{id}
  • GET /api/v1/challenges/{id}/download
  • GET /api/v1/challenges/{id}/redeem-info
  • POST /api/v1/challenges/{id}/instance
  • GET /api/v1/challenges/{id}/instance
  • DELETE /api/v1/challenges/{id}/instance
  • GET /api/v1/challenges/{id}/launch-url

Gameplay:

  • POST /api/v1/arc/submit
  • POST /api/v1/biometrics/calibrate
  • POST /api/v1/biometrics/verify
  • POST /api/v1/flag/submit

Scoreboard:

  • GET /api/v1/scoreboard
  • WS /ws/scoreboard

Admin:

  • GET /api/v1/admin/monitoring/overview
  • GET /api/v1/admin/monitoring/users
  • GET /api/v1/admin/monitoring/teams
  • GET /api/v1/admin/monitoring/events
  • POST /api/v1/admin/users/{id}/ban
  • POST /api/v1/admin/users/{id}/unban
  • POST /api/v1/admin/teams/{id}/ban
  • POST /api/v1/admin/teams/{id}/unban

Quick start

cp .env.example .env
docker compose down -v
docker compose up --build

Default local services:

  • Frontend: http://localhost:5173
  • Backend API: http://localhost:8000
  • Swagger: http://localhost:8000/docs
  • Shared nc redeem gateway: nc localhost 2401
  • Web sample challenge: http://localhost:9105

Default admin account:


Behavioral verification

The current build uses a relaxed, keyboard-first behavioral verification model.

Important behavior:

  • typing signals are weighted more heavily than mouse movement
  • behavioral verification is intended as a soft anti-abuse signal, not a harsh punishment mechanism
  • repeated behavioral failures should not immediately auto-ban legitimate users

For local testing, if verification still feels too strict, lower:

BEHAVIORAL_THRESHOLD=0.05

Then rebuild the stack and recalibrate.


Dedicated nc instance requirements

Dedicated nc instance deployment uses the Docker socket from the backend container.

This is already wired in docker-compose.yml:

  • ./challenge_services:/challenge_services
  • /var/run/docker.sock:/var/run/docker.sock

Useful environment variables:

  • INSTANCE_PUBLIC_HOST
  • INSTANCE_NETWORK
  • INSTANCE_PORT_START
  • INSTANCE_PORT_END
  • INSTANCE_ACCESS_TOKEN_TTL_SECONDS
  • CHALLENGE_SERVICE_ROOT

Runtime flag behavior

There are now two flag validation modes:

Shared redeem and web dynamic flags

These remain time-windowed dynamic flags.

Dedicated nc runtime instance flags

These are stable runtime flags bound to the owning team or user and the challenge.

This is important for pwn and long-running runtime solves:

  • the player may need time to exploit the service
  • the flag should not expire just because the time window rolled over
  • anti-sharing still works because the flag is bound to the correct owner and challenge

Demo flow for a dedicated nc challenge

  1. Register a player and team
  2. Complete behavioral calibration
  3. Unlock the category with ARC
  4. Open the challenge page
  5. Download the static artifact
  6. Solve or analyze the artifact locally
  7. Click Launch nc instance
  8. Copy the host, port, and access token
  9. Connect with nc host port
  10. Paste the access token
  11. The real challenge process starts
  12. Trigger the solve condition in the running service
  13. Submit the returned NEXUS{...} runtime flag in the platform

Admin monitoring

This build includes an admin monitoring dashboard at /admin/monitoring.

It provides:

  • recent suspicious security events
  • per-user and per-team 24-hour risk scoring
  • automatic bans for severe token misuse and repeated suspicious bursts
  • manual ban and unban controls for both users and teams

Behavioral verification failures should be treated more gently than hard token misuse.


Troubleshooting

  • If behavioral verification is too strict for local testing, lower BEHAVIORAL_THRESHOLD in .env
  • If a shared redeem token expires, request a new one from the challenge page
  • If a dedicated nc instance fails to launch, confirm Docker is available to the backend and that the Compose network name matches INSTANCE_NETWORK
  • If a Python runtime instance fails to start, check whether the artifact directory contains the required requirements.txt
  • After changing seeded challenges or manifests, use docker compose down -v and rebuild the stack

Summary recommendation by category

  • pwn -> dedicated nc runtime instance with the real binary.
  • reverse -> redeem checker or dedicated runtime instance, depending on whether it needs a live remote service
  • crypto -> redeem checker or dedicated runtime instance, depending on the challenge design
  • forensics -> shared nc redeem by default
  • misc -> shared nc redeem by default
  • web -> live web service

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors