Skip to main content

Attack & Defence

Attack & Defence worlds use organiser-operated checkers. Biterra coordinates rounds and stores checker tokens, service configuration, flags, SLA events, captures, and scores. It does not host or run the service-specific checker code.

The organiser must run every checker on infrastructure that competing teams cannot access. A checker may run on a separate organiser host or in an isolated part of the service environment, but never in a team-controlled container, VM, account, or network segment. The checker knows how to place and retrieve flags and validate its assigned service, then reports the result to the Biterra A/D API.

Operating model​

  1. Set the world type to Attack & Defence in the customer portal world settings.
  2. Open the world admin portal and use the A/D workspaces to set the tick interval.
  3. Create one A/D service per challenge service.
  4. Open Checker API in the world admin and create a world-scoped checker token.
  5. Deploy the biterra CLI, or your own checker, on organiser-controlled infrastructure that can reach each challenge service.
  6. Enrol one checker identity per service/team instance. One organiser process may operate several identities, provided their runtime tokens and assignments remain isolated.

The round coordinator is authoritative for round timing. Checker deployment is independent: an organiser may run separate checker processes or one central checker fleet.

For implementation details, see Writing and running A/D checkers.

Overview and game control​

The Home workspace shows the current game state, active round, round-coordinator health, checker-health totals, and the latest result for every team/service pair. Use it to start, pause, resume, or stop the game and to identify missing, stale, recovering, or faulty checkers. If coordinator state and persisted rounds disagree, an organiser can run the authenticated repair action from Home.

Before starting scoring, confirm that every expected instance has a reachable URL and a recently reporting checker. Starting the game creates the first round; pausing stops new rounds while preserving the current configuration and history.

Services​

A/D services represent the challenge services that can be attacked and checked. Each service has its own scoring values, flag rotation mode, colour, and icon.

The world supplies defaults for attack points, SLA points, placement and retrieval requirements, recovering SLA percentage, defense points, and checker-result grace. A service can override SLA and checker settings; a flag store can override attack and defense points. Resetting an override makes it inherit the current world value again. The effective settings are captured on scoring events and issued generations, so later configuration changes do not rewrite history.

An up checker result earns full SLA when any configured placement and retrieval requirements are satisfied. recovering, and up without required evidence, earns the configured percentage rounded down to a whole point. Other checker failures and not_checked earn zero SLA. A placed generation earns its captured defense value when it leaves the six-generation validity window without being captured.

Create and publish a service before expecting team instances to appear. Use the service placement mode to decide whether new instances share the service's base country or are distributed across available countries.

Flag stores​

Every service has at least one flag store. Creating a service creates its default store automatically. A store represents an independent place or data shape in which the checker puts one flag generation per round. Stores have their own attack and defense points, and a service may publish several stores when a custom checker handles each of them.

SLA is awarded once per service and round, not once per store. When placement is required, every published store must report its current generation as placed. When retrieval is required, the checker must report every previous valid generation returned in its work as retrieved. Retiring a store removes it from future checker work without deleting its history.

Retire a service when it should stop appearing in future rounds but its history must remain. Permanent service deletion is a separate destructive action: the admin modal requires the exact service name or slug and removes the service, stores, generations, checker results, scoring events, instances, and linked score entries. Both service deletion and activity corrections are written to the platform audit log.

Bringing team instances online​

The checker can publish separate addresses when it starts and checks in. Opponents receive attack_url; the owning team receives defend_url, falling back to attack_url; and the checker receives checker_url, also falling back to attack_url. Private checker or defender addresses are never exposed to opponents.

World managers can edit and save the URL as a manual override. A checker may probe a different Docker-local address internally, but it must advertise the address that players can reach.

Team instances are the concrete attack targets shown on the player map. A team can expose several services from one country, but a country cannot belong to two teams in the same world.

To bring an instance online:

  1. Open Checker API → Checker access and create a short-lived enrollment token.
  2. Deploy the biterra CLI or a custom checker beside the service, using the world URL and enrollment token.
  3. Set BITERRA_ATTACK_URL to the player-facing address and enrol the checker for the matching team and service. Custom checkers may also publish checker_url and defend_url.
  4. Let checker startup publish the URL automatically, then use Instances to choose its country and save any manual URL correction.
  5. Start or resume the game so the checker receives an assignment.
  6. Confirm that Instances and Home show a current result instead of missing or stale.

The checker target is checker_url when configured, otherwise attack_url. It must be reachable from the organiser-controlled checker environment.

For CLI configuration, custom API examples, token handling, and retry guidance, see Writing and running A/D checkers.

Rounds​

Rounds are the scoring intervals for an A/D game. Configure the round length while the game is stopped, then start or resume the game from Home. The per-world round coordinator is the only component that advances rounds; ordinary admin, checker, player, and scoreboard reads never create them. The Rounds workspace shows when each interval began, ended, and was finalised, and identifies the active round.

At a round boundary, the next round begins from the persisted previous ended_at, even if the coordinator alarm runs late. Late or retried alarms reconcile every elapsed round idempotently. Pausing truncates and finalises the active round and removes the alarm; resuming creates the next round. Stopping or reaching world end finalises all pending work and stops scheduling.

Checker results normally close at the round end. Configured checker grace extends only the result deadline; it does not delay the next round. After the applicable deadline Biterra finalises the round, rejects later results, and inserts a zero-point not_checked SLA event for every eligible team/service pair that did not report. not_checked is historical scoring state, whereas missing and stale describe live checker health.

Keep checker probe timeouts shorter than the round duration. A checker that cannot fetch and submit work within the interval can become stale or miss scoring opportunities.

Activity and troubleshooting​

The Activity workspace records checker state changes and captured flags. Open a row to inspect its diagnostic message. Diagnostics should explain operational failures without containing flags, tokens, credentials, headers, or sensitive response bodies.

World managers can delete an activity entry from the table. Deleting an SLA or captured-flag entry also removes its associated score entry and deducts any points awarded by that entry. This cannot be undone, so the action requires confirmation.

Deleting a defense award removes that generation's event and linked score. An internal exclusion prevents coordinator repair or alarm retries from recreating that deliberately corrected award. It does not affect SLA and does not prevent later generations from earning their own defense awards.

Use activity together with the Home health table:

  • Missing means no current checker report for the active round.
  • Stale means the checker has not reported for the expected interval.
  • Recovering means the checker submitted recovering, or submitted up without evidence required by the service; it receives the configured partial SLA.
  • Faulty means the checker itself or its functional validation failed.
  • Flag missing means the checker could not retrieve or place the expected flag.
  • Not checked is written during finalisation when no result arrived before the service's grace deadline; it awards zero SLA.

Map Builder​

Use Map Builder to place team/service instances on countries in the player map. Select a country, find the instance, and move it there. Country placement controls where the target appears to players; it does not change the instance URL or checker enrollment.

Flag lifecycle​

Biterra issues a new flag generation for every eligible team, service, and published store when its organiser-owned checker fetches that round's work. The checker places the current flag, may retrieve recently valid previous flags, and reports only the evidence it actually produced. Current and previous flags plus private checker state are available only to the runtime token bound to that team/service checker identity.

A generation remains valid for its source round and the following five generations. Competing teams submit captured flags to Biterra; accepted captures award the attack points captured on the generation and identify the victim, service, store, and source round. Duplicate, expired, own-team, invalid, and inactive-game submissions do not score. A placed generation that leaves the validity window uncaptured may award its captured defense value once.

Browser submission and automated submission use the same scoring service. Team members can create a team-scoped API token from the player A/D API modal, see its plaintext once, and later list or revoke its metadata. The token authenticates player reads and POST /api/ad/v1/player/flags, which accepts batches of up to 100 flags and returns a result for each input index without echoing flag values. Team API tokens cannot access checker, admin, or token-management endpoints.

Flag submission requests are limited to 64 KiB and rate limited per world/team. A 429 response includes code: "rate_limited", retry_after_seconds, and a Retry-After header. Automation should wait for that interval before retrying the whole batch.

Public attack information​

Some services cannot be exploited efficiently without a public identifier for the object containing a flag. For example, the checker may create user alina_schneider, store the flag in that user's private record, and publish { "username": "alina_schneider" } as attack_info. Biterra returns that value to competing teams with the target's store and generation, allowing their exploit to select the intended account or object.

The organiser's custom checker produces attack information when it reports successful placement; competing teams and their exploit scripts consume it through GET /api/ad/v1/player/targets. It is not checker configuration and it is not used for scoring. It may contain public lookup identifiers such as usernames, record IDs, document slugs, or paths. It must never contain the flag, credentials, runtime tokens, private checker state, vulnerability instructions, or sensitive service data.

Attack information is optional. Services whose exploits can discover the relevant object do not need to publish it. Biterra exposes it only for placed generations within the current six-generation validity window. Private checker state, used to retrieve and verify flags later, is stored separately and is never returned to players.

Player API and scoreboard​

Players open Attack & Defence API from the world footer. The modal lets team members create, list, and revoke team API tokens and links to the interactive player OpenAPI reference. API clients send the displayed secret as Authorization: Bearer btr_ads_…; they do not copy a browser session cookie. The reference contains player operations only: every /api/ad/v1/admin/* and /api/ad/v1/checker/* operation, together with their authentication schemes, is excluded.

The player targets endpoint supplies opponent attack_url values, published stores, and public attack information. Teams commonly poll this endpoint from exploit automation, attack each returned target, then submit captured flags in a batch with their team token. Browser users can inspect the same targets and submit individual flags without creating a token.

The A/D scoreboard reports offense, SLA, defense, total, captures, flags lost, rank, service/store breakdowns, and the latest SLA/checker state. It applies the world's anonymity and freeze-time rules. recovering and not_checked remain visible as distinct SLA states so teams can distinguish partial service recovery from a missing checker result.

Monitoring checkers​

Use the world admin A/D workspaces to see:

  • last check-in per service/team
  • current up/down/stale/missing state
  • current expected round
  • latest placement and result time
  • recent SLA and flag capture events

If a row is missing or stale, the service checker is not reporting for the current round. Check its runtime token, network path to Biterra, checker target, probe timeout, and logs before using coordinator repair; repair fixes scheduling state, not a broken checker.