Skip to main content

Application Target

caution

Application Target Challenges are only available on Hosted or Self-Hosted Enterprise CTFd Instances

caution

Application Target Challenges are heavily beta. If your challenge workload does not currently work please reach out to us.

Application Target challenges allow users to deploy a per-account instance of an application. For example if a challenge requires that every participant must have their own instance of a given website, Application Target challenges allow for that. Each Application Target challenge instance can be deployed, redeployed, and accessed by their respective owners. Note that any user with knowledge of the URL/hostname will be able to access the challenge instance.

Defining an Application

Application Target Challenges use a subset of the docker-compose.yml format.

For example, the following is an example of a valid docker-compose.yml file but also a valid application spec for an Application Target challenge:

version: "3.9"
services:
nginx:
image: nginx
ports:
- 80
redis:
image: redis

Ports

Application Targets will take challenges whose ports are defined in the spec and map public URLs to those ports. For example the port 80 specified for nginx will be mapped to a subdomain on chals.io for Hosted CTFd instances.

Ports defined with just a container port are exposed as HTTPS URLs:

ports:
- "80"

If a port needs to be exposed as a raw TCP connection instead, use the host-to-container mapping syntax:

ports:
- "2222:22"

Each container can expose up to 3 TCP ports. Note that regardless of the host port specified on the left-hand side, the actual port exposed to the internet will be random.

Services that are internal to the application should not have any ports listed in the spec.

Port Extension Keys

Application Target challenges support several non-standard Compose extension keys that give you fine-grained control over how each exposed port is presented to competitors. These keys can be placed at the service level alongside ports.

x-protocol

Controls the protocol used for the connection URL shown to the user. Supported values are http, https, and tcp.

services:
app:
image: my-image
ports:
- "2222:22"
x-protocol: tcp

x-connection-info

Allows direct customization of the connection string displayed to the user. Supports the following variables:

  • $ROUTE — the full route URL (used with http protocol)
  • $HOST — the hostname (used with tcp protocol)
  • $PORT — the port number (used with tcp protocol)
services:
app:
image: my-image
ports:
- "2222:22"
x-protocol: tcp
x-connection-info: ssh remote_user@$HOST -p $PORT

x-connection-label

Controls the label displayed before the connection URL.

services:
app:
image: my-image
ports:
- "2222:22"
x-protocol: tcp
x-connection-info: ssh remote_user@$HOST -p $PORT
x-connection-label: "ssh: "

Per-Port Configuration with List Syntax

When a service exposes multiple ports, extension keys can be specified as a list to configure each port individually. The list order corresponds to the order of the ports entries.

services:
app:
image: my-image
ports:
- "8080:80"
- "2222:22"
x-protocol:
- http
- tcp
x-connection-info:
- $ROUTE
- ssh remote_user@$HOST -p $PORT
x-connection-label:
- "http: "
- "ssh: "

Per-User Flags

Application Target challenges support generating a random per-user flag and adding it into the target specification. This allows Application Target challenges to implement a type of cheating detection system where certain instances of flag sharing can be detected.

caution

Keep in mind that it is not possible for CTFd to detect or prevent all forms of cheating. For example, we cannot reliably prevent users from sharing solutions or solving challenges for each other.

To pass the per-user flag to your application target you would provide the $FLAG variable in the environment section of your target specification:

version: "3.9"
services:
nginx:
image: nginx
environment:
- FLAG=$FLAG
ports:
- 80

During deployment of this target the application will receive a unique per-user value for the $FLAG variable which can then be used by the application as the flag for the challenge. This value will be accepted by CTFd as the flag to solve the answer.

Should any user attempt to submit a per-user flag belonging to a different user it will be recorded by CTFd in the Anti-Cheat page in the Admin Panel.

caution

Because the flag is provided to the target as an environment variable, your challenge must not allow competitors to read the environment variables via command execution or by reading /proc/<pid>/environ.

challenge.yml

In order to use application target challenges with the ctfcli challenge.yml format you should set the type to application_target and set the application_spec and application_name fields under the extra section.

For example:

type: application_target

# The extra field provides additional fields for data during the install/sync commands/
# Fields in extra can be used to supply additional information for other challenge types
# For example the follow extra field is for dynamic challenges. To use these following
# extra fields, set the type to "dynamic" and uncomment the "extra" section below
extra:
application_spec: |
version: "3.9"
services:
nginx:
protocol: https
image: nginx
ports:
- "80"
application_name: testing

Was this page helpful?